Wie Google Ihre Big Query-Tabellen speichert und wie sich das auf Sie auswirkt
Veröffentlicht: 2016-02-24Dies ist eine Tech-Talk-Installation unseres Blogs, präsentiert vom außergewöhnlichen Entwickler Adam Knox.
Obwohl Big Query eine der SQL sehr ähnliche Syntax verwendet, erfordert es tatsächlich einen deutlich anderen Takt als eine Lösung zur Verarbeitung großer Datenmengen. Big Query neigt zu Brute-Force-Dingen und verwendet eigentlich keine Indizes, sodass viele Daten viele Prozessoren und Verarbeitungszeit bedeuten. Um dies zu erreichen, hat Google eine andere Methode zum Speichern von Daten gewählt, die sich auf die Gestaltung Ihrer Abfragen auswirken kann.
Datei Format
Wenn eine Tabelle erstellt wird, verwendet Google ihr ColumnIO-Format, um Ihre Daten zu speichern. Jede Spalte wird als separate Datei gespeichert, mit Ausnahme von Wiederholungsfeldern. Wenn Sie eine Tabelle mit den Spalten haben: Name (Zeichenfolge), Telefonnummern (wiederholte Ganzzahl); Der Name wird zusammen mit den anderen Namen in einer einzigen Zeile gespeichert, und alle diesem Namen zugeordneten Telefonnummern werden zusammen mit den Telefonnummern in einer einzigen Zeile gespeichert. Spalten können auch aufgeteilt werden, wenn sie zu groß werden, aber das hat keine Auswirkungen auf den Arbeitsablauf.
Wenn Sie dies wissen, können Sie Abfragen schneller ausführen, indem Sie keine Spalten verarbeiten, die Sie eigentlich nicht interessieren, und in einigen Fällen sogar früher unmögliche Abfragen ausführen können. Abfragen können auch billiger werden, da das System nach der Menge der verarbeiteten Daten berechnet, und wenn eine Spalte nicht in der Abfrage enthalten ist, werden diese Daten nicht verarbeitet.
Dateispeicher
Wenn Sie eine Tabelle erstellt haben, können Sie sich einigermaßen sicher fühlen, dass sie nirgendwo hingeht, denn sobald Ihre Dateien erstellt sind, werden sie in drei verschiedenen Rechenzentren und sogar an drei verschiedenen Orten innerhalb jedes Rechenzentrums gespeichert. Da Big Query Prozessoren vor Probleme stellt, müssen Daten leicht zugänglich sein. Der Vorbehalt dabei sind temporäre Datensätze. Es besteht die Möglichkeit, eine Ablaufzeit für Tabellen innerhalb eines Datensatzes anzugeben, und Tabellen werden gelöscht, sobald sie älter als dieses Ablaufdatum sind.
Tabellenhierarchie
Ein Projekt kann Datensätze speichern, die jeweils Tabellen enthalten können. Der vollständige Befehl für den Zugriff auf eine Tabelle in Big Query-Syntax lautet [projectname:datasetname.tablename]
, kann jedoch zu dataset.tablename
abgekürzt werden, wenn Sie von dem Projekt aus auf die Tabelle zugreifen, in dem Sie gerade arbeiten.
Das Aufteilen verwandter Daten in separate Tabellen (z. B. nach Datum oder nach Eintreten eines bestimmten Ereignisses) kann vorteilhaft sein, um Abfragen besser wartbar zu machen, da Abfragen im Allgemeinen alle Zeilen in einer Tabelle durchlaufen. Das bedeutet, dass Sie sich möglicherweise mehrere Tabellen ansehen möchten, sodass in jedem Datensatz eine sogenannte Metatabelle versteckt ist, auf die unter [projectname:datasetname.__TABLES__]
und die Informationen zu jeder Tabelle im Datensatz enthält und zum Aggregieren von Tabellen verwendet werden kann für abfragen.
Der Befehl TABLE_QUERY
ist ein Befehl, mit dem mehrere ähnliche Tabellen aggregiert werden können, bevor eine Abfrage auf dem Aggregat ausgeführt wird, und jede Spalte in __TABLES__
kann verwendet werden, um dieses Aggregat zu bilden. Wenn ich beispielsweise eine Vorstellung von den Antwortzeiten seit dem 1. Januar 2016 für ein Projekt haben möchte, könnte ich die folgende Abfrage ausführen, die die minimalen, mittleren und maximalen Antwortzeiten anzeigt:
SELECT QUANTILES((protoPayload.endTime - protoPayload.startTime), 3) AS responseTimeBucketsInMilliseconds FROM (TABLE_QUERY(appengine_logs, "table_id CONTAINS 'appengine_googleapis_com_request_log' AND creation_time > 1451606400000"))
Da nur zwei Spalten verwendet werden, die jeweils Ganzzahlen enthalten, ist dies immer noch eine recht günstige Abfrage (0,0003 $), obwohl sie auf 28+ zugreift, von denen mir durch die folgende Abfrage mitgeteilt wird, dass sie 1,857 TB groß ist und etwa 9 $ kosten würde, um auf jedes Feld zuzugreifen .

SELECT SUM(size_bytes)/1000000000 FROM [repcore-prod:appengine_logs.__TABLES__] WHERE table_id CONTAINS 'appengine_googleapis_com_request_log' AND creation_time > 1451606400000
Aktualisieren von Dateien
Big Query ist großartig, wenn es darum geht, Änderungen zu protokollieren und diese Änderungen zu analysieren, da Sie neue Zeilen in eine Tabelle streamen können. Aufgrund des Mangels an Indizes ist es jedoch ein schreckliches Datenspeichergerät für schnelles und häufiges Nachschlagen bestimmter Zeilen und auch nicht gut zum Speichern einzelner Darstellungen von Objekten, von denen Sie erwarten, dass sie geändert werden, da Zeilen in einer Tabelle nicht geändert oder entfernt werden können .
Trenntische
In manchen Situationen ist sogar der Zugriff auf eine einzelne Spalte zu viel für Big Query. Ich präsentiere Ihnen die folgende unbrauchbare Abfrage, die Auflistungs-IDs in der Reihenfolge des Erstellungsdatums der Auflistung zurückgibt:
SELECT lid FROM [repcore-prod:datastore.LIS] ORDER BY ct
Technisch gesehen ist dies seit kurzem möglich, aber nicht für die Leute bei Vendasta, da es die Aktivierung einer höheren Abrechnungsstufe erfordert. Da es keine vorbestellten Indizes gibt, verarbeitet es eine kleine Datenmenge sehr intensiv, sodass in diesem Fall die Verarbeitung in Rechnung gestellt wird. Das Ändern des Abrechnungstarifs kann in interaktiven Abfragen in der Big Query-Benutzeroberfläche vorgenommen werden, indem unter der Schaltfläche „Optionen“ die Option „Unbegrenzt zulassen“ (falls aktiviert) aktiviert wird.
Angenommen, Ihre Abfrage ist so effizient wie möglich, gibt es noch ein paar Ansätze, um die Tabellengröße zu reduzieren, um diese Art von harten Grenzen zu umgehen. Der erste ist Tischdekoration und der zweite ist mit einem Hash.
Hier erfahren Sie mehr über Tischdekorateure. Im Gegensatz zum Herunterfiltern von Ergebnissen mit Befehlen wie LIMIT/WHERE/HAVING/OMIT
verringern Tabellen-Decorators tatsächlich die Kosten für die Abfrage einer Tabelle, da nicht einmal auf die Daten außerhalb des angegebenen Bereichs zugegriffen wird. Leider ist diese Methode bei Vendasta so gut wie nutzlos, denn selbst für Tabellen wie das ListingHistoryModel, zu denen wir tatsächlich streamen, löschen wir immer noch die gesamte Tabelle und ersetzen sie jeden Tag durch eine Replik, wenn sie von NDB stammt, was bedeutet, dass Tischzeitdekorateure nur an der arbeiten ListingHistoryModel, wenn Sie sich nur für die Einträge des aktuellen Tages interessieren.
Ein Blick auf die Protokollierung ist der einzige Ort, an dem sie bei Vendasta sehr hilfreich sein können. Aufgrund der Größe des tatsächlichen Protokollinhalts werden Berechnungs- und Speichergrenzen leicht erreicht, und das Abfragen auch nur der Protokollinhaltsspalte ist teuer. Bei Protokollen kümmert man sich meist auch nur um bestimmte Zeitpunkte und genau da hilft der Zeitdekorateur.
Abfrageergebnisse
Jedes Mal, wenn Sie eine Abfrage ausführen, erstellt sie eine neue Tabelle und erstellt manchmal unbekannte versteckte Tabellen hinter den Kulissen. Wenn Sie möchten, können Sie der Ergebnistabelle einen Namen geben, um sie beizubehalten, oder sie bei dem Namen belassen, den Google ihr gegeben hat, und sie nach einem Tag verschwinden lassen. Wenn Sie jemals auf eine „Antwort zu groß für eine Rücksendung“ stoßen, liegt das daran, dass sie Sie vor sich selbst schützen. Es ist einfach, riesige Tabellen zu erstellen (insbesondere mit Kreuzverknüpfungen). Wenn dies passiert und Sie es erwartet haben, müssen Sie die Tabelle benennen und die Option „Große Ergebnisse zulassen“ aktivieren. Wenn Sie eine Abfrage wiederholen, an die keine neuen Zeilen gestreamt werden, erhalten Sie nur die zwischengespeicherten Ergebnisse, wenn sie noch vorhanden sind.
