Die Menschen hinter den Produkten, Teil 7: Leo Giakoumakis – Test Lead, Query Optimizer

Endlich nehme ich meine Reihe mir den Interviews aus meiner Redmond-Zeit wieder auf. Eines der interessantesten Interviews habe ich mit Leo Giakoumakis – Test Lead, Query Optimizer geführt.

Gruß,
Steffen

Hallo Leo, schön Dich zu sehen. Dein Jobtitel lautet „Test Lead“. Kannst Du uns einen kurzen Überblick geben wer Du bist und wo Du herkommst?

Ich komme ursprünglich aus Griechenland. Danach habe ich ein paar Jahre in England gelebt, und seit 8 Jahren bin ich hier bei Microsoft in Redmond. Den größten Teil davon im Engine Team in der SQL Server Gruppe. Meine Rolle während der Katmai-Release (SQL Server 2008) war der Test Lead für den Query Optimizer. Es ist interessant, im Test einer so komplexen Komponente zu arbeiten.

Die normale Test-Position bei Microsoft heißt „Software Development Engineer in Test“ (SDE/T). Das finde ich interessant, denn die meisten Leute würden erst mal nicht annehmen, dass ein Tester ein Entwickler sein sollte. Warum ist das so?

Bei Microsoft, und insbesondere in einer Produktgruppe wie SQL Server kommen die Tester aus derselben Gruppe von Menschen wie Entwickler oder Program Manager – Menschen mit einem Abschluss in Informatik, Menschen, die Code schreiben. Der Grund für die Programmierkenntnisse ist, dass all unsere Tests automatisiert sind. Es gibt kaum manuelle Tests, in meiner Gruppe gar keine. Der Code, den wir entwickeln überprüft den Code auf verschiedene Art, validiert Korrektheit, Performance, Skalierbarkeit und solche Sachen. Für ein Produkt wie SQL Server ist die Menge an Testcode, den wir schreiben so groß sein wie ein kleineres Produkt. Wir haben also ähnliche Software-Engineering-Probleme: Code Reviews, Wartbarkeit, Korrektheit, Fehlerbehebung und so weiter. Damit Du eine Idee bekommst: Jedes Mal, wenn wir einen neuen Datentyp einführen, wie Date und Time in SQL Server 2008, müssen wir sicherstellen, dass die Indizierung funktioniert, dass Updates funktionieren, dass der Query Optimizer den richtigen Index für einen bestimmten Ausführungsplan verwendet und so weiter. Ein neuer Datentyp bedeutet also einen Bedarf an hundert Tests. Der Code im Produkt ist inzwischen so weit, dass die Einführung eines neuen Datentypen ziemlich einfach ist. Es gibt interne Strukturen zur Unterstützung von Datentypen, und der meiste Code kann das nutzen. In den letzten Jahren haben wir festgestellt, dass sich der Testcode auf einen ähnlichen Stand kommen muss, denn sonst ergeben 1000 Codezeilen eines Entwicklers 10000 Testfälle. Und das skaliert natürlich nicht. Daher sind wir inzwischen so weit, dass der Testcode eine ähnliche Abstraktion und ein ähnliches Modell wie der Produktcode hat. Dadurch können wir vorhandene Teststrukturen viel einfacher auf Erweiterungen im Produkt anpassen. Und daher kommt der Bedarf an guten Softwareentwicklern, das ist eine Herausforderung. In der Datenbankengine kommt dazu, dass der Tester die Technologie und ihre Arbeitsweise tiefgehend verstehen muss um sie zu validieren. Wenn man nur die Oberfläche betrachtet kann man nicht allzu viel erreichen. Daher also der „Software Development Engineer in Test“.

Schaut ein Tester eigentlich auch in den Quellcode, um die Wurzel eines Bugs oder Performanceproblems zu finden? Oder ist das Sache des Entwicklers?

Viele Tester gehen so weit. Da sind wir ein wenig flexibel. Manche Kollegen wollen die Quelle eines Problems finden, andere sagen, ihr Job ist getan wenn sie das Problem identifiziert haben und sie überlassen den Rest dem Entwickler. Die Tester sind da unterschiedlich weit Hardcore. Wir empfehlen, tief zu gehen und zu debuggen.

Für alle Features gibt es verschiedene Testfälle. Testet Ihr da wirklich jeden täglichen Build der Datenbankengine? (Daily Build: Normalerweise wird ein Produkt komplett einmal am Tag kompiliert und in ein Verzeichnislayout wie auf dem Auslieferungs-Datenträger gebracht)

Nicht jeder tägliche Build. Insbesondere die Katmai-Release wurde in kleinen virtuellen Teams erstellt, die die einzelnen Features implementiert haben. Diese Teams bestehen aus verschiedenen Rollen von verschiedenen Gruppen, etwa jemand vom Optimizer, jemand aus der Storage Engine, unterschiedliche Teile der Datenbankengine. Für so ein Team gibt es eine Gruppe von Tests, die sehr oft ausgeführt werden. Manche Tests laufen auf jeder Entwicklermaschine, andere Täglich oder wöchentlich, und sehr umfassende Tests laufen bevor dieses Feature in die SQL Server Haupt-Builds integriert wird. Es wäre zu aufwändig, jeden Test mit jedem Build auszuführen. Daher haben wir diesen mehrschrittigen Prozess.

Verwendet Ihr nur künstliche Tests oder auch echte Workloads von Kunden?

Typischerweise muss man die Dinge von beiden Seiten aus sehen. Für die Ingenieure ist es interessant, sich mit synthetischen Benchmarks und Tests zu beschäftigen, die auf spezifische Aspekte des Problems fokussieren. Aber am Schluss braucht man diese realistische Validierung. Typischerweise schauen wir also zuerst auf sehr spezifische Teile des Produkts. Wenn wir also zum Beispiel Statistiken im Query Optimizer testen dann erstellen wir zuerst Daten mit einer genau bekannten Verteilung, damit wir wissen wenn die Statistiken korrekt sind. Realistische Daten haben jedoch sehr komplexe Verteilungen, und damit müssen wir ebenso testen. Jede Art des Tests hat ein anderes Ziel. Der Ingenieur schreibt einen Test, der ein spezifisches Problem prüft. Er kennt den Test, er weiß was er testet und wenn er fehlschlägt weiß er, was schief läuft. Am Ende müssen wir aber echte Workloads ausführen um zu sehen, wie sich das System in seiner Gesamtheit verhält. Es kann ja sein, dass die Einzelteile gut funktionieren, aber ein Integrationspunkt Probleme macht, wenn alles zusammengefügt wird. Wir machen also beides. Wir versuchen, Kunden-Workloads ins Haus zu bekommen. Wir versuchen, sie auf die wichtigsten Abfragen, Aktionen und Teile zu reduzieren und verwenden sie dann als interne Benchmarks. Wir haben einige davon.

Es gibt ja auch viele externe Tester, wie das TAP Programm, öffentliche Betas, alles was auf Connect ( https://connect.microsoft.com ) steht. Wie arbeitet ihr damit? Ist es die Aufgabe Deines Teams, externe festgestellte Probleme zu valideren?

Unsere Rolle im Testteam ist es, die Brücke zwischen der Entwicklung und der Kundensicht zu bilden. Daten von Connect, von Hotfixen, aus Foren bekommen wir als Eingabe und überprüfen diese Szenarien. Der große Wert des TAP-Programms ist es zum Beispiel, dass dort Probleme gefunden werden, die wir im Haus nur sehr schwer nachstellen können. Über die Zeit prüfen wir dann, ob wir im Haus ähnliche Bedingungen aufbauen können, damit wir diese Art von Problemen früher finden können. Man braucht wirklich beides: interne und externe Validierung. Es ist auch eine Frage davon, wie gut man das nachstellen kann. Die Kunden haben hunderte Benutzer und Terabytes an Daten. Daraus müssen wir sehr fokussierte Tests erstellen. Das ist ein Prozess, der kontinuierlich weiterentwickelt wird.

Da Du am Test der Datenbankengine arbeitest: Gibt es irgendwelche Features oder Verhaltensweisen in der Datenbankengine von denen Du denkst, dass sie wichtig sind aber viele Kunden das nicht wissen?

Normalerweise versuchen wir, die guten Nachrichten zu überbringen (lacht). Im Query Optimizer haben wir einige Dinge getan, die für Kunden im Data Warehousing Bereich und für große Datenbanken sehr nützlich sind. Insbesondere ist da die verbesserte Parallelität bei Abfragen über partitionierte Tabellen zu nennen. Kunden mit partitionierten Tabellen auf Maschinen mit vielen Prozessorkernen sollten einen signifikanten Performancevorteil sehen, in einigen Fällen um Faktoren.

Aus Test-Sicht ist es immer unsere Aufgabe sicherzustellen, dass Fortschritte die wir einbauen einen insgesamt positiven Effekt haben – ohne Regressionen zur Folge zu haben. Das ist manchmal ein Kompromiss: In den häufigen Szenarien sollte immer eine Verbesserung zu sehen sein, und wenn es dadurch in anderen Bereichen Verschlechterungen gibt, dann dürfen die nur in Randszenarien auftreten und nicht das Kundenerlebnis negativ beeinflussen.

Ich kann Dir dazu eine Grafik zeigen: Das ist ein zufälliger Punkt während der Entwicklung von SQL Server 2008 (keine CTP oder Release-Version!). Es ist nach dem Punkt, wo die Haupt-Performanceverbesserungen eingecheckt wurden. Das ist nicht repräsentativ für die RTM-Version von SQL Server 2008. Es ist ein Zwischenstand in der Entwicklung.

clip_image002[4]

Die Grafik ist so zu lesen: Jeder Datenpunkt ist eine Abfrage aus einer echten Kunden-Workload. Auf der X-Achse sieht man die Zeit, die die Abfrageausführung dauert. Links sind also sehr schnelle Abfragen, die weniger als eine Minute gebraucht haben, die Abfragen rechts dauerten mehr als eine Stunde. Die Y-Achse zeigt die Performanceverbesserung auf einer logarithmischen Skala. Alles um die 1 auf der Y-Achse ist im Wesentlichen unverändert: Keine Verbesserung, keine Verschlechterung. Viele Abfragen, insbesondere die mit langer Laufzeit sind deutlich schneller geworden, bis zu zehn Mal so schnell. Das liegt an den Performanceverbesserungen für große Datenbanken. Dann siehst Du einige Abfragen zwischen 0,5 und 1. Das liegt an einem grundsätzlichen Problem der Abfrageoptimierung: Es ist unmöglich, fundamentale Verbesserungen einzupflegen ohne ein gewisses Maß an Regression bei anderen Abfragen zu bekommen. Um einen besseren Ausführungsplan zu bekommen muss man mehr arbeiten, und daher verlängert sich die Kompilierzeit in einigen Fällen. Das kann bei einigen Abfragen einen signifikanten Anteil an der Ausführungszeit darstellen. Aber für Abfragen mit langer Ausführungszeit können wir es uns leisten, etwas länger zu kompilieren. Unser Job ist es, bei jedem Release ein angemessenes Bild in dieser Grafik zu haben. Wie schon gesagt, die abgebildete Grafik war während der Entwicklung: Es gibt da noch ein paar Ausreißer nach unten, die wir in der Folge behoben haben. Mehr findet sich in diesem Dokument: https://sites.computer.org/debull/A08mar/giakoumakis.pdf

Danke, ich verstehe. Am Ende ist es doch so: Sobald man Programmcode zu irgendeinem Programm hinzufügt fügt man auch mehr Prozessortakte hinzu, die ausgeführt werden müssen.

Genau. Und in Datenbanken ist das ein statistisches Problem, denn die Eingaben sind statistisch verteilt, der Optimizer verwendet Näherungsalgorithmen. Man kann nicht immer die bestmögliche Lösung finden, man muss eine „gut genug“ Lösung finden. Daher sind die Folgen für eine einzelne Abfrage nicht immer positiv.

Wenn Du an die Kundenworkloads denkst, die Ihr untersucht: Gibt es da Dinge, die die Kunden nicht mehr tun sollten, weil sie den Optimizer und die Verbesserungen, die Ihr eingebaut habt behindern?

Ja, es gibt einige „bad practices“, die unglücklicherweise aus der Reichhaltigkeit der SQL-Sprache resultieren und die eine ordentliche Arbeit des Query Optimizers verhindern. Dazu gehören komplexe Ausdrücke in einer Abfrage. Die vereinfachen zwar die Programmierung, aber es ist schwerer für den Optimizer, solche Ausdrücke abzuschätzen. Wenn man zum Beispiel schreibt WHERE colC + 10 > 5, so ist es für den Optimizer schwer zu wissen, was colC + 10 ist. Es ist viel einfacher, wenn da WHERE colC > -5 steht. Das ist jetzt ein sehr einfaches Beispiel. Aber grundsätzlich gilt: Je komplexer die Ausdrücke, desto schwerer ist die Aufgabe der Abfrageoptimierung. Für einfache Abfragen oder für Abfragen mit geringen Datenmengen ist das nicht wirklich wichtig. Aber insbesondere für Abfragen über große Datenbestände sollten die Ausdrücke so einfach wie möglich gehalten werden. Komplexe Ausdrücke kann der Optimizer kaum abschätzen. Mit abschätzen meine ich: Wie viele Zeilen betrifft die Abfrage, wie viele Zeilen werden gefiltert und so weiter. Schlecht sind auch lokale Variablen in teuren Abfragen, sowas wie DECLARE @var; SET @var = wert;. Dieser Ausdruck wird zur Laufzeit ausgewertet. Zur Kompilierzeit hat der Compiler sehr wenige Informationen über den Wert dieser Variable. Er kann also nur raten. Wenn hingegen die Variable von einer Stored Procedure kommt, dann wird sie zur Kompilierzeit ausgewertet und die Variable hat eine sehr gute Schätzung. Das sind wohlbekannte Probleme, über die schon viel gebloggt wurde, aber wir sehen so etwas immer noch. Mehr Informationen gibt es auch in unserem Blog: https://blogs.msdn.com/sqlqueryprocessing

Wie bist Du aus dem sonnigen Griechenland hierher gekommen, wo es normalerweise regnet?

Ich war schon in anderen wolkigen Orten. Ich habe für Digital und dann Compaq in der Nähe von London gearbeitet. Ich habe bereits in England studiert und dann da vier Jahre gearbeitet. Ich habe schon als Kind viel mit Computern gespielt und habe schon damals davon geträumt, zu Microsoft zu kommen. Später habe ich mich dann einfach beworben.

Hast Du ein Verhältnis zwischen der Anzahl Entwickler und der Anzahl Tester in der SQL Produktgruppe?

Wir haben ein Ziel: Für je 10 Entwickler soll es 7-8 Tester geben. Das ist eine ziemlich hohe Zahl. Der Grund ist, dass Tester hier eine etwas andere Rolle haben als in anderen Firmen oder bei anderen Produkten. Wir beeinflussen die Entwicklung vom ersten Tag des Softwaredesigns bis zur Fertigstellung, wir haben zusätzliche Aufgaben die in anderen Produkten unnötig sind.

Diese Zahl ist schwer einzuhalten, denn wir wollen die Besten und Klügsten haben. Die Rolle des Testers wird aber manchmal als zweitklassig wahrgenommen. Daher ist es kompliziert, gute Mitarbeiter zu überzeugen, dass sie in dieser Test-Rolle bis auf die höchsten Karrierestufen wachsen können, dass sie auch Einfluss haben, das Design vorantreiben indem sie es überprüfen. Für einen Manager, der sein Team besetzen will ist das ein schwieriges Problem.

Tester sind also bereits Teil bei der Spezifikation von neuen Features?

Ja. Für jedes Feature gibt es ein virtuelles Team, mit Mitarbeitern aus verschiedenen Komponenten des Produkts und aus verschiedenen Rollen. Dieses Team definiert den Umfang des Features – wir nennen das Verbesserung („improvement“), es gibt mehrere Features in einem Improvement – und bewertet die Spezifikation. Wenn die Spezifikation definiert ist überlegen sich die Entwickler das Design und erstellen Design-Spezifikationen, die Tester überlegen, wie es getestet werden kann. Oft müssen wir die Funktionalität verbessern um sie besser testbar zu machen. Auch wie der Support durch CSS (den Microsoft Support) später aussehen kann ist wichtig. All das gehört dazu, die Kundenprobleme zu lösen und ist Teil der Erfolgskriterien, wenn das Feature fertig ist. Wir brauchen also Mitarbeiter aus allen Rollen, die Experten für das Feature werden, es vorantreiben, es später weiterentwickeln und supporten können. So funktioniert im Grundsatz der Entwicklungsprozess bei SQL Server.

Danke für Deine Zeit, Leo