Was passiert, wenn ein Delfin und ein Elefant aufeinander treffen? Was hat das alles mit den aktuellen Schlagwörtern Big Data, MapReduce und Hadoop zu tun? Das erfährst Du in diesem Artikel.
Der (derzeit überbeanspruchte) Begriff Big Data bezieht sich auf sehr große Datenmengen, die etwa in sozialen Netzwerken wie Facebook oder Twitter produziert werden. So entstehen bei Facebook beispielsweise tagtäglich 500 Terabyte neuer Daten, gesamt müssen mehr als 100 Petabyte an Daten analysiert werden (1 Petabyte = 1.000.000 Gigabyte). Die Analyse dieser Datenmengen, die bis zu mehreren Petabytes groß werden können, ist mittels „normaler“ Hardware nicht mehr zu bewältigen. Um beim Beispiel von Facebook zu bleiben: derartige Analysen berechnen Details zum Userverhalten oder der Vernetzung zwischen Usern, damit beispielsweise zielgerichtet neue Freunde vorgeschlagen werden können. Bereits 2004 haben Jeffrey Dean und Sanjay Ghemawat (beide arbeiten bei Google) MapReduce vorgestellt, das ein neues Paradigma für die hochverteilte Berechnung und Analyse großer Datenmengen zur Verfügung stellt. Dabei werden die Daten auf viele Rechner verteilt und die Berechnung wird gleichfalls in kleine Einzelberechnungen aufgesplittet, die dann sehr einfach parallel berechnet werden können. Durch diese Verteilung auf viele verschiedene Rechner kann der Analyseprozess skaliert werden, indem die die Anzahl an (günstigen) Rechnern und damit die Gesamt-Rechenpower erhöht wird. Das derzeit populärste System, das MapReduce umsetzt, ist Apache Hadoop. Hadoop stellt einerseits ein verteiltes Dateisystem und darauf aufbauend MapReduce-Funktionalitäten zur Verfügung. Der hohe Verteilungsgrad gepaart mit der sehr einfachen Handhabung sind das Erfolgsrezept von Apache Hadoop. Auf eine nähere Beschreibung von MapReduce und Hadoop möchten wir hier verzichten, da es dazu mehr als ausreichend Literatur bereits gibt.
Du fragst Dich jetzt bestimmt, was das alles überhaupt mit MySQL zu tun haben soll, oder? Diese Frage ist sehr einfach beantwortet: in der Datenverarbeitungs-Pipeline steht meist auch MySQL, in dem die Produktivdaten primär gespeichert werden. Hadoop ist keine Datenbank und kann deren Aufgaben nicht übernehmen, daher werden die Daten meist zunächst in MySQL gespeichert und in einem weiteren Schritt in das Hadoop-eigene Dateisystem HDFS (Hadoop Distributed File System) exportiert und dort in weiterer Folge parallelisiert analysiert. MySQL schreibt im Whitepaper „MySQL and Hadoop-Big Data Integration“, dass bis zu 80% aller Hadoop-Installationen in Kombination mit MySQL verwendet werden. Zu diesem Import von Daten aus MySQL in Hadoop stellen Apache und MySQL zwei Tools zur Verfügung: Apache Sqoop und Apache Applier, die wir im Folgenden vorstellen möchten.
Apache Sqoop
Apache Sqoop wurde von Cloudera, einer auf Hadoop-Produkte spezialisierten IT-Firma entwickelt und dient dazu, große Datenmengen von relationalen Datenbanksystem nach HDFS zu importieren (bulk loading) und die Analyseergebnisse von Hadoop auch wieder zurück in die MySQL-Datenbank zu schreiben. Sind die Daten erst mal in HDFS gespeichert, ist es natürlich möglich, diese Daten für MapReduce-Jobs, mit Hive oder auch HBase zu nutzen. Sqoop unterstützt dabei MySQL, aber beispielsweise auch Oracle, Postgres, Netezza oder Teradata. Um Dir kurz zu zeigen, wie einfach dieser Export von MySQL nach HDFS funktioniert, hier ein kurzes Beispiel für den Import einer Tabelle von MySQL in Hadoop:
sqoop import –connect jdbc:mysql://mysql_host/db_name –table tablename –hive-import
Analog können auch ganze Datenbanken von MySQL in HDFS importiert werden. Für den Export der Daten aus HDFS (nach beispielsweise MySQL) stellt Sqoop ebenfalls Funktionen zur Verfügung, mit denen etwa Ordner aus HDFS in Tabellen exportiert werden können.
Applier
Falls es für Dich nicht ausreicht, große Datenmengen beispielsweise einmal am Tag in die Hadoop-Infrastruktur zu importieren, sondern die Daten in HDFS stets aktuell sein sollen, stellt MySQL mit dem Applier das richtige Tool zur Verfügung. Applier verwendet für den Austausch das MySQL-Binlog, das wir im Buch bereits ausreichend beschrieben haben. Das Laden von Daten in HDFS funktioniert ähnlich wie Replikation in MySQL – Hadoop liest die geänderten Daten aus dem Binlog des entsprechenden MySQL-Servers aus und schreibt diese in Hadoop, wie man auch in der folgenden Abbildung erkennen kann:
Applier-Architektur (Quelle: https://innovating-technology.blogspot.co.at/2013/04/mysql-hadoop-applier-part-1.html)
Mit dieser Replikation in das HDFS-Dateisystem kann sichergestellt werden, dass die Daten in HDFS real-time upgedated werden und so alle Hadoop-Analysen stets auf den aktuellsten Daten ausgeführt werden.
Weiterführende Links
Was nach dem Starten der neuen Version direkt auffällt, ist das neue Design. Übersichtlich werden die gespeicherten verfügbaren gespeicherten Connections aufgelistet.
Im Folgenden werden wir nun die wichtigsten und hilfreichsten Neuerungen Schritt für Schritt präsentieren.
Queries formulieren
Im Abfrage-Screen wird beim Verfassen einer Abfrage in der neuen Version auf der rechten Seite Syntax-Hilfestellung gegeben. So wird passend zur aktuellen Abfrage die Syntax des entsprechenden Befehls angezeigt. Besonders hilfreich ist dies beim Verfassen von Gespeicherten Funktionen oder Prozeduren, in denen oft Statements verwendet werden, die man eventuell nicht so oft verwendet und deren Syntax man nachschlagen müsste – dies wird jetzt von der Workbench übernommen (siehe Abbildung 2).
Administration
Bisher waren die Administration und die normalen Abfrage-Funktionalitäten komplett getrennt, man musste sich über zwei verschiedene Interfaces zum Server connecten, um entweder Abfragen auszuführen oder den MySQL-Server administrieren zu können. Dies wurde in der neuen Version geändert, was man auch direkt beim Connecten zu einem Server sehen kann, da auf der linken Seite des Screens einerseits (wie bisher) die verschiedenen Schemata, andererseits aber auch Management-Funktionalitäten angeboten werden. Diese beinhalten das Abrufen und Anzeigen der Server-Auslastung, der Anzahl der offenen Connections, System-Variablen und -Einstellungen, aber auch das gesamte User- und Rechtemanagement und Import- und Export-Funktionalitäten (siehe auch Abbildungen 3 und 4).
Schema Inspector
Ein neues Feature ist der sogenannte „Schema Inspector“, der es ermöglicht, sehr einfach einen Überblick über die Tabellen, Indexe, Triggers, etc. einer Datenbank zu bekommen. Dabei werden beispielsweise die Anzahl der Zeilen, der aktuelle Auto Increment-Stand oder auch die Größe der Tabelle angezeigt. Sehr bequem ist dabei die sogenannte „Maintenance“-Funktion, mit Hilfe derer Sie mit einem Click für jede Tabelle ANALYZE, OPTIMIZE, ChECK oder CHECKSUM aufrufen können, wie Abbildung 5 zeigt.
Visual Explain
Eine sinnvolle – und optisch sehr ansprechende – Neuerung sind sogenannte Visual Explains. Dabei werden Ausführungspläne, die man bisher mithilfe des EXPLAIN-Statements analysiert hat, graphisch aufbereitet und übersichtlich dargestellt. So können Sie etwaige Optimierungen mit einem Blick erkennen!
Textsuche über alle Tabellen
Ein sehr praktisches neues Feature ist die Möglichkeit, über ganze Datenbanken hinweg nach Strings und auch Patterns zu suchen. Damit können Sie sehr einfach nach Datensätzen suchen, bei denen Sie sich nicht mehr sicher sind, wie diese im Detail aufgebaut waren, welche Daten sie beinhaltet haben oder in welcher Tabelle diese gespeichert wurden. Auch sehr nützlich ist diese Funktion, wenn Sie nähere Einblicke in eine neue oder importierte Datenbank bekommen möchten.
Migration
Die neue Workbench-Version bietet einen Migration Wizard an, der umfangreiche Hilfestellung bei der Migration von Datenbanken aus anderen DB-Systemen bietet.
Folgende Datenbanken werden dabei unterstützt:
Weitere Neuerungen
Fazit
Die neue Version der MySQL-Workbench ist ein vollwertiges Tool für alle Bedürfnisse eines MySQL-Benutzers und auch Administrators. Die Neuerungen der Version 6.0 sind durchdacht und erleichtern das Leben eines MySQL-Benutzers. Die neu gestaltete Oberfläche ist intuitiver, reagiert schneller und optisch ansprechend.
Weitere Informationen:
]]>Umkreissuche befasst sich – wie der Name bereits verrät – mit der Suche von Punkten innerhalb eines gewissen Umkreises. So können beispielsweise alle Orte berechnet werden, die sich in einem Umkreis von 200 km um Innsbruck befinden. Eine solche Suche lässt sich mit MySQL mit einfachen Mitteln realisieren. Grundlage dafür ist eine Tabelle, die die Koordinaten all jener Punkte enthält, die durchsucht werden sollen. MySQL stellt dazu im Rahmen der GIS-Erweiterung den Datentyp POINT zur Verfügung, der es erlaubt, Punkte die durch X- und Y-Koordinaten lokalisiert sind, zu speichern. Im folgenden Beispiel werden die Koordinaten stets durch Grad Länge und Breite definiert (WGS-Referenzsystem). In einem konkreten Beispiel erfolgt die Erzeugung einer solchen Tabelle bzw. Spalte wie folgt:
[sql]
CREATE TABLE geodaten(
stadt VARCHAR(30) NOT NULL,
geolokation POINT NOT NULL,
SPATIAL INDEX (geolokation)
) ENGINE=MyISAM;
[/sql]
Die Spalte geolokation beinhaltet dabei Werte des POINT-Datentyps. Wichtig dabei ist, dass ein räumlicher (spatial) Index für die Spalte mit den Koordinaten angelegt wird. Dieser Index wird in MySQL als sogenannter R-Baum realisiert und erlaubt performante Abfragen auf räumliche Daten. Näheres zum R-Baum findest Du im Buch. Ein solcher R-Baum ist allerdings nur in der Storage Engine MyISAM verfügbar, daher musst Du die Tabelle basierend auf dieser Storage Engine erzeugen.
Beim Einfügen von Daten in die geodaten-Tabelle werden basierend auf den X- und Y-Koordinaten (in Grad Breite bzw. Länge angegeben) der jeweiligen Punkte POINT-Objekte erzeugt und eingefügt:
[sql]
INSERT INTO geodaten(stadt, geolokation)
VALUES (‚Innsbruck‘, POINT(47.26027800, 11.343889));
[/sql]
Vorausgesetzt Du hast die Tabelle nun mit ausreichend Daten gefüllt, kannst Du – wie folgt beschrieben – eine Umkreissuche realisieren und so beispielsweise alle Orte berechnen, die in einem Umkreis von 200 km zur Stadt Innsbruck liegen. Eine sehr einfache Berechnung der Distanz zweier Orte beruht auf dem Satz von Pythagoras (a² + b² = c²). Prinzipiell lässt sich die Vorgehensweise zur Umsetzung einer Umkreissuche in folgende Schritte gliedern:
Diese Schritte werden im Folgenden durchgeführt und erklärt. Zu Beginn müssen der Ausgangspunkt der Umkreissuche und der gewünschte Umkreis (in Kilometern) festgelegt werden. Dazu werden die Variablen @ibk_laenge und @ibk_breite mit den Koordinaten von Innsbruck und die Variable @umkreis mit dem gewünschten Umkreis gefüllt. Im Anschluss werden die Eck-Koordinaten des Suchrechtecks festgelegt. Bei einem gewünschten Umkreis von 200 km soll das Rechteck dementsprechend 200 km nach Westen, Osten, Norden und Süden reichen. Das Suchrechteck wird in Grad berechnet, der Umkreis liegt in diesem Fall allerdings in Kilometern vor. Daher müssen diese Einheiten umgerechnet werden. Breitengrade lassen sich dabei ganz einfach umrechnen: 1 Grad entspricht 111 Kilometern. Die Umrechnung der Längengrad ist etwas kniffliger: diese hängt nämlich vom jeweiligen Breitengrad ab. So liegen zwei zwei Längengrade näher am Pol — in Kilometern gerechnet — weniger weiter auseinander als zwei Längengrade in der Nähe des Äquators. Dies wird berücksichtigt, indem zusätzlich durch den Cosinus des Radians der Breite (Absolutwert) dividiert wird.
Diese oben beschriebenen Schritte können in MySQL wie folgt realisiert werden:
[sql]
SET @ibk_laenge = 11.343889;
SET @ibk_breite = 47.26027800;
SET @umkreis = 200;
SET @breite_nord = @ibk_breite + (@umkreis / 111);
SET @breite_sued = @ibk_breite – (@umkreis / 111);
SET @laenge_west = @ibk_laenge –
(@umkreis / (ABS(COS(RADIANS(@ibk_breite))) * 111));
SET @laenge_ost = @ibk_laenge +
(@umkreis / (ABS(COS(RADIANS (@ibk_breite))) * 111));
[/sql]
Der nächste Schritt ist das Erzeugen des Suchrechteckes, das mittels eines Multipoint-Objects (einem Kantenzug) definiert wird, der die vier bereits definierten Ecken beinhaltet. Dieses Multipoint-Objekt bildet die Grundlage für das Suchrechteck, das mittels des ENVELOPE-Befehls als minimal umspannendes Rechteck definiert wird. Dies ist notwendig, um dann wirklich basierend auf diesem Rechteck die Suche einschränken zu können:
[sql]
SET @mp = CONCAT(‚MULTIPOINT(‚, @breite_sued , ‚ ‚,
@laenge_west, ‚, ‚,
@breite_nord, ‚ ‚,
@laenge_ost, ‚)‘);
SET @quadrat = ENVELOPE(GEOMFROMTEXT(@mp));
[/sql]
Der letzte Schritt ist dann die eigentliche Abfrage. Dabei wird das Suchrechteck verwendet und alle darin befindlichen Punkte selektiert (mithilfe des MBRCONTAINS-Befehls). Zusätzlich wird die Distanz aller im Suchrechteck liegenden Punkte berechnet. Dies geschieht – wie bereits erwähnt – über den Satz von Pythagoras. Beachte allerdings, dass bei dieser Formel die Erdkrümmung nicht in die Berechnung einfließt. Daher ergeben sich bei weiteren Strecken Abweichungen. Falls Du die Erdkrümmung auch berücksichtigen möchtest, sollten Du Dich an die Haversinsche Formel halten.
Wichtig bei der gezeigten Berechnung ist, dass wiederum die Umrechnung der Gradangaben in Kilometerangaben korrekt erfolgt. Dabei wird – wie bereits bei der Berechnung des Suchrechteckes – die Umrechnung der Längengrade von der jeweiligen Breite abhängig gemacht. Darauf basierend werden die Distanz in der Breite und die Distanz in der Länge (beides in km umgerechnet) quadriert (POW-Funktion) und aus der Summe dieser beiden Werte wird anschließend die Wurzel gezogen (SQRT-Funktion).
Durch die Verwendung eines Rechteckes (200 km lang und 200 km breit) als Grundlage für die Suche ist allerdings noch nicht sichergestellt, dass die Distanz zu jedem Punkt in diesem Rechteck kleiner als 200 km ist. So liegen die Eckpunkte beispielsweise weiter als 200 km vom Ausgangspunkt entfernt. Daher muss in einem letzten Schritt nochmals nachselektiert werden. Dazu machen wir uns die bereits berechnete Distanz zunutze und schränken diese mittels einer HAVING-Klausel nochmals ein.
Abschließend noch einmal das gesamte Beispiel:
[sql]
SET @ibk_laenge = 11.343889;
SET @ibk_breite = 47.26027800;
SET @umkreis = 200;
SET @breite_nord = @ibk_breite + (@umkreis / 111);
SET @breite_sued = @ibk_breite – (@umkreis / 111);
SET @laenge_west = @ibk_laenge –
(@umkreis / ABS(COS(RADIANS(@ibk_breite))) * 111);
SET @laenge_ost = @ibk_laenge +
(@umkreis / ABS(COS(RADIANS(@ibk_breite))) * 111);
SET @mp = CONCAT(‚MULTIPOINT(‚, @breite_sued , ‚ ‚,
@laenge_west, ‚, ‚,
@breite_nord, ‚ ‚,
@laenge_ost, ‚)‘);
SET @quadrat = ENVELOPE(GEOMFROMTEXT(@mp));
SELECT (
FLOOR(
SQRT(
POW((@ibk_breite – sub.breite) * 111, 2) +
POW((@ibk_laenge – sub.laenge) * 111 *
ABS(COS(RADIANS(@ibk_breite))),2)
)
)
) AS distanz, sub.stadt
FROM
(
SELECT stadt, Y(geolokation) AS laenge,
X(geolokation) AS breite
FROM geodaten
WHERE MBRCONTAINS(@quadrat, geolokation)
) AS sub
HAVING distanz <= @umkreis
ORDER BY distanz;
[/sql]
Vor kurzem habe ich für eine Datenbanken-Lehrveranstaltung einen möglichst realitätsnahen Test-Datensatz zusammengestellt. Dafür habe ich über eine API einfach direkt Artikel eines Produktkatalogs angefordert und in MySQL gespeichert. Diese API lieferte allerdings viele der Produkte mehrfach zurück und natürlich wollte ich keine Duplikate speichern. Was macht man in so einem Fall? Natürlich – man verwendet INSERT IGNORE. Diese spezielle Art des INSERTS gibt beim Versuch, einen bereits in der Tabelle vorhandenen Datensatz einzufügen, nur eine Warning zurück und fügt den neuen Datensatz nicht ein.
Dabei fiel mir auf, dass bei einem INSERT IGNORE der Zähler für das auto_increment auch erhöht wird, wenn die einzufügende Zeile ignoriert bzw. verworfen wird. Es wird also in Wirklichkeit kein weiterer Datensatz hinzugefügt, trotzdem wird der auto_increment Zähler weitergezählt. Dieses Verhalten führte zu einer großen, durchlöcherten ID-Spalte. Im folgenden Beispiel kann man gut erkennen, wie nach zwei „erfolglosen“ Einfüge-Operationen (der Hitchhiker ist in der Tabelle schon vorhanden), für das nächste eingefügte Element die ID 5 vergeben wird, obwohl es in Wirklichkeit erst das dritte eingefügte Element ist.
[sql]
CREATE TABLE `products` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`product_name` varchar(100) NOT NULL,
PRIMARY KEY (`product_id`),
UNIQUE KEY `idx_name_unique` (`product_name`)
) ENGINE=InnoDB;
INSERT IGNORE INTO products(product_name)
VALUES („Hitchhiker’s Guide“);
INSERT IGNORE INTO products(product_name)
VALUES („Romeo and Juliet“);
INSERT IGNORE INTO products(product_name)
VALUES („Hitchhiker’s Guide“);
INSERT IGNORE INTO products(product_name)
VALUES („Hitchhiker’s Guide“);
INSERT IGNORE INTO products(product_name)
VALUES („Faust I“);
SELECT * FROM products;
+————+——————–+
| product_id | product_name |
+————+——————–+
| 1 | Hitchhiker’s Guide |
| 2 | Romeo and Juliet |
| 5 | Faust I |
+————+——————–+
[/sql]
Doch wie kommen nun die Löcher wirklich in den Käse? Der Grund für dieses Verhalten ist, dass InnoDB bereits vor dem Einfügen des Datensatzes den auto_increment Zähler erhöht und damit zu diesem Zeitpunkt einfach noch nicht weiß, ob der Datensatz danach wirklich eingefügt wird oder nicht. InnoDB verwendet standardmäßig den „consecutive lock mode“ für auto_increment Werte. Das bedeutet, dass für jede INSERT-Operation zu Beginn der Operation eine Sperre (siehe auch Mutex) auf den Zähler gesetzt und dieser erhöht wird. Damit wird sichergestellt, dass IDs nicht mehrfach vergeben werden. Alternativ gibt es noch den „traditional lock mode“, der für die Dauer jeder Einfügeoperation eine Sperre auf die gesamte Tabelle setzt. Damit wir der auto_increment Zähler wirklich nur dann erhöht, wenn wirklich ein neuer Datensatz eingefügt wurde (siehe auch MySQL Reference Manual).
Grundsätzlich solltet Ihr euch also nie auf dichte IDs verlassen, wenn Ihr die Daten mit InnoDB, auto_increment und INSERT IGNORE einfügt. Das Gleiche gilt auch für INSERT … ON DUPLICATE UPDATE, auch dort werden von InnoDB die auto_increments fälschlicherweise erhöht.
Falls Ihr trotzdem dichte IDs generieren möchtet (bei mir waren es zugegebenermaßen kosmetische Gründe, die mich dazu veranlasst haben), gibt es die folgenden Möglichkeiten:
innodb_autoinc_lock_mode = 0
in der my.cnf oder beim Starten des MySQL-Dienstes. Allerdings muss ich auch erwähnen, dass dieser Locking-Mode natürlich über eine wesentlich schlechtere Performance verfügt, da die Tabelle für jede Einfüge-Operation gesperrt werden muss.
Die Lösung zu diesem Problem liegt buchstäblich auf der Hand: Tastatur-Shortcuts.
Der vermutlich wichtigste Shortcut ist jener zum direkten Ausführen des soeben verfassten SQL-Statements: STRG + ENTER. Damit kann jener Befehl, in dem der Cursor gerade steht, direkt über die Tastatur ausgeführt werden. Alternativ können Sie auch STRG + SHIFT + ENTER verwenden, damit werden alle SQL-Statements im aktuellen Skript-Fenster nacheinander ausgeführt.
Shortcuts sind jedoch nicht nur für das sogenannte Abfragen-Fenster zum Verfassen von SQL-Statements verfügbar, sondern auch für viele weitere Funktionen, die die Workbench zur Verfügung stellt. Eine genaue Auflistung alle von der MySQL-Workbench angebotenen Shortcuts finden Sie auf der entsprechenden Seite der Dokumentation. Natürlich müssen Sie nicht alle diese Shortcuts beherrschen, aber gerade für Befehle oder Arbeitsschritte, die Sie besonders oft ausführen, kann es sehr sinnvoll sein, wenn Sie sich die entsprechenden Shortcuts aneignen.
]]>