Wie ein KI-Agent einen dreijährigen Performance-Bug in einer Query-Engine aufspürte

Deine Reaktion:

Ein Team von PostHog in Lissabon ließ einen KI-Agenten auf ihre Datenbank-Query-Engine los. Der Agent fand einen Bug, der fast drei Jahre lang unentdeckt in der Codebasis lag. Der Fix verbesserte die Performance deutlich – ohne Änderung der Abfragelogik.

Die Grundidee stammt von Andrej Karpathy. Im März 2026 veröffentlichte er das Repository „Autoresearch“. Der Kern: ein KI-Agent bekommt ein kleines System, einen Benchmark und ein Budget. Er durchläuft eine Schleife: eine Änderung vorschlagen, den Benchmark ausführen, Verbesserungen behalten und Verschlechterungen verwerfen. Karpathy ließ den Agenten zwei Tage auf einem kleinen neuronalen Netz laufen. Er fand rund zwanzig Änderungen, die den Validierungsfehler senkten. Einige übertrugen sich auf größere Modelle. Das Prinzip ist nicht neu – DeepMind veröffentlichte 2023 FunSearch, Sakana 2024 den AI Scientist. Karpathys Version ist jedoch konkret genug, um an einem Nachmittag eine eigene Implementierung zu bauen.

Das PostHog-Team nutzte diesen Ansatz für ein Hackathon-Projekt auf einem Offsite. Ziel: die Performance von ClickHouse automatisieren, der Datenbank hinter ihrer Produktanalytik. Sie verwendeten pi, einen Terminal-Coding-Agenten von Mario Zechner, der mit jedem LLM spricht. Dazu kam pi-autoresearch, eine Community-Erweiterung von davebcn87, die Karpathys Schleife in pi integriert. Darüber bauten sie eine Kampagnen-Orchestrierung, die den Optimierungsprozess strukturiert, damit der Agent systematisch vorgeht.

Der Aufbau: Eine Kampagne hat eine langsame Query und einen Git-Branch. Sie ist in Lanes unterteilt – Optimierungsrichtungen wie Prädikatsreihenfolge, JSON-Parsing, Zeitzonen-Handling, Primärschlüssel-Nutzung. Jede Lane enthält eine konkrete, testbare Hypothese. Jede Hypothese wird in einem Experiment mit genau einem Durchlauf, Benchmark und Urteil getestet. Nach jedem Experiment muss der Agent eine Reflexion durchführen. Dazu kommt ein eigener ClickHouse-Testcluster mit denselben Daten wie die Produktion, aber anonymisiert und auf günstigerer Hardware. So bleibt die Iterationsgeschwindigkeit hoch und Kundenabfragen werden nicht gestört.

Das Team fütterte dem Agenten zunächst händisch langsame Queries – solche, über die sie sich bereits geärgert hatten, und solche aus system.query_log. Eine dieser Queries war ein Trichter über sieben Tage für ein echtes Team. Hier stieß der Agent auf den sogenannten „Drei-Jahres-Bug“.

ClickHouse ist schnell, weil es Arbeit überspringen kann. Die Tabelle events ist nach toYYYYMM(timestamp) partitioniert. Der Primärschlüssel ist (team_id, toDate(timestamp), event, …). Eine gut geschriebene Query mit Zeitstempel-Filter sollte ClickHouse erlauben, ganze Monate zu überspringen (Partition Pruning) und direkt zur richtigen Woche zu springen. Das passierte nicht. Im April 2023 hatte das Team Zeitzonen-Unterstützung für HogQL hinzugefügt. Der vernünftige Weg: Jeden Verweis auf timestamp in toTimeZone(timestamp, team_tz) wickeln. Was sie nicht bedachten: Der ClickHouse-Queryplaner kann nicht durch toTimeZone() hindurchsehen. Er kann nicht ableiten, dass die Bedingung toTimeZone(timestamp, tz) >= '2024-03-01' bedeutet, dass toYYYYMM(timestamp) auf bestimmte Monate reduziert werden kann. Partition Pruning war ausgeschaltet. Auch der Primärschlüssel toDate(timestamp) wurde nicht genutzt – er beschränkte sich auf team_id und event und hörte dann auf.

Warum der Bug nicht früher auffiel? ClickHouse hat einen MinMax-Skip-Index auf timestamp. Ein MinMax-Index speichert den kleinsten und größten Wert einer Spalte pro Granula (8192 Zeilen). Vergleicht man toTimeZone(timestamp, tz) mit einer Konstanten, kann ClickHouse pro Granula prüfen, ob der Bereich überlappt, und Granulas ohne Treffer überspringen. Das ist viel schwächer als Partition Pruning, aber es funktioniert. Queries waren nicht katastrophal langsam – nur messbar langsamer als sie sein sollten. Diese Art Bug versteckt sich: Sie ist langsam, aber nicht alarmierend. Jede Query ist betroffen, niemand kann einen A/B-Vergleich mit einer „guten“ Version machen. Der Beweis liegt in der Ausgabe von EXPLAIN PLAN indexes=1, json=1, die niemand ausführt, es sei denn, er vermutet bereits etwas.

Der Agent führte genau dieses EXPLAIN aus. Er bemerkte Partition: Condition='true' (kein Pruning) und probierte zwei Ansätze: Erstens indexHint() mit nackten Zeitstempel-Grenzen, zweitens die Umschreibung des Vergleichs, sodass auf der Feldseite der nackte timestamp steht und die Konstante die Zeitzone trägt. Der zweite Ansatz gewann deutlich. Die Semantik ist identisch – toTimeZone() ändert nur die Anzeige-Metadaten, der Unix-Timestamp bleibt gleich. Der Planer sieht jetzt einen nackten timestamp und kann arbeiten. Auf der Benchmark-Query über sieben Tage: beste Laufzeit von 2.824 ms auf 2.192 ms (–22%), getrimmter Mittelwert der mittleren drei Läufe von 4.694 ms auf 2.954 ms (–37%), Anzahl der vom Skip-Index gescannten Granulas von 60.683 auf 23.291 (–62%).

Der Geschwindigkeitszuwachs ist am größten bei kurzen Zeiträumen, weil Partition Pruning dort am meisten bringt. Bei einem 90-Tage-Zeitraum ist die relative Verbesserung kleiner, aber messbar. Die Granula-Reduktion ist bei jedem Zeitraum real – sie übersetzt sich nur in kleinere Wanduhr-Verbesserungen, wenn absolut mehr Granulas gescannt werden müssen.

Das Team handelte während des Hackathons noch händisch. Sie bauen jetzt eine Pipeline, die das automatisiert: Sie holt langsame Queries aus system.query_log, startet pro Kandidaten-Query eine Sandbox, lässt pi-autoresearch laufen, dedupliziert die Vorschläge per LLM und lässt einen anderen Agenten (PostHog Code) die eigentliche Änderung mit Tests und Benchmarks in die Codebasis schreiben. Die Pull-Requests landen im Team-Slack, wo ein Mensch sie prüft und merged.

Das zeigt: Selbst in einer gut gewarteten Codebase überleben subtile Performance-Probleme über Jahre, einfach weil kein Mensch den Anreiz oder die Zeit hat, sie systematisch zu suchen. Ein KI-Agent hat diese Nachteile nicht. Er hat keine Betriebsblindheit. Er behandelt einen dreijährigen Ausdruck mit derselben Skepsis wie die Zeile von gestern. Die Methode ist nicht auf langsame Queries beschränkt. Wenn du eine Metrik in deinem System hast, die du stillschweigend tolerierst – Geschwindigkeit, Speicher, Kosten, Genauigkeit, Fehlerrate – baue eine Testumgebung, setze einen Agenten darauf, und schau, was zurückkommt.

Quelle: posthog.com

Deine Reaktion:
Artikel teilen:
Sebastian Krötzsch
Autor

Sebastian Krötzsch

Sebastian Krötzsch schreibt auf sebask.de über Künstliche Intelligenz, Automatisierung, digitale Systeme und die Frage, was davon im Alltag wirklich nützlich ist. Ohne Buzzword-Nebel, dafür mit klarem Blick auf Praxis, Tools und echte Wirkung.