Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O driver mssql-python fornece métodos de busca Apache Arrow para recuperação de dados colunares de alto desempenho a partir do Microsoft SQL e do Banco de Dados SQL do Azure.
Apache Arrow é uma plataforma de desenvolvimento multi-linguagens para dados colunares em memória. O driver converte conjuntos de resultados ODBC diretamente para o formato Arrow em C++, ignorando a criação de objetos em Python para melhorar o desempenho.
A integração com seta possibilita:
- Transferência de dados sem cópia para Polars, pandas e DuckDB. "Zero-copy" significa que os dados permanecem em um único buffer na memória, que o driver grava e as bibliotecas consumidoras leem diretamente, de modo que nenhuma linha é duplicada para objetos Python intermediários.
- Transmitir conjuntos de resultados via
RecordBatchReadersem carregar tudo na memória. - Formato de dados colunar ideal para cargas de análise e aprendizado de máquina.
- Uso de memória reduzido em comparação à criação de objetos Python linha por linha.
Métodos de cursor
O pyarrow pacote é obrigado a usar métodos de busca Arrow. Instale-o com pip install pyarrow. Se pyarrow não estiver instalado, chamar qualquer método Arrow gera um ImportError.
O driver mssql-python adiciona três métodos ao objeto cursor para acesso a dados do Arrow. Os três métodos convertem conjuntos de resultados ODBC para o formato Arrow na camada C++ do driver, o que evita criar objetos Python intermediários.
-
arrow()retorna todo o conjunto de resultados como uma única tabela em memória. O mais simples de usar. -
arrow_batch()retorna um lote de linhas por vez, permitindo controle manual do loop. -
arrow_reader()retorna um iterador que gera lotes automaticamente. Ideal para transmitir grandes volumes de resultados.
Usando cursor.arrow(batch_size=8192)
Obtenha todo o conjunto de resultados como um único pyarrow.Table. Esse método é o mais simples e funciona bem quando o conjunto completo de resultados cabe na memória.
import mssql_python
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product")
table = cursor.arrow()
print(type(table)) # <class 'pyarrow.lib.Table'>
print(table.num_rows) # Number of rows fetched
print(table.num_columns) # Number of columns
print(table.schema) # Column names and Arrow types
print(table.to_pandas()) # Convert to pandas DataFrame
Note
Se a sua cadeia de conexão usa Authentication=ActiveDirectoryDefault, o driver usa DefaultAzureCredential, que tenta vários provedores de credenciais em sequência. A primeira conexão pode ser lenta porque o SDK percorre a cadeia até encontrar um provedor funcionando. Em produção, se você sabe qual tipo de credencial seu ambiente usa, especifique-o diretamente (por exemplo, ActiveDirectoryMSI para identidade gerenciada) para evitar a caminhada em cadeia. Para obter mais informações, consulte Autenticação do Microsoft Entra.
Usando cursor.arrow_batch(batch_size=8192)
Busque um único pyarrow.RecordBatch contendo até batch_size linhas. Use esse método para ciclos personalizados de processamento em lote, onde você precisa de controle detalhado sobre quantas linhas são buscadas ao mesmo tempo.
cursor.execute("SELECT * FROM Production.TransactionHistory")
while True:
batch = cursor.arrow_batch(batch_size=10000)
if batch.num_rows == 0:
break
# Process each batch
print(f"Fetched {batch.num_rows} rows")
Usando cursor.arrow_reader(batch_size=8192)
Retorna um pyarrow.RecordBatchReader que produz objetos RecordBatch até esgotar o conjunto de resultados. Esse método é a opção mais eficiente em memória para grandes conjuntos de resultados.
cursor.execute("SELECT * FROM Production.TransactionHistory")
reader = cursor.arrow_reader(batch_size=50000)
for batch in reader:
# Process streaming batches without loading all data
print(f"Batch: {batch.num_rows} rows")
Padrões comuns
As tabelas de seta se integram diretamente com bibliotecas de dados populares em Python. Os exemplos a seguir mostram como passar dados do Arrow para pandas, Polars, DuckDB e formatos de arquivo sem copiar dados.
Carregue os resultados no pandas
cursor.execute("SELECT * FROM Production.Product")
table = cursor.arrow()
# Convert to pandas with zero-copy where possible
df = table.to_pandas()
print(df.head())
Carregar resultados no Polars
import polars as pl
cursor.execute("SELECT * FROM Production.Product")
table = cursor.arrow()
df = pl.from_arrow(table)
print(df)
Resultados da consulta com o DuckDB
O DuckDB pode consultar tabelas de seta diretamente em SQL sem copiar dados. Essa funcionalidade é útil quando você precisa de análise no estilo SQL em conjuntos de resultados que já estão no formato Arrow.
import duckdb
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
arrow_table = cursor.arrow()
# Query the Arrow table with DuckDB SQL
result = duckdb.sql("SELECT CustomerID, SUM(TotalDue) FROM arrow_table GROUP BY CustomerID")
print(result.fetchall())
Faça streaming de grandes conjuntos de resultados em Parquet
Para conjuntos de resultados grandes, transmita lotes do Arrow diretamente para um arquivo Parquet sem carregar todo o conjunto de dados na memória. O ParquetWriter grava cada lote incrementalmente.
import pyarrow.parquet as pq
cursor.execute("SELECT * FROM Production.TransactionHistory")
reader = cursor.arrow_reader(batch_size=100000)
# Write streaming batches to a Parquet file
writer = None
for batch in reader:
if writer is None:
writer = pq.ParquetWriter("output.parquet", batch.schema)
writer.write_batch(batch)
if writer:
writer.close()
Exportação para outros formatos
O PyArrow fornece gravadores integrados para CSV e o formato de arquivo IPC Arrow (também conhecido como Feather V2). Arquivos Arrow IPC preservam exatamente os tipos Arrow e são rápidos de ler novamente.
import pyarrow as pa
import pyarrow.csv as pcsv
cursor.execute("SELECT * FROM Production.Product")
table = cursor.arrow()
# Write to CSV
pcsv.write_csv(table, "products.csv")
# Write to an Arrow IPC file
with pa.ipc.new_file("products.arrow", table.schema) as writer:
writer.write_table(table)
Mapeamentos de tipo de dados
Os métodos de busca do Arrow mapeiam os tipos SQL da Microsoft para tipos do Arrow no nível de C++.
| Tipo SQL do Microsoft | Tipo de seta |
|---|---|
| int, smallint, tinyint, bigint |
int32, int16, int8, int64 |
| ponto flutuante, real |
float64, float32 |
| decimal, numérico | decimal128 |
| bit | bool |
| char, varchar, nchar, nvarchar | utf8 |
| texto, ntext | large_utf8 |
| binário, varbinário |
binary, large_binary |
| date | date32 |
| Tempo | time64[us] |
| datetime, datetime2, smalldatetime | timestamp[us] |
| datetimeoffset | timestamp[us, tz=UTC] |
| uniqueidentifier |
utf8 (corda maiúscula) |
| xml | utf8 |
Note
O driver converte o datetimeoffset tipo para UTC porque as colunas de seta exigem um fuso horário fixo. O driver normaliza informações de fuso horário por célula do Microsoft SQL para UTC durante a conversão.
O sql_variant tipo não é suportado pelos métodos Arrow fetch e gera uma exceção de tipo de dado não suportado. Use o padrão fetchone(), fetchmany(), ou fetchall() para consultas que retornam sql_variant colunas.
Considerações sobre desempenho
Métodos de busca por seta são os mais rápidos para análises e operações de dados em massa, enquanto métodos padrão de cursor são mais adequados para padrões transacionais com conjuntos de resultados pequenos.
Quando usar Arrow em vez do fetch padrão
| Scenario | Abordagem recomendada |
|---|---|
| Busque algumas linhas para exibir | fetchone() / fetchall() |
| Carregar dados no pandas ou no Polars | cursor.arrow() |
| Processar grandes conjuntos de dados em blocos | cursor.arrow_reader() |
| Consultas de uma única linha ou pequenos conjuntos de resultados | fetchone() / fetchval() |
| Pipelines de análise ou de agregação |
cursor.arrow() + Polars/DuckDB |
| Gravar resultados em Parquet ou Arrow IPC |
cursor.arrow_reader() + PyArrow I/O |
Gerenciamento de memória para grandes conjuntos de dados
Para conjuntos de resultados que possam exceder a memória disponível, use arrow_reader() com um razoável batch_size.
cursor.execute("SELECT * FROM Production.TransactionHistory")
# Process in batches of 100K rows
reader = cursor.arrow_reader(batch_size=100000)
total_rows = 0
for batch in reader:
# Work with each batch individually
total_rows += batch.num_rows
# batch goes out of scope and memory is freed
print(f"Processed {total_rows} rows")
Ajustar tamanho do lote
O batch_size parâmetro controla quantas linhas são buscadas em cada lote. O tamanho ideal depende da largura da sua linha e da memória disponível. Linhas mais largas com colunas grandes como nvarchar(max) ou varbinary(max) se beneficiam de tamanhos de lote menores, enquanto fileiras estreitas se beneficiam de tamanhos maiores.
- Padrão (8192): Bom equilíbrio para a maioria das cargas de trabalho.
- Menor (1000-5000): Use para tabelas amplas com colunas largas.
- Maior (50000-100000): Use para tabelas estreitas ou quando a taxa de transferência importa mais do que a memória.
# Narrow table with many rows - use larger batches
cursor.execute("SELECT ProductID, ListPrice FROM Production.Product")
table = cursor.arrow(batch_size=100000)
# Wide table with LOB columns - use smaller batches
cursor.execute("SELECT * FROM Production.Document")
table = cursor.arrow(batch_size=1000)