Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
DuckDB est un moteur d’analyse SQL en cours de processus qui peut interroger directement les tables Apache Arrow sans copier de données. En combinant DuckDB avec le pilote mssql-python, on peut :
- Exécutez des requêtes SQL analytiques sur des jeux de résultats Microsoft SQL sans charger les données dans pandas ou Polars.
- Interrogez des tables Arrow en mémoire sans surcoût de copie.
- Rejoignez les données SQL Microsoft avec des fichiers locaux (CSV, Parquet, JSON) dans une seule requête DuckDB.
- Exportez les données SQL de Microsoft vers Parquet, CSV ou d’autres formats via DuckDB.
Logiciels requis
- Python 3.10 ou version ultérieure.
- Les
mssql-python,duckdbetpyarrowpaquets. Installez tout avecpip install mssql-python duckdb pyarrow. - Installez les prérequis ponctuels spécifiques au système d'exploitation. Les utilisateurs Windows peuvent sauter cette étape. Pour tous les détails sur la plateforme, voir Installer mssql-python.
Créer une base de données SQL
Créer ou connecter une base de données SQL sur l’une des plateformes suivantes :
Les exemples de cet article interrogent la base de données d’exemple AdventureWorks . Si vous ne l’avez pas déjà, consultez les bases de données d’exemple AdventureWorks.
Installer des dépendances
pip install mssql-python duckdb pyarrow
Interroger les données SQL Microsoft avec DuckDB
Le flux de travail de base est : exécuter une requête avec mssql-python, récupérer les résultats sous forme de table de flèches, puis interroger cette table de flèches avec DuckDB SQL.
Motif de base
Commencez par établir une connexion et récupérer les données sous forme de table Arrow.
import duckdb
import mssql_python
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes"
)
cursor = conn.cursor()
# Fetch Microsoft SQL data as Arrow
cursor.execute("SELECT * FROM Production.Product WHERE ListPrice > 0")
products = cursor.arrow()
# Query the Arrow table with DuckDB
result = duckdb.sql("""
SELECT Color, COUNT(*) AS ProductCount, AVG(ListPrice) AS AvgPrice
FROM products
GROUP BY Color
ORDER BY ProductCount DESC
""")
print(result.fetchdf())
DuckDB fait référence à la products table Arrow par son nom de variable Python. Aucune donnée n’est copiée dans le stockage de DuckDB.
Agrégat et filtre
Utilisez le SQL de DuckDB pour regrouper et agréger les données Arrow.
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
# Top customers by total spend
top_customers = duckdb.sql("""
SELECT
CustomerID,
COUNT(*) AS OrderCount,
SUM(TotalDue) AS TotalSpent,
AVG(TotalDue) AS AvgOrderValue
FROM orders
GROUP BY CustomerID
HAVING SUM(TotalDue) > 10000
ORDER BY TotalSpent DESC
LIMIT 20
""")
print(top_customers.fetchdf())
Rejoindre plusieurs résultats Microsoft SQL
Récupérez plusieurs tables depuis Microsoft SQL et rejoignez-les dans DuckDB sans écrire de requête inter-serveurs.
# Fetch two tables
cursor.execute("SELECT * FROM Production.Product")
products = cursor.arrow()
cursor.execute("SELECT * FROM Production.ProductSubcategory")
subcategories = cursor.arrow()
# Join in DuckDB
result = duckdb.sql("""
SELECT
s.Name AS Subcategory,
COUNT(*) AS ProductCount,
ROUND(AVG(p.ListPrice), 2) AS AvgPrice
FROM products p
JOIN subcategories s ON p.ProductSubcategoryID = s.ProductSubcategoryID
GROUP BY s.Name
ORDER BY AvgPrice DESC
""")
print(result.fetchdf())
Relier les données SQL Microsoft avec des fichiers locaux
DuckDB peut lire nativement les fichiers CSV, Parquet et JSON. Combinez les données de SQL Server avec des fichiers locaux dans une seule requête.
Associer avec un fichier CSV
Chargez un fichier CSV et rejoignez-le avec les données de Microsoft SQL.
import csv
from pathlib import Path
cursor.execute("SELECT CustomerID, PersonID FROM Sales.Customer")
customers = cursor.arrow()
csv_path = Path("customer_regions.csv")
with csv_path.open("w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(["CustomerID", "Region", "Segment"])
writer.writerows([
(1, "West", "Premium"),
(2, "East", "Standard"),
(3, "Central", "Basic"),
])
try:
result = duckdb.sql("""
SELECT c.CustomerID, c.PersonID, f.Region, f.Segment
FROM customers c
JOIN read_csv_auto('customer_regions.csv') f ON c.CustomerID = f.CustomerID
""")
print(result.fetchdf())
finally:
csv_path.unlink(missing_ok=True)
Effectuer une jointure avec un fichier Parquet
Chargez un fichier Parquet et rejoignez-le avec les données de Microsoft SQL.
from pathlib import Path
import pyarrow as pa
import pyarrow.parquet as pq
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product")
products = cursor.arrow()
parquet_path = Path("order_history.parquet")
order_history = pa.table({
"ProductID": [1, 2, 680],
"OrderDate": ["2024-06-01", "2024-03-15", "2024-01-10"],
"Quantity": [10, 5, 3],
})
pq.write_table(order_history, parquet_path)
try:
result = duckdb.sql("""
SELECT p.Name, p.ListPrice, h.OrderDate, h.Quantity
FROM products p
JOIN read_parquet('order_history.parquet') h ON p.ProductID = h.ProductID
WHERE h.OrderDate >= '2024-01-01'
""")
print(result.fetchdf())
finally:
parquet_path.unlink(missing_ok=True)
Exporter les données SQL de Microsoft
Utilisez la déclaration de COPY DuckDB pour exporter les données Microsoft SQL vers différents formats de fichiers.
Exporter vers Parquet
Exportez les données vers le format Apache Parquet.
cursor.execute("SELECT * FROM Production.Product")
products = cursor.arrow()
duckdb.sql("COPY products TO 'products.parquet' (FORMAT PARQUET)")
Exporter au format CSV
Exportez les données vers un fichier de valeurs séparées par virgules :
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
duckdb.sql("COPY orders TO 'orders.csv' (FORMAT CSV, HEADER)")
Exporter un fichier Parquet partitionné
Exportez les données vers des fichiers Parquet partitionnés pour l’analyse distribuée :
import shutil
from pathlib import Path
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
output_dir = Path("sales_data")
shutil.rmtree(output_dir, ignore_errors=True)
duckdb.sql("""
COPY (SELECT *, YEAR(OrderDate) AS OrderYear FROM orders)
TO 'sales_data'
(FORMAT PARQUET, PARTITION_BY (OrderYear))
""")
Traiter en flux de grands ensembles de résultats
Pour les grands ensembles de données, utilisez arrow_reader() pour traiter les données en flux sans charger toutes les lignes en mémoire en même temps :
cursor.execute("SELECT * FROM Production.TransactionHistory")
reader = cursor.arrow_reader(batch_size=50000)
# Process each batch with DuckDB
total_rows = 0
for batch in reader:
result = duckdb.sql("""
SELECT ProductID, SUM(ActualCost) AS TotalCost
FROM batch
GROUP BY ProductID
""")
total_rows += batch.num_rows
print(f"Processed {total_rows} rows")
Accumuler les résultats en streaming
Pour agréger sur tous les lots, enregistrez chaque lot dans une connexion DuckDB persistante et accumulez les résultats de manière incrémentale.
cursor.execute("SELECT * FROM Production.TransactionHistory")
reader = cursor.arrow_reader(batch_size=50000)
duck = duckdb.connect()
duck.execute("CREATE TABLE transactions (ProductID INT, ActualCost DOUBLE, Quantity INT)")
for batch in reader:
duck.execute("INSERT INTO transactions SELECT ProductID, ActualCost, Quantity FROM batch")
# Query the accumulated data
result = duck.sql("""
SELECT ProductID, SUM(ActualCost) AS TotalCost, SUM(Quantity) AS TotalQty
FROM transactions
GROUP BY ProductID
ORDER BY TotalCost DESC
LIMIT 10
""")
print(result.fetchdf())
duck.close()
Astuces pour les performances
Laissez Microsoft SQL gérer le gros du travail
Microsoft SQL est plus rapide pour le filtrage, les jointures et les agrégations que de récupérer toutes les données brutes via le fil. Utilisez DuckDB pour l’analyse secondaire des ensembles de résultats déjà récupérés, et non comme un remplacement de l’optimisation des requêtes SQL Server.
# Suboptimal: Pull all rows, filter in DuckDB
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
result = duckdb.sql("SELECT * FROM orders WHERE TotalDue > 1000")
# Better: Filter in Microsoft SQL, analyze in DuckDB
cursor.execute("SELECT * FROM Sales.SalesOrderHeader WHERE TotalDue > 1000")
orders = cursor.arrow()
result = duckdb.sql("SELECT CustomerID, SUM(TotalDue) FROM orders GROUP BY CustomerID")
Utilisez Arrow pour toutes les opérations de lecture
Le transfert basé sur des flèches évite de créer des objets Python intermédiaires, ce qui réduit la consommation de mémoire et améliore le débit. Privilégiez cursor.arrow() plutôt que la conversion manuelle ligne par ligne lors du transfert de données vers DuckDB.
Utilisez le streaming pour de grands ensembles de données
Pour les ensembles de résultats dont la taille dépasse la mémoire disponible, utilisez arrow_reader() avec un paramètre batch_size pour traiter les données de manière incrémentale.