Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
DuckDB ist eine in-process SQL-Analyse-Engine, die Apache Arrow-Tabellen direkt abfragen kann, ohne Daten zu kopieren. Die Kombination von DuckDB mit dem mssql-python-Treiber ermöglicht es:
- Führe analytische SQL-Abfragen auf Microsoft SQL-Ergebnissätzen aus, ohne Daten in Pandas oder Polars zu laden.
- Abfragen von Arrow-Tabellen im Speicher ohne Kopier-Overhead.
- Verknüpfen Sie Microsoft SQL-Daten mit lokalen Dateien (CSV, Parquet, JSON) in einer einzigen DuckDB-Abfrage.
- Exportiere Microsoft SQL-Daten über DuckDB in Parquet, CSV oder andere Formate.
Voraussetzungen
- Python 3.10 oder höher.
- Die
mssql-python,duckdb, undpyarrowPakete. Installieren Sie alle mitpip install mssql-python duckdb pyarrow. - Installieren Sie die einmaligen betriebsystem-spezifischen Voraussetzungen. Windows-Nutzer können diesen Schritt überspringen. Für vollständige Plattformdetails siehe Install mssql-python.
Erstellen einer SQL-Datenbank
Erstellen oder verbinden Sie sich mit einer SQL-Datenbank auf einer der folgenden Plattformen:
Die Beispiele in diesem Artikel fragen die AdventureWorks Beispieldatenbank ab. Falls du sie noch nicht hast, schau dir die AdventureWorks-Beispieldatenbanken an.
Abhängigkeiten installieren
pip install mssql-python duckdb pyarrow
Abfrage von Microsoft-SQL-Daten mit DuckDB
Der grundlegende Arbeitsablauf ist: Eine Abfrage mit mssql-python ausführen, die Ergebnisse als Arrow-Tabelle abrufen und dann diese Arrow-Tabelle mit DuckDB SQL abfragen.
Grundlegendes Muster
Beginnen Sie damit, eine Verbindung herzustellen und Daten als Pfeiltabelle abzurufen.
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 verweist auf die products Arrow-Tabelle anhand ihres Python-Variablennamens. Es werden keine Daten in den Speicher von DuckDB kopiert.
Aggregat und Filter
Verwenden Sie das SQL von DuckDB, um Arrow-Daten zu gruppieren und zu aggregieren.
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())
Treten Sie mehreren Microsoft SQL-Ergebnissen bei
Mehrere Tabellen aus Microsoft SQL holen und sie in DuckDB einfügen, ohne eine serverübergreifende Abfrage zu schreiben.
# 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())
Verknüpfe Microsoft SQL-Daten mit lokalen Dateien
DuckDB kann CSV-, Parquet- und JSON-Dateien nativ lesen. Kombinieren Sie SQL Server-Daten mit lokalen Dateien in einer einzigen Abfrage.
Mit einer CSV-Datei verknüpfen
Lade eine CSV-Datei und verbinde sie mit Daten von 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)
Mit einer Parquet-Datei verbinden
Lade eine Parquet-Datei und verbinde sie mit Daten aus 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)
Microsoft SQL-Daten exportieren
Verwenden Sie die COPY DuckDB-Anweisung, um Microsoft SQL-Daten in verschiedene Dateiformate zu exportieren.
Export nach Parquet
Daten in das Apache-Parquet-Format exportieren.
cursor.execute("SELECT * FROM Production.Product")
products = cursor.arrow()
duckdb.sql("COPY products TO 'products.parquet' (FORMAT PARQUET)")
In CSV exportieren
Exportiere die Daten in eine Komma-getrennte Wertedatei:
cursor.execute("SELECT * FROM Sales.SalesOrderHeader")
orders = cursor.arrow()
duckdb.sql("COPY orders TO 'orders.csv' (FORMAT CSV, HEADER)")
Partitioniertes Parquet exportieren
Exportiere Daten in partitionierte Parquet-Dateien für verteilte Analysen:
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))
""")
Große Ergebnismengen streamen
Verwenden Sie für große Datensätze arrow_reader(), um Daten in Streaming-Batches zu verarbeiten, ohne alle Zeilen gleichzeitig in den Arbeitsspeicher zu 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")
Streaming-Ergebnisse akkumulieren
Um über alle Chargen hinweg zu aggregieren, registrieren Sie jeden Batch in einer persistenten DuckDB-Verbindung und akkumulieren Sie die Ergebnisse schrittweise.
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()
Leistungstipps
Lass Microsoft SQL die schwere Arbeit übernehmen
Microsoft SQL ist schneller für Filterung, Joins und Aggregationen, als alle Rohdaten über die Leitung zu ziehen. Verwenden Sie DuckDB für sekundäre Analysen von bereits abgerufenen Ergebnismengen, nicht als Ersatz für die SQL Server-Abfrageoptimierung.
# 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")
Verwenden Sie Arrow für alle Leseoperationen
Pfeilbasierte Übertragungen vermeiden das Erstellen von Zwischen-Python-Objekten, was den Speicherbedarf reduziert und den Durchsatz verbessert. Bevorzuge cursor.arrow() statt einer manuellen zeilenweisen Konvertierung beim Übergeben von Daten an DuckDB.
Nutzen Sie Streaming für große Datensätze
Für Ergebnismengen, die größer sind als der verfügbaren Speicher, verwenden Sie arrow_reader() mit einem batch_size-Parameter, um Daten inkrementell zu verarbeiten.