Code & Queries

Code & Queries: Your Source for SQL, Python, and AI Insights

In diesem Blogbeitrag werden wir Schritt für Schritt eine CI/CD-Pipeline (Continuous Integration/Continuous Deployment) mit Python und DuckDB erstellen. DuckDB ist eine leistungsstarke, in-memory OLAP-Datenbank, die sich hervorragend für analytische Workloads eignet. Wir werden eine Pipeline aufbauen, die automatisch Tests durchführt, die Datenbank aktualisiert und bei Bedarf neue Versionen bereitstellt.

Voraussetzungen

Bevor wir beginnen, stellen Sie sicher, dass Sie folgende Tools installiert haben:

  • Python 3.8 oder höher
  • DuckDB: Installieren Sie DuckDB mit pip install duckdb.
  • Git: Für die Versionskontrolle.
  • GitHub Actions oder ein anderer CI/CD-Dienst (z.B. GitLab CI, Jenkins).
  • Ein GitHub-Repository: Wo wir unseren Code und die Pipeline speichern werden.

Schritt 1: Projektstruktur erstellen

Zuerst erstellen wir eine grundlegende Projektstruktur:

my_duckdb_project/
│
├── .github/
│   └── workflows/
│       └── ci_cd_pipeline.yml
├── src/
│   └── main.py
├── tests/
│   └── test_main.py
├── requirements.txt
└── README.md
  • .github/workflows/ci_cd_pipeline.yml: Hier definieren wir unsere CI/CD-Pipeline.
  • src/main.py: Unser Hauptskript, das DuckDB verwendet.
  • tests/test_main.py: Unit-Tests für unser Skript.
  • requirements.txt: Liste der Python-Abhängigkeiten.
  • README.md: Dokumentation des Projekts.

Schritt 2: Python-Skript mit DuckDB erstellen

In src/main.py schreiben wir ein einfaches Python-Skript, das DuckDB verwendet:

import duckdb

def create_table():
    conn = duckdb.connect('my_db.duckdb')
    conn.execute("CREATE TABLE IF NOT EXISTS my_table (id INTEGER, name STRING)")
    conn.close()

def insert_data(id, name):
    conn = duckdb.connect('my_db.duckdb')
    conn.execute(f"INSERT INTO my_table VALUES ({id}, '{name}')")
    conn.close()

def query_data():
    conn = duckdb.connect('my_db.duckdb')
    result = conn.execute("SELECT * FROM my_table").fetchall()
    conn.close()
    return result

if __name__ == "__main__":
    create_table()
    insert_data(1, 'Alice')
    insert_data(2, 'Bob')
    print(query_data())

Dieses Skript erstellt eine Tabelle, fügt Daten ein und gibt die Daten aus der Tabelle zurück.

Schritt 3: Unit-Tests schreiben

In tests/test_main.py schreiben wir Unit-Tests für unser Skript:

import unittest
from src.main import create_table, insert_data, query_data

class TestDuckDB(unittest.TestCase):
    def test_create_table(self):
        create_table()
        # Überprüfen, ob die Tabelle erstellt wurde
        self.assertTrue(True)  # Platzhalter für echte Überprüfung

    def test_insert_data(self):
        insert_data(1, 'Alice')
        data = query_data()
        self.assertIn((1, 'Alice'), data)

if __name__ == "__main__":
    unittest.main()

Schritt 4: Abhängigkeiten festlegen

In requirements.txt listen wir unsere Python-Abhängigkeiten auf:

duckdb==0.5.0

Schritt 5: CI/CD-Pipeline mit GitHub Actions erstellen

In .github/workflows/ci_cd_pipeline.yml definieren wir unsere CI/CD-Pipeline:

name: CI/CD Pipeline for DuckDB Project

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.8'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run tests
      run: |
        python -m unittest discover -s tests

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.8'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run main script
      run: |
        python src/main.py

Diese Pipeline führt die folgenden Schritte aus:

  1. Test-Job: Führt die Unit-Tests aus, wenn ein Push oder Pull Request auf den main-Branch erfolgt.
  2. Deploy-Job: Führt das Hauptskript aus, wenn die Tests erfolgreich sind.

Schritt 6: Pipeline in Aktion

Sobald Sie den Code in Ihr GitHub-Repository pushen, wird die Pipeline automatisch ausgeführt. Sie können den Fortschritt und die Ergebnisse der Pipeline in der GitHub Actions-Ansicht überprüfen.

Fazit

In diesem Blogbeitrag haben wir eine einfache CI/CD-Pipeline mit Python und DuckDB erstellt. Diese Pipeline führt automatisch Tests durch und stellt bei Erfolg das Skript bereit. Dieses Setup kann je nach Bedarf erweitert werden, z.B. durch das Hinzufügen von Datenbank-Migrationen, weiteren Tests oder Deployment-Schritten.

Um ein Trennkriterium für "Obere" und "Untere" in einem Ranking in DuckDB SQL zu erstellen, können wir eine Kombination aus Fensterfunktionen und bedingter Logik verwenden. Das Ziel ist es, die Daten in zwei Gruppen zu unterteilen: die obere Hälfte und die untere Hälfte des Rankings.

Beispiel:

Angenommen, wir haben eine Tabelle sales mit den Spalten id, salesperson, und sales_amount. Wir möchten die Verkäufer nach ihrem Verkaufsvolumen (sales_amount) ranken und sie dann in die obere und untere Hälfte einteilen.

Schritt 1: Ranking erstellen

Zuerst erstellen wir ein Ranking basierend auf der sales_amount:

WITH ranked_sales AS (
    SELECT
        id,
        salesperson,
        sales_amount,
        RANK() OVER (ORDER BY sales_amount DESC) AS sales_rank,
        COUNT(*) OVER () AS total_salespeople
    FROM
        sales
)

Schritt 2: Trennkriterium anwenden

Nun teilen wir die Verkäufer in die obere und untere Hälfte ein. Wir verwenden dazu die sales_rank und total_salespeople:

SELECT
    id,
    salesperson,
    sales_amount,
    sales_rank,
    CASE
        WHEN sales_rank <= total_salespeople / 2 THEN 'Obere Hälfte'
        ELSE 'Untere Hälfte'
    END AS ranking_group
FROM
    ranked_sales
ORDER BY
    sales_rank;

Vollständiges Beispiel:

-- Tabelle erstellen und Daten einfügen
CREATE TABLE sales (
    id INT,
    salesperson VARCHAR,
    sales_amount DECIMAL(10, 2)
);

INSERT INTO sales (id, salesperson, sales_amount) VALUES
(1, 'Alice', 1500.00),
(2, 'Bob', 2000.00),
(3, 'Charlie', 1200.00),
(4, 'David', 1800.00),
(5, 'Eve', 2200.00),
(6, 'Frank', 1300.00),
(7, 'Grace', 1700.00),
(8, 'Hank', 1900.00),
(9, 'Ivy', 2100.00),
(10, 'Jack', 1400.00);

-- Ranking und Trennung in obere/untere Hälfte
WITH ranked_sales AS (
    SELECT
        id,
        salesperson,
        sales_amount,
        RANK() OVER (ORDER BY sales_amount DESC) AS sales_rank,
        COUNT(*) OVER () AS total_salespeople
    FROM
        sales
)
SELECT
    id,
    salesperson,
    sales_amount,
    sales_rank,
    CASE
        WHEN sales_rank <= total_salespeople / 2 THEN 'Obere Hälfte'
        ELSE 'Untere Hälfte'
    END AS ranking_group
FROM
    ranked_sales
ORDER BY
    sales_rank;

Erklärung:

  1. RANK() OVER (ORDER BY sales_amount DESC): Diese Funktion weist jedem Verkäufer einen Rang basierend auf der sales_amount zu. Der Verkäufer mit dem höchsten Verkaufsvolumen erhält den Rang 1.

  2. COUNT(*) OVER (): Diese Funktion zählt die Gesamtanzahl der Verkäufer in der Tabelle.

  3. CASE-Statement: Hier wird entschieden, ob ein Verkäufer zur oberen oder unteren Hälfte gehört. Wenn der Rang eines Verkäufers kleiner oder gleich der Hälfte der Gesamtanzahl der Verkäufer ist, wird er der "Oberen Hälfte" zugeordnet, andernfalls der "Unteren Hälfte".

Ergebnis:

Das Ergebnis dieser Abfrage wird eine Liste der Verkäufer sein, die nach ihrem Verkaufsvolumen geordnet ist, zusammen mit einer Spalte ranking_group, die angibt, ob sie zur oberen oder unteren Hälfte gehören.

 id | salesperson | sales_amount | sales_rank | ranking_group
----+-------------+--------------+------------+---------------
  5 | Eve         |      2200.00 |          1 | Obere Hälfte
  9 | Ivy         |      2100.00 |          2 | Obere Hälfte
  2 | Bob         |      2000.00 |          3 | Obere Hälfte
  8 | Hank        |      1900.00 |          4 | Obere Hälfte
  4 | David       |      1800.00 |          5 | Obere Hälfte
  7 | Grace       |      1700.00 |          6 | Untere Hälfte
  1 | Alice       |      1500.00 |          7 | Untere Hälfte
 10 | Jack        |      1400.00 |          8 | Untere Hälfte
  6 | Frank       |      1300.00 |          9 | Untere Hälfte
  3 | Charlie     |      1200.00 |         10 | Untere Hälfte

In diesem Beispiel gehören die ersten 5 Verkäufer zur "Oberen Hälfte" und die restlichen 5 zur "Unteren Hälfte".

Einleitung

Parquet Files und DuckDB bieten eine moderne, leichtgewichtige und effiziente Lösung für OLAP-Analysen (Online Analytical Processing). Parquet als Dateiformat ermöglicht schnelle und platzsparende Speicherung, während DuckDB als SQL-Engine ideal für Ad-hoc-Analysen direkt auf Parquet-Daten ausgelegt ist. Diese Kombination eignet sich hervorragend für Data Warehousing, Business Intelligence (BI) und Big-Data-Analysen ohne den Overhead traditioneller OLAP-Systeme.


Vorteile der Kombination

1. Parquet: Effiziente Speicherung

  • Spaltenbasiert: Parquet speichert Daten spaltenweise, wodurch die Abfrageleistung bei analytischen Workloads erheblich gesteigert wird.
  • Kompakte Datenstruktur: Datenkompression und Codierung reduzieren den Speicherbedarf.
  • Portabilität: Parquet-Dateien sind plattformunabhängig und können von zahlreichen Tools wie Pandas, Spark oder Hive gelesen werden.

2. DuckDB: Eingebettete SQL-Engine

  • Direkte Parquet-Unterstützung: DuckDB ermöglicht SQL-Abfragen direkt auf Parquet-Dateien, ohne diese vorher in eine Datenbank importieren zu müssen.
  • Performance: Optimiert für analytische Abfragen durch spaltenbasierte Verarbeitung und speicheroptimierte Ausführung.
  • Flexibilität: Unterstützt JOINs, Aggregationen und OLAP-Operationen.
  • Leichtgewichtig: Keine Installation erforderlich, ideal für lokale oder cloudbasierte Workflows.

3. Kombination für OLAP

  • Self-Service BI: Analyse direkt aus Parquet-Dateien, ohne komplexe ETL-Prozesse.
  • Kostenreduktion: Keine teuren OLAP-Datenbanken notwendig.
  • Einfache Integration: Unterstützt gängige Workflows mit Python, R oder Shell-Skripten.

Architektur für OLAP mit Parquet und DuckDB

  1. Datenquellen

    • Daten aus APIs, CSV, JSON, oder relationalen Datenbanken extrahieren.
    • Speicherung als Parquet-Dateien.
  2. Datenaufbereitung

    • Transformation und Bereinigung der Daten mittels Python oder ETL-Tools.
    • Speicherung vorbereiteter Daten als Parquet-Dateien für jede Dimension und Faktentabelle.
  3. DuckDB als SQL-Layer

    • Verbindung zu Parquet-Dateien herstellen.
    • OLAP-Abfragen direkt auf den Dateien ausführen.
    • Erstellung von Views für komplexe Analysen.
  4. Integration mit BI-Tools

    • DuckDB kann mit Tools wie Tableau, Power BI oder Jupyter Notebooks integriert werden.
    • Ad-hoc-Analysen durch SQL-Schnittstelle.

Beispiel: Abfrage auf Parquet mit DuckDB

import duckdb

# Verbindung zu DuckDB herstellen
con = duckdb.connect()

# Parquet-Dateien direkt abfragen
query = """
    SELECT 
        product_category, 
        SUM(sales) AS total_sales
    FROM 'data/fact_sales.parquet'
    WHERE year = 2024
    GROUP BY product_category
    ORDER BY total_sales DESC
"""
result = con.execute(query).fetchdf()

print(result)

Optimierungstipps

  1. Partitionierung der Parquet-Dateien:

    • Daten basierend auf Datumsfeldern (z. B. year, month) partitionieren, um Abfragen zu beschleunigen.
  2. Statistische Dimensionen:

    • Zeit- und Datumsdimensionen statisch halten, um Redundanz und Berechnungsaufwand zu reduzieren.
  3. Dynamische Dimensionen:

    • Änderungen in Dimensionen wie Brand oder Station mit SCD Typ 2 verwalten.
  4. Indexierung:

    • DuckDB verwendet intern Optimierungen wie spaltenbasierte Verarbeitung. Indexe sind nicht notwendig.

Anwendungsfälle

  1. Tankstellen-Monitoring:

    • Preisänderungen und historische Datenanalysen basierend auf Parquet-Dateien mit DuckDB.
  2. E-Commerce-Analysen:

    • Auswertung von Verkäufen, Trends und Kundenverhalten direkt aus den Parquet-Daten.
  3. IoT-Datenanalyse:

    • Verarbeitung großer Mengen Sensordaten für Ad-hoc-Berichte.

Fazit Die Kombination aus Parquet und DuckDB ist eine leistungsstarke und kostengünstige Alternative zu traditionellen

OLAP-Lösungen. Sie ermöglicht datengetriebene Entscheidungen in Echtzeit und unterstützt sowohl große Datenmengen als auch skalierbare Architekturen für moderne Datenplattformen.

Blog-Beitrag: DuckDB – Die revolutionäre Datenbank für analytische Workloads


Einleitung

In der Welt der Datenbanken gibt es immer wieder neue Tools, die versprechen, unsere Arbeit effizienter und einfacher zu machen. Eines dieser Tools, das in letzter Zeit viel Aufmerksamkeit auf sich gezogen hat, ist DuckDB. DuckDB ist eine in-process SQL-Datenbank, die speziell für analytische Workloads entwickelt wurde. In diesem Beitrag werfen wir einen Blick darauf, was DuckDB so besonders macht, warum es sich lohnt, es auszuprobieren, und wie du es in deinen Projekten einsetzen kannst.


Was ist DuckDB?

DuckDB ist eine Open-Source-Datenbank, die für Datenanalyse optimiert ist. Im Gegensatz zu herkömmlichen Datenbanken wie MySQL oder PostgreSQL ist DuckDB in-process, was bedeutet, dass sie direkt in deiner Anwendung läuft – ohne separaten Server. Das macht sie besonders schnell und einfach zu nutzen.

DuckDB ist ideal für:
- Analytische Abfragen (OLAP – Online Analytical Processing)
- Datenwissenschaftliche Workloads
- Lokale Datenanalyse ohne komplexe Infrastruktur


Warum DuckDB?

Hier sind einige Gründe, warum DuckDB eine Überlegung wert ist:

  1. Einfache Installation und Nutzung:
    DuckDB lässt sich leicht in Python, R oder anderen Sprachen integrieren. Es gibt keine aufwendige Server-Konfiguration – einfach installieren und loslegen.

  2. Blitzschnelle Abfragen:
    DuckDB ist für analytische Abfragen optimiert und nutzt moderne Techniken wie Vektorisierung, um Daten schnell zu verarbeiten.

  3. Keine externe Infrastruktur nötig:
    Da DuckDB in-process läuft, brauchst du keinen separaten Datenbankserver. Das macht es perfekt für lokale Analysen oder Embedded-Systeme.

  4. SQL-Unterstützung:
    DuckDB unterstützt standardisiertes SQL, sodass du keine neue Sprache lernen musst.

  5. Open Source:
    DuckDB ist kostenlos und quelloffen, mit einer aktiven Community, die ständig neue Features entwickelt.


DuckDB in Aktion: Ein Beispiel mit Python

Lass uns DuckDB mit Python ausprobieren. Wir werden eine CSV-Datei laden, eine einfache Abfrage durchführen und die Ergebnisse anzeigen.

Schritt 1: Installation

Installiere DuckDB mit pip:

pip install duckdb
Schritt 2: CSV-Datei laden und analysieren

Angenommen, du hast eine CSV-Datei mit Verkaufsdaten (sales.csv). So kannst du sie mit DuckDB analysieren:

import duckdb

# Verbindung zur DuckDB-Datenbank herstellen (in-memory)
con = duckdb.connect(database=':memory:')

# CSV-Datei laden
con.execute("CREATE TABLE sales AS SELECT * FROM read_csv_auto('sales.csv')")

# Eine einfache Abfrage durchführen
result = con.execute("SELECT product, SUM(revenue) AS total_revenue FROM sales GROUP BY product").fetchdf()

# Ergebnisse anzeigen
print(result)
Ergebnis:

Du erhältst eine Tabelle mit den Gesamtumsätzen pro Produkt – schnell und ohne großen Aufwand!


Wann sollte man DuckDB verwenden?

DuckDB eignet sich besonders gut für:
- Lokale Datenanalyse: Wenn du schnell Daten analysieren möchtest, ohne eine komplexe Infrastruktur aufzubauen.
- Embedded-Systeme: Wenn du eine Datenbank in deiner Anwendung einbetten möchtest.
- Prototyping: Für schnelle Tests und Experimente mit Daten.

Für transaktionale Workloads (OLTP – Online Transaction Processing) oder sehr große Datenmengen, die auf verteilten Systemen laufen müssen, sind jedoch andere Datenbanken wie PostgreSQL oder Big-Data-Tools wie Apache Spark besser geeignet.


Fazit

DuckDB ist ein leistungsstarkes Werkzeug für analytische Workloads, das durch seine Einfachheit und Geschwindigkeit überzeugt. Ob du Datenwissenschaftler, Analyst oder Entwickler bist – DuckDB kann dir helfen, deine Daten schneller und effizienter zu analysieren.

Probiere es aus und lass uns wissen, wie es dir gefällt! Hast du schon Erfahrungen mit DuckDB gemacht? Teile sie gerne in den Kommentaren.


Weiterführende Ressourcen


Das war’s für heute! Bleib dran für mehr Beiträge zu spannenden Tools und Technologien im Bereich Daten, SQL, Python und KI. 😊