Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
DuckDB is een in-process SQL-analyse-engine die Apache Arrow-tabellen direct kan opvragen zonder data te kopiëren. Door DuckDB te combineren met de mssql-python-driver kun je:
- Voer analytische SQL-queries uit op Microsoft SQL-resultatensets zonder data in pandas of Polars te laden.
- Doorzoek Arrow-tabellen in het geheugen zonder kopieer-overhead.
- Verbind Microsoft SQL-gegevens met lokale bestanden (CSV, Parquet, JSON) in één DuckDB-query.
- Exporteer Microsoft SQL-gegevens naar Parquet, CSV of andere formaten via DuckDB.
Prerequisites
- Python 3.10 of hoger.
- De
mssql-python,duckdb, enpyarrowpakketten. Installeer alles metpip install mssql-python duckdb pyarrow. - Installeer eenmalige vereisten voor het besturingssysteem. Windows-gebruikers kunnen deze stap overslaan. Voor volledige platformdetails, zie Install mssql-python.
Een SQL-database maken
Maak een SQL-database aan of maak verbinding met een van de volgende platforms:
De voorbeelden in dit artikel zoeken de AdventureWorks voorbeelddatabase op. Als je het nog niet hebt, bekijk dan de voorbeelddatabases van AdventureWorks.
Afhankelijkheden installeren
pip install mssql-python duckdb pyarrow
Zoek Microsoft SQL-gegevens op met DuckDB
De basisworkflow is: voer een query uit met mssql-python, haal de resultaten op als een Arrow-tabel, en vraag die Arrow-tabel vervolgens op met DuckDB SQL.
Basispatroon
Begin met het opzetten van een verbinding en het ophalen van gegevens als een Arrow-tabel.
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 verwijst naar de products Arrow-tabel met de Python-variabelenaam. Er worden geen gegevens gekopieerd in de opslag van DuckDB.
Aggregaat en filter
Gebruik de SQL van DuckDB om Arrow-gegevens te groeperen en te aggregeren.
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())
Sluit je aan bij meerdere Microsoft SQL-resultaten
Haal meerdere tabellen op van Microsoft SQL en voeg ze toe in DuckDB zonder een cross-server query te schrijven.
# 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())
Sluit Microsoft SQL-data aan met lokale bestanden
DuckDB kan CSV-, Parquet- en JSON-bestanden rechtstreeks lezen. Combineer SQL Server-gegevens met lokale bestanden in één enkele query.
Samenvoegen met een CSV-bestand
Laad een CSV-bestand en voeg het toe met data van 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)
Sluit aan bij een Parquet-bestand
Laad een Parquet-bestand en voeg het aan met data van 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)
Exporteer Microsoft SQL-gegevens
Gebruik de COPY DuckDB-instructie om Microsoft SQL-gegevens te exporteren naar verschillende bestandsformaten.
Exporteren naar Parquet
Exporteer gegevens naar Apache Parquet-formaat.
cursor.execute("SELECT * FROM Production.Product")
products = cursor.arrow()
duckdb.sql("COPY products TO 'products.parquet' (FORMAT PARQUET)")
Exporteren naar CSV
Exporteer gegevens naar een komma-gescheiden waardenbestand:
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
duckdb.sql("COPY orders TO 'orders.csv' (FORMAT CSV, HEADER)")
Gepartitioneerde Parquet exporteren
Exporteer data naar gepartitioneerde Parquet-bestanden voor gedistribueerde analyse:
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))
""")
Stroom grote resultaatsets
Voor grote datasets kun je het gebruik arrow_reader() gebruiken om data in streamingbatches te verwerken zonder alle rijen tegelijk in het geheugen te laden:
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")
Verzamel streamingresultaten
Om over alle batches te aggregeren, registreer je elke batch in een persistente DuckDB-verbinding en verzamel je successief resultaten.
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()
Tips voor prestaties
Laat Microsoft SQL het zware werk doen
Microsoft SQL is sneller voor filtering, joins en aggregaties dan het ophalen van alle ruwe data via de wire. Gebruik DuckDB voor secundaire analyse van al opgehaalde resultatensets, niet als vervanging voor SQL Server-queryoptimalisatie.
# 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")
Gebruik Arrow voor alle leesbewerkingen
Pijl-gebaseerde overdracht voorkomt het creëren van tussenliggende Python-objecten, wat het geheugengebruik vermindert en de doorvoer verbetert. Geef de voorkeur cursor.arrow() boven handmatige rij-voor-rij conversie bij het doorgeven van data aan DuckDB.
Gebruik streaming voor grote datasets
Gebruik je voor resultaatsets die groter zijn dan het beschikbare geheugen arrow_reader() met een batch_size-parameter om gegevens incrementeel te verwerken.