LangChain SQLDatabaseChain vs DataSpoc Lens: Qual é Melhor para Queries de Dados?
O SQLDatabaseChain do LangChain foi uma das primeiras ferramentas que permitiram LLMs consultarem bancos de dados. O DataSpoc Lens usa uma abordagem diferente: um motor de query construído especificamente para Parquet na nuvem. Ambos permitem fazer perguntas em linguagem natural sobre dados. Eles resolvem o problema de formas muito diferentes.
Este post coloca os dois lado a lado com código real, e depois dá um veredito.
O Setup: LangChain SQLDatabaseChain
LangChain precisa de uma conexão com banco de dados, um LLM e uma chain que os conecta:
pip install langchain langchain-openai langchain-community sqlalchemy psycopg2-binaryfrom langchain_community.utilities import SQLDatabasefrom langchain_openai import ChatOpenAIfrom langchain.chains import create_sql_query_chainfrom langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
# 1. Connect to your databasedb = SQLDatabase.from_uri( "postgresql://user:password@host:5432/analytics", include_tables=["orders", "customers", "products"], # limit scope sample_rows_in_table_info=3, # include sample rows in schema prompt)
# 2. Create LLMllm = ChatOpenAI(model="gpt-4o", temperature=0)
# 3. Create the chainquery_chain = create_sql_query_chain(llm, db)execute_tool = QuerySQLDataBaseTool(db=db)
# 4. Ask a questionsql = query_chain.invoke({"question": "What were total sales by region last quarter?"})print(f"Generated SQL: {sql}")
result = execute_tool.invoke(sql)print(f"Result: {result}")Isso funciona, mas note o que você precisa: uma instância PostgreSQL rodando, credenciais no seu código, acesso de rede ao banco de dados e o driver SQLAlchemy correto instalado.
O Setup: DataSpoc Lens
O Lens conecta diretamente a arquivos Parquet no seu bucket na nuvem:
pip install dataspoc-lensfrom dataspoc_lens import LensClient
lens = LensClient() # reads config from ~/.dataspoc/config.yaml or env vars
# List what's availableprint(lens.tables())# ['raw_orders', 'raw_customers', 'curated_sales', 'gold_revenue']
# Ask a question (natural language → SQL → execute → result)answer = lens.ask("What were total sales by region last quarter?")print(answer)
# Or write SQL directlydf = lens.query(""" SELECT region, SUM(amount) as total_sales FROM curated_sales WHERE sale_date >= '2026-01-01' GROUP BY region ORDER BY total_sales DESC""")print(df)Sem servidor de banco de dados. Sem credenciais no código. Sem SQLAlchemy. Os dados vivem como arquivos Parquet em S3/GCS/Azure, e o Lens os lê com DuckDB.
Lado a Lado: As Mesmas 5 Tarefas
Tarefa 1: Listar Tabelas Disponíveis
# LangChainprint(db.get_usable_table_names())# Requires active DB connection
# DataSpoc Lensprint(lens.tables())# Reads from bucket manifest — no database neededTarefa 2: Explorar um Schema
# LangChainprint(db.get_table_info(table_names=["orders"]))# Returns CREATE TABLE + sample rows (sent to LLM as context)
# DataSpoc Lensprint(lens.schema("raw_orders"))# Returns column names and types as a dictTarefa 3: Query em Linguagem Natural
# LangChainchain = create_sql_query_chain(llm, db)sql = chain.invoke({"question": "Top 5 customers by lifetime value"})result = execute_tool.invoke(sql)
# DataSpoc Lensanswer = lens.ask("Top 5 customers by lifetime value")Tarefa 4: SQL Direto
# LangChainresult = db.run("SELECT customer_id, SUM(amount) FROM orders GROUP BY 1 ORDER BY 2 DESC LIMIT 5")
# DataSpoc Lensdf = lens.query("SELECT customer_id, SUM(amount) FROM raw_orders GROUP BY 1 ORDER BY 2 DESC LIMIT 5")# Returns a pandas DataFrame, not a stringTarefa 5: Usar com um Agente de IA
# LangChain — define as a toolfrom langchain.agents import create_openai_tools_agent, AgentExecutorfrom langchain.tools import Tool
tools = [ Tool(name="query_db", func=execute_tool.invoke, description="Run SQL"), Tool(name="list_tables", func=db.get_usable_table_names, description="List tables"),]agent = create_openai_tools_agent(llm, tools, prompt)executor = AgentExecutor(agent=agent, tools=tools)executor.invoke({"input": "Analyze sales trends"})
# DataSpoc Lens — native MCP server# No code needed. Just configure the MCP server:# dataspoc-lens mcp# Any MCP-compatible agent (Claude, Cursor, etc.) connects directly.Matriz de Comparação
| Critério | LangChain SQLDatabaseChain | DataSpoc Lens |
|---|---|---|
| Fonte de dados | Qualquer banco SQL (Postgres, MySQL, etc.) | Parquet em S3/GCS/Azure |
| Infraestrutura | Banco de dados rodando + acesso de rede | Apenas bucket na nuvem |
| Credenciais | String de conexão com user/password | Cloud IAM (sem secrets) |
| Motor de query | Motor do próprio banco | DuckDB (in-process) |
| Linguagem natural | LLM gera SQL via chain | lens.ask() integrado |
| Integração com agentes | Agents/tools LangChain | Servidor MCP (qualquer cliente) |
| Tipo de retorno | String | pandas DataFrame |
| Cache | Nenhum integrado | lens.cache_status(), lens.cache_refresh() |
| Tempo de setup | 10-30 minutos | 2 minutos |
| Custo | Compute do banco + tokens LLM | Apenas tokens LLM |
| Segurança de escrita | Pode executar INSERT/UPDATE/DELETE | Somente leitura por design |
Onde LangChain Ganha
A SQL chain do LangChain é a escolha certa quando:
-
Seus dados vivem em um banco de dados tradicional. Se está em Postgres, MySQL ou Snowflake e você não quer movê-los, LangChain conecta diretamente.
-
Você precisa de JOINs entre múltiplos bancos. LangChain pode conectar a múltiplos bancos através de diferentes chains.
-
Você já está no ecossistema LangChain. Se sua aplicação usa LangChain para outras coisas (recuperação de documentos, memória de chat, orquestração de ferramentas), adicionar SQLDatabaseChain é natural.
# LangChain excels at ad-hoc DB accessfrom langchain_community.utilities import SQLDatabase
# Connect to your production read replicadb = SQLDatabase.from_uri("postgresql://readonly:pass@replica:5432/prod")Onde DataSpoc Lens Ganha
Lens é a escolha certa quando:
-
Seus dados estão em um lake (Parquet em S3/GCS/Azure). Lens é construído especificamente para isso. Sem banco de dados para gerenciar.
-
Você quer zero infraestrutura. Sem servidor de banco, sem connection pooling, sem read replicas. DuckDB roda in-process.
-
Você precisa de acesso nativo para agentes. O servidor MCP significa que qualquer cliente MCP (Claude Code, Cursor, agentes customizados) conecta sem escrever código wrapper.
-
Segurança importa. Cloud IAM controla o acesso. Sem credenciais de banco para gerenciar ou vazar. Somente leitura por design.
# Lens excels at data lake accessfrom dataspoc_lens import LensClient
lens = LensClient()# Data comes from Parquet in your bucket — no DB neededdf = lens.query("SELECT * FROM curated_sales WHERE region = 'EMEA' LIMIT 100")Híbrido: Use Ambos
Se você tem dados tanto em um banco quanto em um lake, pode usar ambos no mesmo agente:
import jsonfrom openai import OpenAIfrom langchain_community.utilities import SQLDatabasefrom dataspoc_lens import LensClient
openai_client = OpenAI()db = SQLDatabase.from_uri("postgresql://readonly:pass@host:5432/app")lens = LensClient()
TOOLS = [ { "type": "function", "function": { "name": "query_app_db", "description": "Query the application database (users, sessions, settings).", "parameters": { "type": "object", "properties": {"sql": {"type": "string"}}, "required": ["sql"], }, }, }, { "type": "function", "function": { "name": "query_data_lake", "description": "Query the data lake (sales, events, analytics).", "parameters": { "type": "object", "properties": {"sql": {"type": "string"}}, "required": ["sql"], }, }, },]
def dispatch(name, args): if name == "query_app_db": return db.run(args["sql"]) elif name == "query_data_lake": df = lens.query(args["sql"]) return df.to_json(orient="records")O Veredito
Use LangChain SQLDatabaseChain quando seus dados estão em um banco de dados tradicional e você está construindo uma aplicação LangChain.
Use DataSpoc Lens quando seus dados estão em um data lake na nuvem (arquivos Parquet), você quer zero infraestrutura, ou precisa de acesso MCP nativo para agentes.
Use ambos quando seus dados abrangem bancos de dados e lakes. Deixe o LLM decidir qual ferramenta chamar baseado na pergunta.
O verdadeiro insight: a ferramenta importa menos que a arquitetura de dados. Se seus dados já estão em Parquet em um bucket na nuvem (e deveriam estar para analytics), o Lens dá o caminho mais simples da pergunta à resposta.