Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
DuckDB je průběžný SQL analytický engine, který dokáže přímo dotazovat tabulky Apache Arrow bez kopírování dat. Kombinace DuckDB s ovladačem mssql-python vám umožní:
- Spouštět analytické SQL dotazy nad sadami výsledků Microsoft SQL, aniž by bylo nutné načítat data do pandas nebo Polars.
- Dotazujte tabulky Arrow v paměti s nulovou režií kopírování.
- Spojte data Microsoft SQL s lokálními soubory (CSV, Parquet, JSON) v jednom dotazu DuckDB.
- Exportujte data Microsoft SQL do Parquet, CSV nebo jiných formátů přes DuckDB.
Předpoklady
- Python 3.10 nebo novější.
- Balíčky
mssql-python,duckdbapyarrow. Vše nainstalujte pomocípip install mssql-python duckdb pyarrow. - Nainstalujte požadavky specifické pro jednorázový operační systém. Uživatelé Windows mohou tento krok přeskočit. Pro úplné podrobnosti o platformě viz Instalace mssql-python.
Vytvoření databáze SQL
Vytvořte nebo se připojte k SQL databázi na jedné z následujících platforem:
Příklady v tomto článku se dotazují na vzorovou databázi AdventureWorks . Pokud ji ještě nemáte, podívejte se na ukázkové databáze AdventureWorks.
Nainstalujte závislosti
pip install mssql-python duckdb pyarrow
Dotaz na data Microsoft SQL pomocí DuckDB
Základní pracovní postup je: spravit dotaz pomocí mssql-python, načíst výsledky jako tabulku Arrow a poté tuto tabulku Arrow dotazovat pomocí DuckDB SQL.
Základní vzor
Začněte navázáním spojení a načtením dat jako tabulky 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 odkazuje na tabulku products Arrow podle názvu její Python proměnné. Žádná data nejsou kopírována do úložiště DuckDB.
Agregovat a filtrovat
Použijte SQL DuckDB pro seskupování a agregaci dat 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())
Připojte se k více výsledkům Microsoft SQL
Načtěte více tabulek z Microsoft SQL a spojte je do DuckDB bez psaní dotazu napříč servery.
# 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())
Spojte data Microsoft SQL s lokálními soubory
DuckDB umí číst soubory CSV, Parquet a JSON nativně. Spojte data ze SQL Server s lokálními soubory v jednom dotazu.
Sloučit pomocí souboru CSV
Načtěte soubor CSV a spojte jej s daty z 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)
Spojit se souborem Parquet
Načtěte soubor Parquet a spojte jej s daty z 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)
Export dat z Microsoft SQL
Použijte příkaz DuckDB COPY k exportu dat Microsoft SQL do různých formátů souborů.
Exportovat do Parquetu
Exportovat data do formátu Apache Parquet.
cursor.execute("SELECT * FROM Production.Product")
products = cursor.arrow()
duckdb.sql("COPY products TO 'products.parquet' (FORMAT PARQUET)")
Export do CSV
Exportujte data do souboru s hodnotami oddělenými čárkami:
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
duckdb.sql("COPY orders TO 'orders.csv' (FORMAT CSV, HEADER)")
Export děleného souboru Parquet
Exportovat data do rozdělených souborů Parquet pro distribuovanou analytiku:
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))
""")
Streamovat rozsáhlé sady výsledků
U rozsáhlých datových sad použijte arrow_reader() k zpracování dat po dávkách v režimu streamování, aniž by se všechny řádky načítaly do paměti najednou:
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")
Shrnout výsledky streamování
Pro agregaci napříč všemi dávkami registrujte každou dávku do trvalého DuckDB spojení a výsledky akumulujte postupně.
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()
Tipy týkající se výkonu
Nechte Microsoft SQL zvládnout těžkou práci
Microsoft SQL je rychlejší pro filtrování, spojení a agregace než stahování všech surových dat přes kabel. Používejte DuckDB pro sekundární analýzu již načtených výsledků, nikoli jako náhradu za optimalizaci dotazů v 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")
Používejte šipku pro všechny čtecí operace
Přenos na základě šipek se vyhýbá vytváření mezipředmětů v Python, což snižuje využití paměti a zlepšuje propustnost. Preferujte cursor.arrow() před manuálním převodem řádků po řádku při přenosu dat do DuckDB.
Používejte streamování pro velké datové sady
Pro sady výsledků větších, než je dostupná paměť, použijte arrow_reader() s parametrem batch_size k inkrementálnímu zpracování dat.