Zurück zur Startseite

ClickHouse-Client und HTTP-API: Verbindung und erste Abfragen

Leitfaden zu allen Möglichkeiten, eine Verbindung zu ClickHouse herzustellen: clickhouse-client mit Flags, Konfigurationsdatei ~/.clickhouse-client/config.xml, HTTP-API über curl. Interaktive und Batch-Modi, Antwortformate (JSON, CSV, Pretty, TSV) werden gezeigt. Am Beispiel einer Wettplattform werden die Wettdatenbank, die bets-Tabelle mit LowCardinality- und Enum8-Typen erstellt, Testdaten über INSERT und numbers()-Generator eingefügt, SELECT mit WHERE, ORDER BY, GROUP BY ausgeführt.

ClickHouse-Client: So verbinden und arbeiten Sie mit der Konsole und HTTP
Advertisement 728x90

ClickHouse-Client: Wie ich mich mit der Konsole und der HTTP-API in einem Glücksspielprojekt anfreundete

Mein erster Versuch an einer verschlossenen Tür

Ich erinnere mich, nach der Installation von ClickHouse tippte ich fröhlich clickhouse-client und bekam einen Fehler: Code: 210. DB::NetException: Connection refused (localhost:9000). Es stellte sich heraus, dass der Server nur auf 127.0.0.1 lauschte, und ich versuchte, mich von einem anderen Rechner aus zu verbinden. Eine Stunde Googeln, Bearbeiten von config.xml, Neustarten – und erst dann lernte ich, dass der Client die Flags --host und --port hat.

ClickHouse bietet zwei Kommunikationswege: den nativen Client (für Menschen und Skripte) und die HTTP-API (für alles andere). Ich nutze beide täglich. Im Folgenden finden Sie alles, was Sie wirklich brauchen, plus die Fallstricke, auf die ich getreten bin.

Verbindungsmethoden: Von einfach bis richtig

Methode 1. Naiv (nur localhost)

clickhouse-client

Dies funktioniert nur, wenn Sie sich auf demselben Rechner wie der Server befinden und Port 9000 nicht geändert haben. In der Produktion macht das niemand.

Google AdInline article slot

Methode 2. Professionell: Flags für Fernzugriff

clickhouse-client \
  --host analytics.prod.company.com \
  --port 9000 \
  --user analyst \
  --password 'StrongPass123' \
  --database betting

Was ich aus der Produktion gelernt habe: Geben Sie niemals ein Passwort in der Befehlszeile an, wenn die Bash-Verlaufsfunktion aktiviert ist. Verwenden Sie stattdessen eine Konfigurationsdatei.

Methode 3. Richtig: Konfigurationsdatei

Erstellen Sie ~/.clickhouse-client/config.xml:

<config>
    <host>clickhouse.prod.internal</host>
    <port>9000</port>
    <user>analyst</user>
    <password>${CLICKHOUSE_PASSWORD}</password>
    <database>betting</database>
    <history_file>/home/user/.clickhouse-client-history</history_file>
</config>

Passwort über Umgebungsvariable:

Google AdInline article slot
export CLICKHOUSE_PASSWORD="StrongPass123"
clickhouse-client

Warum das sicherer ist: Das Passwort landet nicht in ps aux oder im Verlauf. In der Produktion hatten wir einen Fall, bei dem ein Entwickler clickhouse-client --password secret ausführte, und innerhalb einer Stunde konnte jeder das Passwort in den Orchestrator-Logs sehen.

Methode 4. HTTP-Verbindung (Alternative für CI/CD)

Für die Automatisierung verwende ich oft HTTP:

curl -u analyst:StrongPass123 \
  "http://clickhouse.prod.internal:8123/?query=SELECT+1"

Interaktiv vs. Batch: Wann was verwenden

Interaktiver Modus (für Menschen)

clickhouse-client

Vorteile: Autovervollständigung (Tab-Taste), Befehlsverlauf, mehrzeilige Abfragen. Nachteile: Nicht für Skripte geeignet.

Google AdInline article slot
:) SELECT user_id, sum(amount) FROM bets GROUP BY user_id LIMIT 5;

Mein Life-Hack: Im interaktiven Modus funktionieren Abkürzungen wie \l (Datenbanken auflisten), \d (Tabellen auflisten), \c betting (Datenbank wechseln). Nicht jeder weiß das, aber es spart enorm viel Zeit.

Batch-Modus (für Skripte und Cron)

# Einzelner Befehl
clickhouse-client --query "SELECT count() FROM betting.bets"

# Aus Datei
clickhouse-client --queries-file /path/to/analytics.sql

# Mehrzeilig via heredoc
clickhouse-client <<SQL
SELECT 
    toDate(created_at) AS day,
    count() AS bets
FROM betting.bets
WHERE created_at >= today() - 7
GROUP BY day
ORDER BY day;
SQL

Was mich verbrannt hat: Im Batch-Modus müssen Sie Ihre Abfrage immer mit einem Semikolon beenden. Ohne wird der Befehl nicht ausgeführt, aber es wird auch kein Fehler angezeigt – er hängt einfach. Wir haben eine Stunde damit verbracht, Cron-Jobs zu debuggen.

HTTP-API: curl ist Ihr bester Freund

Das HTTP-Interface läuft auf Port 8123. Es ist perfekt für Microservices, Dashboards und Skripte in jeder Sprache.

GET-Anfragen: Einfach und schnell

# Einfachste Abfrage
curl "http://localhost:8123/?query=SELECT+version()"

# Mit Authentifizierung
curl -u user:pass "http://localhost:8123/?query=SELECT+count()+FROM+betting.bets"

# Mit Datenbankparameter
curl "http://localhost:8123/?database=betting&query=SELECT+count()+FROM+bets"

POST-Anfragen: Für große Abfragen und Dateneinfügung

# Lange Abfrage via POST (keine URL-Längenbegrenzung)
curl -X POST "http://localhost:8123/" \
  -d "SELECT user_id, sum(amount) FROM betting.bets GROUP BY user_id"

# Daten via POST einfügen
curl -X POST "http://localhost:8123/?query=INSERT+INTO+betting.bets+FORMAT+CSV" \
  --data-binary @bets_data.csv

Antwortformate: Wählen Sie für Ihre Aufgabe

ClickHouse kann Daten in vielen Formaten zurückgeben. Ich habe alle ausprobiert – hier ist, was Sie wirklich brauchen:

# Pretty – für Menschen (lesbar, aber viele Formatierungszeichen)
curl "http://localhost:8123/?query=SELECT+user_id,amount+FROM+bets+LIMIT+3&default_format=Pretty"

# JSON – für APIs (überall parsbar)
curl "http://localhost:8123/?query=SELECT+user_id,amount+FROM+bets+LIMIT+3&default_format=JSON"

# JSONEachRow – für zeilenweise Verarbeitung (speicherschonend)
curl "http://localhost:8123/?query=SELECT+user_id,amount+FROM+bets+LIMIT+3&default_format=JSONEachRow"

# CSV – für Export nach Excel/Google Sheets
curl "http://localhost:8123/?query=SELECT+user_id,amount+FROM+bets+LIMIT+3&default_format=CSV"

# TabSeparated – für Weiterleitung an andere Tools (grep, awk)
curl "http://localhost:8123/?query=SELECT+user_id,amount+FROM+bets+LIMIT+3&default_format=TSV"

Praxisbeispiel: Wir senden Aggregate an einen Telegram-Bot. Wir verwenden JSONEachRow, parsen es in Python mit einem einzigen response.json() und formatieren es in eine Nachricht.

Erstellen einer Datenbank für eine Wettplattform

CREATE DATABASE IF NOT EXISTS betting;

Und sofort zu ihr wechseln:

clickhouse-client --database betting

Oder innerhalb des Clients:

USE betting;

Erste Tabelle: Wett-Schema aus einem echten Projekt

In meinem Produktionsprojekt für Wettanalysen sieht die Tabelle so aus:

CREATE TABLE betting.bets
(
    user_id     UInt64,
    created_at  DateTime64(3),
    amount      Decimal(18, 2),
    odds        Float64,
    sport       LowCardinality(String),
    outcome     Enum8('win' = 1, 'loss' = 2, 'void' = 3),
    event_id    UInt64,
    bet_type    String
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(created_at)
ORDER BY (created_at, user_id);

Warum so:

  • LowCardinality für Sport – Fußball, Basketball, Tennis. Sie wiederholen sich tausendfach, komprimiert in ein Wörterbuch.
  • Enum8 für Ergebnis – nur drei Werte, benötigt 1 Byte statt eines Strings.
  • DateTime64(3) – Millisekunden sind wichtig für Live-Wettanalysen.

Häufiger Anfängerfehler: Vergessen, ENGINE = MergeTree() anzugeben. Ohne dies erstellt ClickHouse eine Tabelle mit der TinyLog-Engine (nur zum Testen), die nicht partitioniert werden kann und keine Replikation unterstützt. In der Produktion würde das Einfügen von 10 Millionen Zeilen in eine solche Tabelle sie zerstören.

Einfügen von Testdaten

Einzelner Datensatz

INSERT INTO betting.bets (user_id, created_at, amount, odds, sport, outcome, event_id, bet_type)
VALUES (1001, now(), 50.00, 2.1, 'football', 'win', 50001, 'single');

Mehrere Datensätze (Batch-Einfügung)

INSERT INTO betting.bets VALUES
(1002, now() - INTERVAL 1 HOUR, 100.00, 1.8, 'basketball', 'loss', 50002, 'single'),
(1003, now() - INTERVAL 2 HOUR, 200.00, 3.0, 'tennis', 'win', 50003, 'express'),
(1001, now() - INTERVAL 30 MINUTE, 75.00, 2.5, 'football', 'void', 50001, 'single');

Generieren von Testdaten mit numbers()

Für Auslastungstests generiere ich oft eine Million Datensätze spontan:

INSERT INTO betting.bets
SELECT 
    number % 10000 AS user_id,
    now() - INTERVAL (number % 86400) SECOND,
    (number % 1000) / 10 + 10,
    1.5 + (number % 200) / 100,
    arrayElement(['football', 'basketball', 'tennis', 'hockey'], (number % 4) + 1),
    CAST((number % 3) + 1 AS Enum8('win' = 1, 'loss' = 2, 'void' = 3)),
    number,
    'single'
FROM numbers(1000000);

Wichtiger Hinweis: Diese Einfügung wird auf einem anständigen Server 5-10 Sekunden dauern. ClickHouse ist für solche Massenvorgänge optimiert, aber auf einer schwachen VM kann es eine Minute dauern.

Grundlegende SELECT-Abfragen im Kontext von Wetten

WHERE – Filtern

-- Wetten eines bestimmten Benutzers in der letzten Stunde
SELECT *
FROM betting.bets
WHERE user_id = 1001 
  AND created_at >= now() - INTERVAL 1 HOUR;

-- Gewinnwetten mit Quoten über 2.0
SELECT user_id, amount, odds, amount * odds AS payout
FROM betting.bets
WHERE outcome = 'win' AND odds > 2.0;

ORDER BY – Sortieren

-- Größte Wetten heute
SELECT user_id, amount, created_at
FROM betting.bets
WHERE created_at >= today()
ORDER BY amount DESC
LIMIT 10;

-- Letzte 5 Wetten eines Benutzers
SELECT created_at, sport, amount, odds, outcome
FROM betting.bets
WHERE user_id = 1001
ORDER BY created_at DESC
LIMIT 5;

GROUP BY – Analysen

-- Auszahlungen nach Sportart für die Woche
SELECT 
    sport,
    count() AS total_bets,
    sum(amount) AS total_staked,
    sumIf(amount * odds, outcome = 'win') AS total_payout,
    round(total_payout / total_staked, 4) AS roi
FROM betting.bets
WHERE created_at >= today() - 7
GROUP BY sport
ORDER BY total_bets DESC;

Kombinieren von Bedingungen

-- Benutzer, die mehr als 10 Wetten an einem Tag platziert haben
SELECT 
    user_id,
    count() AS bets_count,
    sum(amount) AS total_amount
FROM betting.bets
WHERE created_at >= today()
GROUP BY user_id
HAVING bets_count > 10
ORDER BY total_amount DESC;

Praxisbeispiel: Verdächtige Muster finden

Hier ist eine echte Abfrage aus unserem Betrugserkennungssystem:

WITH hourly_bets AS (
    SELECT 
        user_id,
        toStartOfHour(created_at) AS hour,
        count() AS bets_per_hour,
        avg(amount) AS avg_bet
    FROM betting.bets
    WHERE created_at >= now() - INTERVAL 3 HOUR
    GROUP BY user_id, hour
)
SELECT 
    user_id,
    max(bets_per_hour) AS max_rate,
    avg(avg_bet) AS typical_bet,
    stddevPop(avg_bet) AS bet_variance
FROM hourly_bets
GROUP BY user_id
HAVING max_rate > 100 AND bet_variance < 0.5;

Diese Abfrage findet Bots: solche, die mehr als 100 Mal pro Stunde mit fast identischen Beträgen wetten. In PostgreSQL mit 50 Millionen Datensätzen würde sie nie fertig werden. ClickHouse liefert die Antwort in 0,6 Sekunden.

Exportieren von Daten: Wenn Sie sie dem Geschäft zur Verfügung stellen müssen

# Export als CSV für die Marketingabteilung
clickhouse-client --query "
    SELECT user_id, sum(amount) AS total_bet, count() AS bet_count
    FROM betting.bets
    WHERE created_at >= '2024-01-01'
    GROUP BY user_id
    ORDER BY total_bet DESC
    LIMIT 1000
" --format CSV > top_users.csv

# Export als JSON für die API eines anderen Dienstes
curl "http://localhost:8123/?query=SELECT+user_id,sum(amount)+FROM+betting.bets+GROUP+BY+user_id+LIMIT+10&default_format=JSON" \
  -o top_users.json

Häufige Fehler und ihre Lösungen

Fehler: Code: 102. DB::NetException: Connection refused

Ursache: Falscher Host oder Port, oder der Server lauscht nicht auf externe Verbindungen.

Lösung: Überprüfen Sie netstat -tulpn | grep clickhouse. Wenn keine 0.0.0.0:9000 vorhanden ist, bearbeiten Sie config.xml:

<listen_host>0.0.0.0</listen_host>

Fehler: Code: 81. DB::Exception: Database betting doesn't exist

Ursache: Datenbank nicht erstellt oder --database nicht angegeben.

Lösung: CREATE DATABASE IF NOT EXISTS betting; oder verbinden mit --database betting.

Fehler: Code: 62. DB::Exception: Syntax error: failed at position 1

Ursache: Semikolon im Batch-Modus vergessen.

Lösung: Setzen Sie immer ; am Ende der Abfrage, wenn Sie --query verwenden.

Wie geht es weiter?

Jetzt wissen Sie, wie Sie sich auf jede Art mit ClickHouse verbinden, Tabellen erstellen, Daten einfügen und Abfragen ausführen. Im nächsten Artikel tauchen wir in fortgeschrittene Analysen ein: Fensterfunktionen, Arrays, Aggregationen und materialisierte Ansichten.

Alle Beispiele getestet mit ClickHouse 24.8. Wenn etwas nicht funktioniert, überprüfen Sie zuerst die Version: SELECT version(); Das hat mir hunderte Male geholfen.


Vorherige:
Nächste: ClickHouse: Vollständige Datentyp-Referenz für Wettanalysen (Woran ich mich verbrannt habe)

— Editorial Team

Advertisement 728x90

Weiterlesen