Möchten Sie BigQuery nutzen? Lesen Sie hier wie…

7 min read

BigQuery

Man hat vor kurzem angefangen, BigQuery zu verwenden, und man muss zugeben, dass man sich in die DB verlieben könnte… Dieser Artikel ist ein Versuch, die Technologie dahinter zu erklären, die Anforderung ist, die DB in Bezug auf Kosten und Leistung effizient zu nutzen.

BigQuery ist die öffentliche Umsetzung von Dremel, die von Google zur allgemeinen Verfügbarkeit gestellt hat.

Dremel ist Googles Abfrage-Engine und kann SQL-Abfragen in einen Ausführungsbaum verwandeln, der Daten aus Googles verteiltem Dateisystem liest. Dremel verfügt über eine hohe Skalierbarkeit und ist in der Lage, die Ergebnisse der Abfragen trotz der Größe des Datensatzes innerhalb von Sekunden (oder innerhalb weniger Sekunden) zurückzugeben.

BigQuery stellt die Kernfunktionen von Dremel für Dritte, über eine REST API, eine Kommandozeile und ein Web-UI zur Verfügung.

Aber BigQuery ist ein bisschen mehr als Dremel…

Tatsächlich nutzt BigQuery mehrere Technologien, die bei Google entwickelt wurden.

Zunächst nutzt es Borg (Googles Cluster-Management-System), um die Rechenkapazität für die Dremel-Jobs zuzuweisen. Dremel-Jobs lesen Daten von Googles Dateisystemen mit Jupiter, dem Hochgeschwindigkeitsnetz von Google, das Daten mit 10 Gbps austauscht.

Dank seiner Architektur benötigt BigQuery keine Indizes, die Daten werden in einem proprietären Kolumnar-Format gespeichert, das auch Colossus (Googles Dateisystem) genannt wird (mehr dazu später), und jede Abfrage führt einen vollständigen Scan der angepeilten Tabelle durch.

Die Erhöhung der Belastung wird hauptsächlich durch das Hinzufügen von Servern gesteuert. Dies wird transparent für den Benutzer gehandhabt, der keine “Server hinzufügen” oder “größere Maschinen” in der Art und Weise verwendet, wie er z.B. Redshift oder Postgres verwenden würde.

Die Begriffe “keine Indizes” und “vollständige Scans” sind normalerweise keine Synonyme für “schnell sein”. Warum ist BigQuery also so schnell?

Vor allem dank zweier Faktoren:

  • Spaltenspeicher: Die Daten werden von Spalten gespeichert und ermöglichen so ein sehr hohes Kompressionsverhältnis und Scan-Durchsatz.
  • Baumarchitektur: Eine Baumausführungsarchitektur wird verwendet, um Abfragen und Aggregatergebnisse über Tausende von Maschinen zu versenden.

Säulenspeicher

Als Analytics DB ist das BigQuery-Speicherformat für den Zugriff auf wenige Spalten für eine sehr große Anzahl von Zeilen optimiert. Aus diesem Grund wird der Speicher von Spalten durchgeführt, so dass Sie nur auf weniger und unterschiedliche Speichermengen zugreifen (was noch schneller ist, da Sie parallel auf sie zugreifen können).

Das Datenmodell ist eng mit Protokollpuffern verbunden, mit notwendigen, wiederholten und optionalen Feldern.

Um Informationen in einer zusammenhängenden Art und Weise zu speichern, stellen wir das Konzept der Wiederholungsebene und Definitionsebene vor.

  • Wiederholungsebene: Die Höhe des Nestes auf dem Pfad, auf dem die Wiederholung stattfindet.
  • Definitionsebene: Wie viele optional/wiederholte Felder im Pfad definiert wurden.

Nehmen wir ein Beispiel, stellen wir uns vor, wir haben folgende Tabellendefinition:

message Book {
 required string title,
 repeated string author,
 repeated group price {
   optional int64 discount,
   optional int64 usd,
   optional int64 eur,
 }
}

und wir haben drei Aufzeichnungen:

Book1:
 author: "AAA"
 title: "firstTitle"
 price:
  discount: 0
  eur: 11
  usd: 12
Book2:
 author: "BBB"
 author: "CCC"
 author: "DDD"
 title: "secondTitle"
Book3:
 title: "thirdTitle"
 price:
  discount: 0
  eur: 11
 price:
  discount: 1
  eur: 11

Lassen Sie uns die Wiederholungs- und Definitionsebene für jeden Wert berechnen. Wir werden auch explizite Nullwerte für die fehlenden optionalen Felder hinzufügen.

Book1:
 author: "AAA"          R: 0, D: 1
 title: "firstTitle"    R: 0, D: 1
 price:
  discount: 0           R: 0, D: 2
  eur: 11               R: 0, D: 2
  usd: 12               R: 0, D: 2
Book2:
 author: "BBB"          R: 0, D: 1
 author: "CCC"          R: 1, D: 1
 author: "DDD"          R: 1, D: 1
 title: "secondTitle"   R: 0, D: 1
 (price):
  (discount: null)      R: 0, D: 0
  (eur: null)           R: 0, D: 0
  (usd: null)           R: 0, D: 0
Book3:
 title: "thirdTitle"   R: 0, D: 1
 (author: null)        R: 0, D: 0
 price:
  discount: 0          R: 0, D: 2
  eur: 11              R: 0, D: 2
  (usd: null)          R: 0, D: 1
 price:
  discount: 1          R: 1, D: 2
  eur: 11              R: 1, D: 2
  (usd: null)          R: 1, D: 1

Wiederholungsebene ist immer null, wenn es keine Wiederholung gibt, wenn ein Feld wiederholt wird, wie der Autor im zweiten Datensatz, R ist 1, weil die Wiederholung auf der ersten wiederholten Ebene stattfindet, das gleiche gilt für den Preis im dritten Datensatz.

Definitionsebene sind recht einfach, zum Beispiel im ersten Datensatz price.discount hat 2, weil sowohl Preis als auch Rabatt definiert sind. Auf der anderen Seite ist in Datensatz 3 die letzte null price.usd D gleich 1, weil der Preis definiert ist, aber price.usd nicht.

Jede Spalte wird als eine Reihe von Blöcken gespeichert, wie:

compressed value, R, D

R und D werden nur bei Bedarf gespeichert und können nicht abgeleitet werden. Null-Werte lassen sich ableiten, da für sie D immer eine Zahl niedriger ist als die Summe der wiederholten und optionalen Felder im Feldpfad (wie man am Beispiel sehen kann).

Aus den gespeicherten Informationen lässt sich jeder Datensatz für jede abgefragte Spalte einfach parallel rekonstruieren.

Betrachten wir zum Beispiel die price.eur Spalte. Auf dem Speicher werden wir haben:

11 R: 0, D: 2
NULL R: 0, D: 0
11 R: 0, D: 2
11 R: 1, D: 2

Beim Scannen der Spalte, jedes Mal, wenn R null ist, stoßen wir auf einen neuen Datensatz.  Wenn R größer als 0 ist, haben wir Wiederholungen im selben Datensatz. Wie bereits erklärt, kann D für null Werte verwendet werden. Durch die Überquerung der Säule erhalten wir:

Book1:
 price:
  eur: 11
Book2:
 price:
  eur: null
Book2:
 price:
  eur: 11
 price:
  eur: 11

Der Spaltenspeicher bringt auch Vorteile, da er es Ihnen ermöglicht, jede Spalte zu komprimieren. Zwei Klassiklösungen sind bitmaps und run-length Encoding (RLE).

Stellen wir uns vor, Sie haben eine Spalte, die aus n-Zeilen besteht, mit k– unterschiedlichen Werten. Am Beispiel des vorherigen Beispiels haben Sie die price.eur Spalte mit den folgenden Werten (n = 10, k = 5)

[10.0, 10.0, 8.99, 8.99, 7.0, 6.0, 7.0, 6.0, 2.0, 2.0]

Diese Spalte kann leicht mit k bitmaps (eine für jeden einzelnen Wert) der Länge n (Reihenlänge) komprimiert werden, wobei Sie ein eingestelltes Bit in der Position eines bestimmten Wertes haben, wenn dieser Wert in der Zeile ist.

price.eur: 10.0 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
price.eur: 8.99 [0, 0, 1, 1, 0, 0, 0, 0, 0, 0]
price.eur: 7.0  [0, 0, 0, 0, 1, 0, 1, 0, 0, 0]
price.eur: 6.0  [0, 0, 0, 0, 0, 1, 0, 1, 0, 0]
price.eur: 2.0  [0, 0, 1, 1, 0, 0, 0, 0, 1, 1]

Die Bitmaps können anstelle der eigentlichen Spalte gespeichert werden. Der Vorteil ist noch größer, wenn man an Selektions-, Aggregations-und Projektionsmuster denkt. In Analyse-DBs können Abfragen (wie unten)

direkt ausgeführt werden, indem die Bitmaps für die Werte = 4,0 und < 3,0 geladen werden und bitweise AND ausgeführt wird.

Mit RLE kann die Komprimierung noch verbessert werden. Was Sie in diesem Fall tun, ist die Darstellung der Sequenzen 0 und 1. Zum Beispiel würden die ersten drei Bitmaps wie folgt aussehen:

price.eur: 10.0 – 0,2 (0 0s, 2 1s, rest 0s)
price.eur: 8.99 – 2,2 (2 0s, 2 1s, rest 0s)
price.eur: 7.0 – 4,1,1,1 (4 0s, 1 one, 1 zero, 1 one, rest 0s)

Wie Sie sich vorstellen können, ist die Effizienz dieser Art von Techniken stark von verschiedenen Faktoren abhängig, wie z.B. Zeilenbestellung, Spaltenarten und Verwendung. Was Capacitor tut, ist der Versuch, eine intelligente Datenstimmung zu finden, mit dem Ziel, die Datenspeicherung und Datenabfrage zu optimieren.

Diese Wahl hat auch einige Nachteile. Zum Beispiel funktioniert es schlecht für Updates. Dremel löst es, indem er keine Update-Operation unterstützt.

Baumarchitektur für die Abfrage

Jede SQL-Anweisung nimmt als Eingabe eine oder mehrere verschachtelte Tabellen und deren Schemata und erzeugt eine verschachtelte Tabelle und ihr Ausgabeschema.Die Idee der verschachtelten Datenstruktur wird verwendet, um das Impedanz-Fitverhältnis zu verringern (auch um das Missverhältnis zwischen Objekten im Anwendungscode und DBs Datendarstellung zu verringern).

Ein verschachteltes Ergebnis wird immer erzeugt, obwohl in der Abfrage kein Datensatzkonstruktor angegeben ist.

Nehmen wir ein Beispiel mit einer SQL-Abfrage, die Folgendes ausführt: Projektion (AS), Auswahl (SELECT / FROM / WHERE) und Aggregation innerhalb eines Datensatzes (COUNT-WITHIN).

Die Abfrage gibt etwa Folgendes zurück:

Book: Book1
price:
 discountCnt: 1
 str: "AAA,firstTitle"

Wenn man an die verschachtelten Einträge, als beschrifteten Baum denkt, dann:

  • Auswahl: WHERE entfernt Verzweigungen, die nicht den Bedingungen entsprechen, während SELECT-Werte auf der gleichen Ebene produziert wie das am meisten wiederholte Feld, das im Ausdruck verwendet wird.
  • Aggregation: COUNT/WITHIN führt mit in Datensatz Aggregation, zählt die Vorkommen von Rabatten im Preisbereich.

Aber wie wird die Abfrage durchgeführt?

Die Antwort ist: Mit einem Baum-Ausführungsansatz.

Der Wurzelknoten empfängt die Abfrage, liest die Tabellenmetadaten und leitet die Abfrage auf die nächste Ebene um. An der unteren Ebene sind die Blattknoten diejenigen, die mit dem verteilten Dateisystem interagieren, die tatsächlichen Daten abrufen und sie in der Baumstruktur weiterverbreiten.

Nehmen wir als Beispiel an, dass Sie Folgendes ausführen:

Der root node erhält alle Partitionen (möglicherweise sind einige von Ihnen mit dem Begriff  “Shards” besser vertraut), aus denen T besteht, als schreibt die Abfrage wie

dabei sind R1iR1n die Ergebnisse der Abfragen, die an die Knoten auf Ebene 1 gesendet wurden. Insbesondere:

Wobei T1i das Tablet (Shard von T) ist, das von Server i in der ersten Ebene des Ausführungsbaums verarbeitet wird.

Die Abfrage wird modifiziert und auf die folgende Ebene gedrückt, bis sie die Blätter erreicht. Die Blätter lesen die eigentlichen Spaltendaten aus den Partitionen, dann wird alles wieder an die Wurzel weitergegeben.

Es ist zu beachten, dass die Datenmenge, die von den Blättern gescannt wird, ist die Datenmenge, die die Kosten beeinflussen, die Sie für die Abfrage zahlen.

In Bezug auf die Partitionierung bestimmt BigQuery die optimale Anzahl von Partitionen für eine Tabelle beim Laden der Daten. Die Zahl wird dann auf der Grundlage des Datenzugriffs und des Abfragemusters  abgestimmt.

Query-Dispatcher

In der Regel werden mehrere Abfragen zur gleichen Zeit ausgeführt, ein Query-Dispatcher plant Abfragen und gleicht die Last aus.

Die Datenmenge, die in jeder Abfrage verarbeitet wird, ist in der Regel größer als die Anzahl der zur Ausführung verfügbaren Verarbeitungseinheiten (Slots). Ein Slot entspricht einem Ausführungsthread auf einem Blattserver. In der Regel passiert, dass jeder Slot mehreren Tabletten zugeordnet wird. Bei der Ausführung von Abfragen berechnet der Dispatcher Histogramme der Verarbeitungszeiten der Tablets und er kann entscheiden, Tablets neu zu planen, deren Verarbeitung zu lange dauert.

Was die Replikation betrifft, so wird jedes Tablet in der Regel dreifach repliziert, wenn also eines von ihnen nicht zugänglich ist, greift der Blattserver auf eine andere Replik zu.

Lassen Sie uns einige Mathematik verwenden, um zu verstehen, wie dieser Mechanismus so schnell bei der Durchführung von Abfragen sein kann.

Nehmen wir an, Sie haben eine Tabelle mit 50TB Daten, 10 Spalten und 1000 Partitionen. Unter Berücksichtigung des zuvor beschriebenen Spaltenspeichers haben Sie 10 Dateien zu je 1000 Tablets.

Nehmen wir an, Sie führen ein SELECT * auf der Tabelle aus.

Wenn Sie 2000 Slots haben, muss jeder Slot 5 Dateien (10×1000/2000) der Größe 5 GB lesen. Das sind insgesamt 25 GB, die parallel gelesen werden können. Angesichts der Geschwindigkeit des Jupiter-Netzwerks können diese Daten in etwa 20 Sekunden bedient werden.

Praktische Überlegungen

Gehen wir durch einige praktische Überlegungen, die sich aus dem Verständnis der Technologie hinter BigQuery ziehen lassen.

  1. Minimieren Sie die Menge an gescannten Daten: Führen Sie niemals ein SELECT * aus. Wenn dies im Allgemeinen für Analyse-DBs zutrifft, gilt dies für BigQuery und dessen Pay-per-Query-Richtlinie. Wählen Sie die gewünschte Spalte sorgfältig aus. Darüber hinaus können Sie mehrere Strategien anwenden, um die Datenmenge zu reduzieren, wie zum Beispiel die Verwendung von partitionierten Tabellen.
  2. Keine Löschungen: Wenn Sie einen Fehler gemacht haben, können Sie eine Spalte nicht löschen oder umbenennen … Sie können nur den Modus der Spalte von REQUIRED zu NULLABLE ändern. Sie können jedoch immer noch eine Spalte entfernen oder umbenennen. Sie können zum Beispiel eine Abfrage ausführen, die alle Spalten außer derjenigen auswählt, die Sie entfernen möchten, und eine neue Tabelle mit den Abfrageergebnissen erzeugt. Oder Sie können die vorhandene Tabelle in Google Cloud Storage (GCS) ablegen und sie ohne die Spalte, die Sie entfernen oder umbenennen möchten, wieder importieren. Für jede dieser Optionen fallen Kosten an (Sie scannen die vollständige Tabelle, Sie erstellen neue Tabellen, sodass Sie zusätzlichen Speicherplatz benötigen).
  3. Externe Quellen: BigQuery kann mit seinen Abfragen auch externe Datenquellen gezielt ansprechen. Die unterstützten Quellen sind Bigtable, Google Cloud Storage und Google Drive. Die Daten werden ohne Vorbereitung in die Dremel-Engine geladen. Das kann zum Beispiel nützlich sein, wenn Sie Protokolle, die Sie auf GCS speichern, direkt abfragen wollen. Auf der anderen Seite führt das Targeting externer Daten zu einer geringeren Leistung im Vergleich zum Targeting von nativen Tabellen.

Fazit: Wir hatten einen Einblick darauf, wie BigQuery unter der Haube funktioniert. Insbesondere, wie das Speicherformat ist und der Abfrageausführungsmechanismus schnelle Analyseabfragen auf einer riesigen Datenmenge durchführen. Dann haben wir einige praktische Überlegungen angestellt zur Optimierung der Kosten- und Abfrageleistung unter Berücksichtigung der frisch gewonnen Erkenntnisse über die Architektur von BigQuery.

Haben Sie vor BigQuery in Ihrem Bereich oder Unternehmen einzusetzen?

Wo sehen Sie die Vorteile und Nachteile?

Welche Erfahrungen konnten Sie bisher mit BigQuery sammeln?

Gern beantwortet Ihnen das Team von AI United alle möglichen Fragen per Email oder in dem Q&A Bereich.

Quellen: https://towardsdatascience.com/want-to-use-bigquery-read-this-fab36822830

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.