Zu Beginn werden wir kurz beschreiben, wie der Prozess aussah, bevor und nachdem wir unserem internen Produkt A1 beigebracht haben, Datenquellen programmgesteuert zu erfassen und auf Tableau Server zu veröffentlichen. Dann werden wir uns das Problem des BI-Befehls und die gefundene Lösung genauer ansehen und auch unter die Haube schauen (hier über das Erstellen einer .hyper-Datei, das Veröffentlichen einer Datei auf einem Tableau-Server und das Aktualisieren eines Hyper) Willkommen bei der Katze!

Wir in der DAN-Werbegruppe arbeiten viel mit Werbeüberwachungsdaten von Mediascope , einem Industriezähler auf dem Medienmarkt. Es gibt verschiedene Szenarien: Einige Mitarbeiter laden Rohdaten hoch, andere verwenden vorgefertigte vorverarbeitete Datenbanken, und jemand ordnet die Entwicklung automatisierter Dashboards an, die auf diesen Daten basieren. Lassen Sie uns das letzte Szenario genauer betrachten - unsere BI-Entwickler sammeln Dashboards in Tableau, aber bevor sie mit dem "Zeichnen" beginnen, müssen sie die Daten auch in das gewünschte Format bringen, das für die Entwicklung geeignet ist.
Der Lebensweg von Daten von Rohstoffen bis hin zu schönen automatisierten Grafiken kann grob in vier Schritte unterteilt werden:
- Rohdaten abrufen
- Datenbereinigung und -revision
- Erstellen von Datenquellen für Tableau
- Entwicklung von Visualisierungen
Es war
Bevor wir gelernt haben, wie Datenquellen für Tableau programmgesteuert generiert werden, sah der Prozess folgendermaßen aus:

1. Rohdaten abrufen
Benutzer erstellen über das interne Tool A1 tabellarische Berichte. Wir werden weiter unten ausführlicher darauf eingehen.
2. Datenbereinigung und -änderung Die Datentransformationsfunktion
ist auch im A1-Tool enthalten. Danach können die bereinigten Daten auf xslx / csv hochgeladen werden und außerhalb des Tools weiter mit ihnen arbeiten. Hierbei ist zu beachten, dass sich einige Benutzer auf den ersten Punkt beschränken und nach dem Hochladen der Berichte die Daten selbst ändern.
3. Erstellen von Datenquellen für Tableau
Zuvor hatten Dashboard-Kunden eine Reihe von Excels, die sie in den vorherigen Absätzen generiert hatten. Und BI-Entwickler haben diese Ex-Werke selbst in eine einzige Datenquelle (Tabloid Slang) gebracht. Es war nicht immer möglich, uns nur auf Tableau-Tools zu beschränken, sie schrieben oft Skripte in Python.
4. Entwicklung von Visualisierungen
Schließlich erstellt die Spitze des Eisbergs ein Dashboard und veröffentlicht es auf dem Tableau Server, wo der Kunde es sehen kann. In der Praxis dauert das Rendern oft weniger lange als das Sammeln von Daten und das Einrichten von Updates.
Der Schmerz häufte sich im dritten Schritt, als die Anzahl der kundenspezifischen Lösungen zunahm, deren Wartung und Implementierung teuer waren. Außerdem traten regelmäßig Fehler in den Daten aus dem zweiten Schritt auf - das Zwischen-Excel zwischen den beiden Systemen (A1 und Tableau) drängte den Benutzer: „Korrigieren wir etwas mit Stiften, niemand wird es bemerken“.
Wurde
Die Hauptaufgabe bestand darin, Ex-Pelz zwischen 2 und 3 Schritten zu entfernen. Aus diesem Grund haben wir A1 beigebracht, Datenquellen zu sammeln und auf Tableau Server zu veröffentlichen. Folgendes ist passiert:

Jetzt finden die Schritte 1 bis 3 in A1 statt. Am Ausgang erhält das BI-Team eine auf dem Tableau Server veröffentlichte Datenquelle zur Entwicklung von Visualisierungen. Die Hyper-API wurde zum Verbindungsglied, auf das weiter eingegangen wird.
Ergebnisse
Die Anzahl der Knoten bei der Arbeit mit verschiedenen Tools wurde reduziert . Jetzt ist es schwieriger, irgendwo im Prozess einen Fehler zu machen, und es ist einfacher zu erkennen, wo der Fehler aufgetreten ist. Die Untersuchung von Fehlern nimmt weniger Zeit in Anspruch. Das System warnt Benutzer vor häufigen Fehlern.
Machen Sie dem BI-Team Zeit . Bisher gab es nur wenige Vorlagenlösungen und viele Anpassungen. Am häufigsten wurde die Verarbeitung in Python für jedes Projekt hinzugefügt. In seltenen Fällen, in denen keine Verarbeitung erforderlich war, haben wir direkt in Tableau Desktop (dem Hauptentwicklungstool) gearbeitet.
Die Vorbereitung der Datenquelle lautet nun: Klicken Sie auf die erforderlichen Felder in der A1-Oberfläche, markieren Sie, welche davon wir in Zeilen erweitern (falls erforderlich) und definieren Sie optional den Feldtyp im Voraus.
Wir laden Tableau Server nichtAktualisieren umfangreicher Datenquellen - Die Aktualisierung erfolgt durch A1, und ein vorgefertigter Hyper wird auf den Server heruntergeladen.
* Bonus - Wir empfehlen Benutzern, in A1 zu arbeiten. Wenn einige Benutzer früher nach dem Entladen von Rohberichten diese manuell außerhalb des Tools geändert haben, ist es für Benutzer jetzt einfacher, den Reinigungsprozess dort einzurichten, da der gesamte Prozess von Schritt 1 bis 3 in A1 stattfindet.
Problem und Lösung
Ein bisschen über A1
Bevor wir über unsere Lösung sprechen, müssen wir über unser internes Produkt A1 sprechen, an das wir die Generierung von Datenquellen angehängt haben.
A1 ist ein unternehmensinternes Produkt, das den Workflow für Mitarbeiter vereinfachen soll, deren Hauptaufgabe folgende ist:
- Abrufen von Daten aus MediaScope-Softwareprodukten
- Bringen Sie diese Daten in eine für Fachanalysten geeignete Form
- Bereiten Sie bei Bedarf Daten für die Erstellung von Dashboards vor (wir werden heute darüber sprechen).
Nachdem der Benutzer die Daten bereinigt hat, werden sie im A1-System gespeichert. In unserer Terminologie wird dies "Container" genannt. Ein Container ist ein reguläres Dokument in MongoDB, das wir auf den Tableau-Server übertragen müssen.
BI-Team-Problem
Unser BI-Entwicklungsteam musste irgendwie Daten von A1 abrufen, das in MongoDB gespeichert war, und Dashboards basierend auf den empfangenen Daten erstellen. Zunächst haben wir versucht, Daten aus MongoDB mit normalen Anzeigetafel-Tools abzurufen, aber dies hat das Problem nicht gelöst:
- Da die Daten in MongoDB gespeichert sind, werden am Eingang der Anzeigetafel Daten mit einer beliebigen Struktur empfangen, was bedeutet, dass Sie diese Logik ständig beibehalten müssten.
- Um Daten aus MongoDB zu aggregieren, mussten bestimmte Datensätze aus der Sammlung und nicht aus der gesamten Sammlung gezogen werden. Der Tableau-Treiber kann dies nicht.
- Unter anderem reichte es nicht aus, um die Daten abzurufen: Manchmal mussten sie "erweitert" werden, um einige Spalten in Zeilen zu "schwenken". Was auch vom Wort her gar nicht so einfach war.
Was haben wir uns ausgedacht?
Es wurde beschlossen, dieses Problem mit meinem Fahrrad mithilfe der Tableau Hyper API- Bibliothek zu lösen . Mit dieser Bibliothek können Sie eine Datei im Hyper-Format erstellen, in die Sie problemlos Daten hinzufügen können, und diese dann als Datenquelle verwenden, um ein Dashboard auf der Serverplatine zu erstellen.
Wie die Entwickler der Anzeigetafel den Hyper selbst beschreiben:
Hyper ist eine leistungsstarke In-Memory-Daten-Engine, mit der Kunden große oder komplexe Datenmengen schnell analysieren können, indem sie Datenbankabfragen effizient auswerten. Basierend auf der Tableau-Plattform verwendet Hyper proprietäre dynamische Codegenerierungstechniken und fortschrittliche Parallelitätstechnologien, um eine hohe Leistung bei Extrakten und Abfragen zu erzielen.Der ungefähre Arbeitsprozess in unserem Programm ist wie folgt:
- Der Benutzer wählt Container und gewünschte Spalten aus
- Das System zieht Daten aus Containern
- Basierend auf den empfangenen Daten bestimmt das System die Spaltentypen
- Die Erstellung des Hyper und das Einfügen von Daten wird initialisiert
- Der Hyper wird auf den Scoreboard-Server geladen
- BI-Entwickler sehen den Hyper auf dem Server und erstellen darauf basierend ein Dashboard
Wenn neue Daten in die Container gegossen werden, erhält das System ein Signal, dass der Hyper aktualisiert werden muss:
- Das System lädt den Hyper vom Scoreboard-Server herunter
- Nimmt frische Daten aus MongoDB und aktualisiert den Hyper
- Danach lädt das System einen neuen Hyper auf den Server hoch und überschreibt den vorhandenen.
- Der Benutzer muss nur auf die Schaltfläche "Aktualisieren" klicken, um aktuelle Informationen im Dashboard anzuzeigen
Was der Benutzer sieht
Wie bereits erwähnt, ist A1 eine Webanwendung. Wir haben Vue.js und Vuetify verwendet, um einen Front-End-Hypergenerierungsdienst zu erstellen.
Die Anwendungsoberfläche ist in drei Bildschirme unterteilt.
Auf dem ersten Bildschirm wählt der Benutzer die gewünschten Container und Spalten aus.
Wenn die Option "Unpivot" aktiviert ist, werden in der Hyper-Variable zwei zusätzliche Spalten erstellt: Variable - die Namen der Spalten, die in der Spalte "Metriken" ausgewählt sind, und Werte - die Werte aus diesen Spalten.
Die Spalte Dimension fügt dem Hyper eine Spalte mit der ausgewählten gleichnamigen Spalte hinzu. Die Anzahl der ausgewählten Spalten Dimensionen und ihre Namen müssen in allen Containern gleich sein, damit die Integrität der Tabelle im Hyper nicht verletzt wird. Daher gibt es eine Spalte "Hypername", in der Sie den Namen der ausgewählten Spalte angeben können, wenn sie in Containern unterschiedlich benannt sind.
Damit ist der Prozess des Einrichtens des Hyper abgeschlossen. Der Benutzer muss nur zum zweiten Bildschirm gehen, auf "Hyper erstellen" klicken und den Fortschritt der Ereignisse in den Protokollen verfolgen.
Der dritte Bildschirm enthält zusätzliche Einstellungen:
- Sie können das Ignorieren von Updates aktivieren, wenn das System das Hyper nicht automatisch aktualisieren muss
- Sie können eine E-Mail angeben, um Aktualisierungsberichte zu senden
- Sie können den Datentyp für die Wertespalte manuell angeben (wird nur im Unpivot-Modus verwendet): float, string oder automatisch vom System festgelegt (wir werden weiter auf Typen eingehen).
- Sie können auch Datentypen für ausgewählte Spalten in Containern angeben.
Was ist unter der Haube
A1 ist in Python geschrieben. Um mit Daten zu arbeiten, verwenden wir Pandas und serialisieren die Daten von Pandas, um sie in MongoDB GridFS aufzunehmen und zu speichern.
Wenn ein Befehl zum Erstellen eines Hyper empfangen wird, führt das System die folgenden Vorgänge aus:
- Entlädt alle erforderlichen Container aus MongoDB und deserialisiert Daten in Pandas-Datenfremes
- Bereitet Daten vor: Belässt nur die erforderlichen Spalten in Datenrahmen, gibt ihnen neue Namen und erweitert Tabellen bei Bedarf über pandas.melt
- Wenn der Benutzer den Datentyp für die Spalten festgelegt hat, konvertieren Sie die Daten entweder in float32 oder in string
- Nach all den vorbereitenden Arbeiten mit den Daten erstellt das System eine Datei über Hyper-API und sendet die Datei über tabcmd an den Scoreboard-Server.
Es lohnt sich, ein wenig über die Datentypen von Spalten zu sprechen. Eine der Funktionen beim Speichern von Daten in A1-Containern besteht darin, dass Benutzer sich nicht darum kümmern, welche Typen Spalten zugewiesen werden sollen. Pandas erledigt dies perfekt für sie: Das System bewältigt ruhig Situationen, in denen Zahlen und Zeichenfolgenwerte in einer Spalte vorhanden sind. Dem Hyper gefällt das jedoch nicht: Wenn Sie ihm sagen, dass die Spalte vom Typ int sein muss, schwört das System, wenn es versucht, etwas anderes als eine Ganzzahl einzufügen. Daher wurde beschlossen, in Hypern nur zwei Datentypen zu verwenden: string und float.
Also haben wir das allgemeine Prinzip der Arbeit herausgefunden. Lassen Sie uns über die Arbeit mit Hyper selbst sprechen.
Erstellen einer .hyper-Datei
Um die Arbeit mit dem Hyper - API, müssen Sie die Bibliothek installieren, können Sie es von der offiziellen Website herunterladen können hier . Es gibt auch einige gute Beispiele für die Arbeit mit diesem Tool. Wir werden kurz auf die wichtigsten Punkte eingehen.
Die Hyiper-Datei selbst ist eine Art Datenbank, die etwas an SQLite erinnert. Über die API können Sie mit der folgenden SQL-Syntax auf Daten zugreifen:
f"SELECT {escape_name('Customer ID')} FROM {escape_name('Customer')}"
Da unser System in Python geschrieben ist, verwenden wir die Bibliothek auch für die entsprechende Sprache. Beim Erstellen der Datei müssen wir den Schemanamen, den Tabellennamen und die Spalten mit Typen angeben. Der Name des Schemas und der Tabelle sollte "Extrahieren" heißen, da Tableau Server in diesem Schema mit der Tabelle klettert, um Daten für Bücher zu extrahieren.
with HyperProcess(Telemetry.SEND_USAGE_DATA_TO_TABLEAU) as hyper:
with Connection(
hyper.endpoint, self.fullpath_hyper, CreateMode.CREATE_AND_REPLACE
) as connection:
connection.catalog.create_schema("Extract")
main_table = TableName("Extract", "Extract")
example_table = TableDefinition(main_table)
Nach dem Erstellen der Tabelle müssen wir Spalten erstellen und Typen festlegen. Wie bereits erwähnt, haben unsere Daten nur zwei Typen (float oder string). Basierend auf dem Spaltentyp im Datenrahmen legen wir dies für die Spalten fest:
for column in dataframe.columns:
if dataframe[column].dtype.name in ("category", "object"):
example_table.add_column(TableDefinition.Column(column, SqlType.text()))
elif dataframe[column].dtype.name in ("float32"):
example_table.add_column(
TableDefinition.Column(column, SqlType.double())
)
connection.catalog.create_table(example_table)
Nach dem Erstellen der Tabelle können Sie Daten einfügen:
with Inserter(connection, example_table) as inserter:
for val in dataframe.values:
inserter.add_row(val.tolist())
inserter.execute()
Hier durchlaufen wir den Datenrahmen Zeile für Zeile und akkumulieren die Liste mit Werten über inserter.add_row () . Tatsächlich gibt es im API-Hyper eine Funktion add_rows () , die eine Liste von Listen erstellt und die Werte bereits einfügt. Warum wurde das nicht gemacht? So sparen Sie RAM: Um eine Liste mit Wertelisten aus dem Datenrahmen bereitzustellen, müssen Sie Pandas auffordern, values.tolist () auszuführen . Und wenn Sie über 150 Millionen Datenzeilen verfügen, stellt sich heraus, dass dies eine sehr teure Operation für den RAM ist, obwohl dies die Leistung in keiner Weise beeinträchtigt (auf jeden Fall wurde nicht bemerkt, dass aufgrund der iterativen Iteration über die Zeilen die Geschwindigkeit der Erstellung eines Hyper irgendwie gesunken ist). Plus, add_rows ()funktioniert wie syntaktischer Zucker: Es nimmt tatsächlich eine Liste von Listen und fügt Daten iterativ hinzu.
Damit ist die Schaffung unseres Hyper abgeschlossen. Als nächstes müssen wir es auf dem Server veröffentlichen.
Veröffentlichen einer Datei auf einem Tableau-Server
Für den Zugriff auf den Tableau-Server verwenden wir das Dienstprogramm tabcmd. Hierbei handelt es sich um ein Konsolendienstprogramm, mit dem Sie eine Verbindung zum Server herstellen und Verwaltungsfunktionen ausführen können. Erstellen Sie Benutzer, Gruppen, Bücher usw.
Wir werden den Befehl tabcmd über den Python-Unterprozess ausführen. Öffnen:
popen = subprocess.Popen(
f'/opt/tableau/tabcmd/bin/tabcmd publish "{fullpath_hyper}" -n "{filename}" -o -r "A1_test" '
'-s http://tableau.domain.com -u "username" -p "password" --no-certcheck',
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
)
return_code = popen.wait()
if return_code:
error = str(popen.communicate()[1])
return f" . {error}"
Wir übergeben den folgenden Befehl und die folgenden Schlüssel an tabcmd:
- Veröffentlichen : Laden Sie eine Datei auf den Server hoch
- -n (--name) : Welcher Dateiname befindet sich auf dem Server ?
- -o (--overwrite) : Wenn eine Datei mit diesem Namen vorhanden ist, überschreiben Sie diese
- -r “A1_test” (--project): ( )
- -s (--server): tableau-
- -u -p:
- --no-certcheck: SSL-
Wir haben herausgefunden, wie ein neuer Hyper erstellt wird. Was ist jedoch zu tun, wenn der Hyper aus zehn Containern besteht und einer von ihnen neue Daten erhalten hat? Wir werden den Hyper aktualisieren.
Wenn neue Daten im Container eintreffen, prüft das System, ob Hypers vorhanden sind, die diesen Container verwenden. Wenn ja, besteht die Aufgabe darin, den Hyper zu aktualisieren.
Um zu verstehen, welche Daten von welchem Container im Hyper enthalten sind, erstellt das System beim Erstellen des Hyper eine zusätzliche Spalte container_id. Mit diesem Ansatz wird die Aktualisierung sehr einfach:
- Wir nehmen die Datei vom Server
- Wir löschen alle Zeilen im Hyper, wobei container_id dem aktualisierten Container entspricht
- Neue Zeilen einfügen
- Laden Sie die überschriebene Datei wieder auf den Server hoch.
Das Abrufen einer Datei unterscheidet sich geringfügig vom Herunterladen. Zunächst nehmen wir nicht die .hyper-Datei vom Server, sondern das .tdsx-Archiv, das wir dann entpacken und die .hyper selbst öffnen.
Um die Datei aufzunehmen, verwenden wir tabcmd:
popen = subprocess.Popen(
f'/opt/tableau/tabcmd/bin/tabcmd get "datasources/{filename_tdsx}" '
f'-s http://tableau.domain.com -u "username" -p "password" '
f'--no-certcheck -f "{fullpath_tdsx}"',
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
)
return_code = popen.wait()
if return_code:
error = str(popen.communicate()[1])
return f". {error}"
Hier verwenden wir den folgenden Befehl und die folgenden Tasten:
- get : Holen Sie sich eine Datei vom Server. Wenn sich die Datei test.hyper auf dem Server befindet, müssen Sie auf die Datei test.tdsx verweisen, und sie befinden sich alle im Datenquellenverzeichnis (ich konnte nicht googeln, warum eine solche Funktion in der Anzeigetafel, wenn Sie wissen, in den Kommentaren geteilt wird).
- -f (--Dateiname) : vollständiger Pfad, einschließlich Dateiname und Erweiterung, in dem die Datei gespeichert werden soll
Nachdem die Datei heruntergeladen wurde, muss sie über eine Zip-Datei entpackt werden:
with zipfile.ZipFile(fullpath_tdsx, "r") as zip_ref:
zip_ref.extractall(path)
Nach dem Entpacken befindet sich der Hyper im Verzeichnis ./Data/Extracts .
Nachdem wir die aktuelle Version der Datei haben, können wir unnötige Zeilen daraus entfernen:
table_name = TableName("Extract", "Extract")
with HyperProcess(Telemetry.SEND_USAGE_DATA_TO_TABLEAU) as hyper:
with Connection(hyper.endpoint, self.fullpath_hyper) as connection:
connection.execute_query(
f"DELETE FROM {table_name} WHERE "
f'{escape_name("container_id")}={container_id}'
).close()
Das Einfügen und Veröffentlichen einer Datei wurde bereits oben beschrieben.
Fazit
Was ist das Endergebnis? Nachdem wir die Arbeit an der Implementierung der Generierung von Hyper-Dateien und deren automatischer Übermittlung an den Tableau-Server erledigt hatten, haben wir die Belastung des BI-Teams erheblich reduziert, es wurde einfacher, die Daten im Dashboard zu aktualisieren und vor allem schneller. Die Bekanntschaft mit Hyper-API war nicht schmerzhaft, die Dokumentation ist gut geschrieben und die Integration der Technologie in unser System war einfach.
Wir bedanken uns für Ihre Aufmerksamkeit! Wenn Sie Fragen oder Kommentare haben, hinterlassen Sie diese bitte in den Kommentaren.
Der Artikel wurde gemeinsam mit Wassili Lawrow geschrieben (VasilyFromOpenSpace) — -