Blockchains mit SQL abfragen · Lektion 1 von 6
Der Analytics-Datenstack
9 Min. Lesezeit
Fast jede Zahl in einem On-Chain-Bericht hat eine Pipeline durchlaufen, die zwischen dem Node, der den Block erfasst hat, und der Abfrage liegt, die die Kennzahl erzeugt hat. Wer als Analyst weiß, zu welcher Ebene eine Tabelle gehört, wer sie erstellt hat, wie aktuell sie ist und welche Regeln ihre Gestaltung beeinflusst haben, kann echte Erkenntnisse von Pipeline-Artefakten unterscheiden. Diese Lektion bildet den Stack und die Entscheidungen ab, die bei der Auswahl der dafür passenden Tools zu treffen sind.
Vom Node zur Tabelle
Ein Node speichert und liefert Blockchain-Daten in der Form, die das Protokoll benötigt: Blöcke, Transaktionen, Receipts und den State, abrufbar über RPC-Aufrufe (siehe die Lektion Node-APIs und Datenzugriff). Analysten benötigen dieselben Daten als Zeilen und Spalten, die sich filtern, verknüpfen und summieren lassen. Der Prozess, der das eine in das andere umwandelt, ist eine ETL-Pipeline: Extract, Transform, Load.
- Extract. Die Pipeline fragt den Node für jeden Block eines Bereichs ab: den Block samt Transaktionen, die Receipts samt Logs und, sofern der Node sie unterstützt, die Call-Traces.
- Transform. Verschachteltes JSON wird in eine Zeile pro Datensatz abgeflacht. Hex-Strings werden in Zahlen umgewandelt, der Block-Zeitstempel wird in jede Transaktion und jedes Log kopiert, sodass Abfragen für die Zeit keinen Join benötigen, und Bezeichner werden normalisiert (zum Beispiel Adressen in Kleinbuchstaben).
- Load. Zeilen werden in einem Speicher abgelegt, meist in spaltenorientierten Dateien wie Apache Parquet, partitioniert nach Datum oder Blockbereich, oder in Datenbanktabellen. Offene Tabellenformate wie Apache Iceberg und Delta Lake legen versionierte Snapshots über die Dateien.
Der zentrale Begriff ist die Granularität: Was stellt eine Zeile dar? Ein Ethereum-Block mit 150 Transaktionen und 400 Event-Logs ergibt eine Zeile in blocks, 150 Zeilen in transactions und 400 Zeilen in logs. Die meisten Abfragefehler entstehen dadurch, dass die Granularität einer Tabelle vergessen und auf der falschen Ebene gezählt oder summiert wird.
Pipelines laufen in zwei Modi. Ein Backfill verarbeitet den Verlauf einmalig in großen Stapeln. Streaming oder inkrementelle Ladevorgänge folgen der Chain-Spitze blockweise. Nahe an der Spitze können Blöcke noch durch eine Reorganisation ersetzt werden. Deshalb wartet eine Pipeline entweder eine bestimmte Anzahl an Bestätigungen oder einen finalisierten Block ab oder schreibt kürzlich verarbeitete Blöcke neu, wenn sich die Chain ändert (siehe die Lektion Blöcke und Header als Daten).
Für einen Großteil dieser Arbeit gibt es Open-Source-Extraktoren: Ethereum ETL und Bitcoin ETL des blockchain-etl-Projekts sowie cryo, das EVM-Daten direkt in Parquet schreibt. Sie sind auch dann wissenswert, wenn du sie nie selbst ausführst, denn viele öffentliche Datensätze wurden mit ihnen erstellt und übernehmen ihre Spaltennamen.
Rohdaten-, dekodierte und kuratierte Tabellen
Tabellen in einem Blockchain-Warehouse gehören zu drei Ebenen, die den Datenebenen entsprechen, die in der Lektion Die Perspektive des Analysten auf eine Blockchain vorgestellt wurden.
| Ebene | Inhalt | Typische Tabellen | Hauptrisiko |
|---|---|---|---|
| Rohdaten | Datensätze, wie der Node sie zurückgibt, typisiert, aber nicht interpretiert | blocks, transactions, logs, traces; Inputs und Outputs bei UTXO-Chains | Hex-Felder, Basiseinheiten (wei, satoshi), schwer lesbar |
| Dekodiert | Rohdatensätze, interpretiert mit einer ABI oder einem Skriptparser | Eine Tabelle pro Contract-Event oder -Funktion, dekodierte Calldata | Fehlende oder falsche ABI, Proxies, nicht verifizierte Contracts |
| Kuratiert | Tabellen auf Business-Ebene, die aus mehreren Quellen erstellt wurden | token_transfers, dex_trades, balances, labels, prices | Verborgene Regeln für die Aufnahme, fehlerhafte Labels, veraltete Preise |
Jeder Schritt nach oben verkürzt Abfragen und fügt Entscheidungen hinzu, die jemand anderes getroffen hat. Eine kuratierte Tabelle token_transfers beantwortet Fragen mit einer einzigen Zeile, aber du musst ihre Regeln kennen. Enthält sie ERC-721-Transfers oder nur fungible Token? Werden Mints und Burns als Zeilen mit der Nulladresse aufgenommen oder ausgeschlossen? Ist der Betrag die rohe Ganzzahl oder wurde er bereits durch die Dezimalstellen geteilt? Zwei Datensätze, die eine Tabelle beide token_transfers nennen, können sich in all diesen Punkten unterscheiden.
Die Gewohnheit, die dich davor schützt, ist der Abgleich: Prüfe eine kuratierte Tabelle anhand der Rohdatenebene, aus der sie stammt, für einen kleinen Blockbereich.
-- Entspricht die kuratierte Tabelle token_transfers den Roh-Logs, aus denen sie erstellt wurde?
SELECT 'Rohe Logs' AS layer, COUNT(*) AS n
FROM logs
WHERE topic0 = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
AND topic3 IS NULL -- nur fungible Transfers (ERC-20-artig)
AND block_number BETWEEN 21000000 AND 21000099
UNION ALL
SELECT 'token_transfers', COUNT(*)
FROM token_transfers
WHERE block_number BETWEEN 21000000 AND 21000099;
Die erste Hälfte zählt rohe Transfer-Events (der lange Hex-String ist der Signatur-Hash des Events, erläutert in der Lektion EVM-Logs und Traces abfragen); die zweite zählt die kuratierten Zeilen für dieselben 100 Blöcke. Wenn die Zahlen abweichen, solltest du zuerst herausfinden, warum, bevor du die Tabelle verwendest: Die kuratierte Ebene lässt möglicherweise bestimmte Token weg, enthält NFTs oder weist fehlende Blöcke auf.
Öffentliche Blockchain-Datensätze
Du brauchst keine eigene Pipeline, um loszulegen. Mehrere kostenlose, öffentliche Datensätze stellen den vollständigen Chain-Verlauf in Abfrage-Engines oder Dateien bereit.
- Öffentliche BigQuery-Datensätze von Google. Die Datensätze
crypto_bitcoinundcrypto_ethereum(sowie weitere für mehrere Chains) wurden mit den Tools von blockchain-etl erstellt. Der Ethereum-Datensatz enthält die Tabellenblocks,transactions,logs,traces,token_transfers,contractsundtokens; seine Logs speichern Topics als Array statt in separaten Spalten. Für Abfragen ist ein Cloud-Konto erforderlich. Daten, die über ein kostenloses Kontingent hinaus gescannt werden, werden in Rechnung gestellt. - AWS Public Blockchain Data. Komprimierte Parquet-Dateien in einem öffentlichen Speicher-Bucket, nach Datum partitioniert und täglich aktualisiert. Der Datensatz umfasst Bitcoin, Ethereum und mehrere weitere Chains; prüfe die Dokumentation auf die aktuelle Liste. Die Dateien lassen sich mit jeder Engine lesen, die Parquet unterstützt.
- Gehostete Abfrageplattformen. Mehrere Unternehmen betreiben Community-Plattformen mit Rohdaten-, dekodierten und kuratierten Tabellen für viele Chains sowie einem kostenlosen Kontingent. Sie sind für dekodierte Daten praktisch, aber ihre kuratierten Tabellen folgen den Regeln des jeweiligen Anbieters.
Öffentlich bedeutet nicht, dass die Daten korrekt oder aktuell sind. Datensätze hinken der Chain um Minuten bis zu einem Tag hinterher, ändern ihre Schemas und lassen gelegentlich nach einem Extraktionsfehler Blöcke aus. Bevor du dich auf eine Tabelle verlässt, erstelle ein Profil davon.
-- Erstelle ein Profil der Tabelle, bevor du ihr vertraust: Abdeckung, Aktualität, Duplikate
SELECT
MIN(block_number) AS first_block,
MAX(block_number) AS last_block,
MAX(block_timestamp) AS latest_data_utc,
COUNT(*) AS row_count,
COUNT(DISTINCT hash) AS distinct_hashes -- sollte row_count entsprechen
FROM transactions;
Diese Abfrage zeigt dir den abgedeckten Blockbereich, wie aktuell die neueste Zeile ist und ob eine Transaktion doppelt vorkommt. Bei einer vollständigen Chain scannt sie nur wenige Spalten, allerdings aus einer sehr großen Tabelle. Führe sie daher bei einer Engine mit Abrechnung pro Scan zuerst für einen aktuellen Datumsbereich aus (siehe die Lektion Performance, Kosten und Reproduzierbarkeit).
Abfrage-Engines und Notebooks
Die Engine ist die Software, die deine SQL-Abfragen ausführt. Dieselben Daten können hinter sehr unterschiedlichen Engines liegen.
| Engine-Typ | Offene Beispiele | Geeignet für |
|---|---|---|
| Cloud-Data-Warehouse | Verwaltete Dienste der großen Cloud-Anbieter | Scans des vollständigen Verlaufs ohne eigene Infrastruktur; hostet öffentliche Datensätze |
| Verteiltes SQL über Dateien | Trino, Apache Spark SQL | Data Lakes mit Parquet-Dateien im Teammaßstab |
| Spaltenorientierte Analytics-Datenbank | ClickHouse | Schnelle Dashboards und kontinuierliche Überwachung |
| Eingebettete Engine | DuckDB, SQLite | Arbeit auf einem Laptop mit einem lokalen Datenextrakt; vertrauliche Fälle |
| Relationale Datenbank | PostgreSQL | Falldaten, Labels und kleine Tabellen, die häufig geändert werden |
Grundlegendes SQL (SELECT, JOIN, GROUP BY, Window-Funktionen) ist weitgehend gleich, doch Funktionsnamen, Datumsverarbeitung, Array-Syntax und sogar die Benennung von Tabellen unterscheiden sich.
-- Eine Frage, drei Arten, die Daten zu benennen
-- Öffentliches Warehouse-Dataset (project.dataset.table, BigQuery-Quoting):
SELECT COUNT(*) FROM `bigquery-public-data.crypto_ethereum.blocks`
WHERE DATE(timestamp) = '2024-11-01';
-- Eingebettete Engine, die Parquet-Dateien direkt liest (DuckDB-Syntax):
SELECT COUNT(*) FROM read_parquet('eth/blocks/date=2024-11-01/*.parquet');
-- Jede Engine mit dem generischen Schema dieses Moduls:
SELECT COUNT(*) FROM blocks WHERE CAST(block_timestamp AS DATE) = DATE '2024-11-01';
Alle drei Abfragen zählen die Blöcke, die an einem UTC-Tag erzeugt wurden. Nur der Tabellenverweis und die Datumssyntax unterscheiden sich; die Logik ist identisch. Die Lektionen in diesem Modul verwenden ein generisches Schema und weisen auf die wichtigsten Dialektunterschiede hin, sobald sie auftreten.
Notebooks (Jupyter und Ähnliches) kombinieren SQL-Zellen, Code in Python oder R, Diagramme und schriftliche Notizen in einem Dokument. Das eignet sich für Untersuchungen: abfragen, prüfen, visualisieren und die Überlegungen dokumentieren. Manche Aufgaben lassen sich mit SQL nur schwer lösen, insbesondere iterative Graphenanalysen wie das Finden verbundener Komponenten für das Clustering. Für solche Aufgaben exportieren Analysten Kanten aus SQL in eine Graphbibliothek (siehe die Lektion UTXO-Daten abfragen).
Tools auswählen
Es gibt keinen besten Stack, sondern nur einen, der zur Fragestellung, zum Budget und zur Sensibilität der Arbeit passt. Wäge diese Kriterien ab:
- Abdeckung. Welche Chains und welcher Datumsbereich? Sind Traces und dekodierte Events enthalten?
- Aktualität. Benötigst du Daten vom letzten Block oder reicht der Stand von gestern?
- Kostenmodell. Abrechnung pro gescannter Datenmenge, pro Rechenzeit oder feste Infrastruktur, die du selbst betreibst.
- Reproduzierbarkeit. Kannst du einen Snapshot oder eine Blockhöhe festlegen und nächsten Monat dieselbe Antwort erhalten?
- Vertraulichkeit. Abfragen bei gehosteten Diensten werden vom Anbieter protokolliert, und auf manchen Community-Plattformen sind sie standardmäßig öffentlich. Wenn du die Adresse eines Verdächtigen in eine gemeinsam genutzte Plattform eingibst, kann das eine Untersuchung offenlegen. Bei vertraulicher Arbeit solltest du einen Blockbereich extrahieren und lokal abfragen.
- Herkunft. Lässt sich jede Zeile auf einen Block-Hash und einen Transaktions-Hash zurückführen, die du auf einem Node überprüfen kannst?
Typische Anwendungsfälle:
| Situation | Sinnvoller Stack |
|---|---|
| Journalist prüft den Verlauf einer Wallet über zwei Jahre | Öffentlicher Datensatz in einem Warehouse oder auf einer gehosteten Plattform, anschließend die verwendeten Zeilen exportieren |
| Risikoteam einer Börse prüft den ganzen Tag Einzahlungen | Streaming-Pipeline in eine spaltenorientierte Datenbank mit Label- und Preistabellen |
| Wissenschaftliche Studie, die exakt reproduziert werden muss | Festgelegter Parquet-Snapshot, versionierter Code, eingebettete oder verteilte Engine |
| Vertrauliche Untersuchung | Eigener Node oder heruntergeladene Dateien, lokale eingebettete Engine, keine gehosteten Abfragen |
Was auch immer du auswählst: Halte bei jedem Ergebnis den Datensatz, seine Version oder das Snapshot-Datum, den Abfragetext und die Ausführungszeit fest.
Prüfungsschwerpunkt: die drei ETL-Phasen und was im Transform-Schritt geschieht; die Bedeutung der Granularität und warum ein Block zu vielen Zeilen wird; der Unterschied zwischen Rohdaten-, dekodierten und kuratierten Tabellen und die jeweiligen Risiken; warum kuratierte Tabellen mit Rohdaten abgeglichen werden müssen; die wichtigsten öffentlichen Datensätze (BigQuery-Krypto-Datensätze, AWS Public Blockchain Data in Parquet) und ihre Grenzen; Kategorien von Abfrage-Engines und wann eine eingebettete Engine sinnvoll ist; warum sich Notebooks für Untersuchungen eignen; Kriterien für die Tool-Auswahl, insbesondere die Vertraulichkeit gehosteter Abfragen und die Reproduzierbarkeit.