Cassandra- und NoSQL-Basics, Teil 3 So funktionieren Abfragen in Apache Cassandra
Anbieter zum Thema
Die NoSQL-Datenbank Cassandra ist als skalierbares, ausfallsicheres System für den Umgang mit großen Datenmengen auf verteilten Systemen (Clustern) konzipiert. Im dritten Teil geht es um das Arbeiten mit Cassandra.

Hier geht es zu Teil 1 „Grundlagen der NoSQL-Datenbank Apache Cassandra“ und hier zu Teil 2 „So funktioniert Cassandra“.
Cassandra ist eine Datenbank, welche die einzelnen Datensätze in sogenannten multidimensionalen Hashtables ablegt und verwaltet. Eine Besonderheit dabei ist, dass jede Zeile eines Hashtables eine oder sogar beliebig viele Spalten haben kann. Insofern besteht Ähnlichkeit mit einer Relation in einem RDBMS oder, einfach ausgedrückt, einer riesigen Excel-Tabelle. Diese Spalten müssen aber nicht in jeder Zeile gleich sein, wie bei einer Relation in einem RDBMS. Identifiziert wird jede Zeile eines Hashtable über eine eindeutige ID. Man kann sich Cassandra also als zeilenorientierten, indizierten Store vorstellen.
Cassandras Datenmodell
Allerdings muss sich der Entwickler zu Beginn eines Projektes keinerlei Gedanken, machen, welche Art Daten er mit Cassandra speichern und verwalten will, da intern sämtliche Daten der beschriebenen Form eines multidimensionalen Hashtable verwaltet werden. In diesem Punkt ist das Datenmodell von Cassandra wieder eher mit einem Document-Store zur Aufnahme weitgehend unstrukturierter Daten vergleichbar, zumal der Nutzer jederzeit neue Spalten hinzufügen kann. Einige Merkmale und Begrifflichkeiten dürften aber auch für SQL-erfahrene Datenbank-Administratoren neu sein.
Keyspaces
Ferner gibt es im Datenmodell von Cassandra sogenannte Keyspaces. Mit Keyspaces wird die Datenhaltung in X-Richtung von der in Y-Richtung unterteilt. Darüber hinaus gibt es Column Families. Diese fassen Columns und so genannte Super Columns zusammen, allerdings entweder nur Columns oder Super Columns, nicht beide gleichzeitig. Erst dann kommt der Key, die eindeutige ID, wobei jeder Key auf einen eindeutigen Eintrag innerhalb einer Column Family verweist.
Keyspaces sind übrigens der einzige eindeutige Index im Datenmodell von Cassandra. Das eigentliche Speichern der Daten passiert dann entweder in Columns oder Super Columns. Bei einer Column speichert Cassandra zu je einem Namen einen Wert und den zugehörigen Key. Eine Super Column kann man sich als Organisationseinheit vorstellen, die hierarchisch eine Stufe oberhalb der Column angeordnet ist.
Folgendes Beispiel macht es deutlicher. Beim Speichern eines Adressdatensatzes „Users“ entsprächen die Einträge
„Privateadress: Hauptstr. 1“, „businessadress: Siemensstr. 2 “ und „postaladress: Poststr. 3“
einer Column, wobei eine Super Column mit dem Namen „adresses“ existieren könnte.
Das ist bei der einfachen Struktur von Key-Value Stores die einzige Möglichkeit, 1:n-Beziehungen direkt in einer Datenstruktur abzubilden und physisch zu speichern, während bei SQL-Datenbanken bekanntlich Joins zum Einsatz kämen. Joins stellen aber bei sehr großen Datenmengen ein Performanceproblem dar, da die Laufzeit viel zu lang ist.
Abfragen
Ohne SQL-Queries kann man mit Cassandra auch keine Abfragen im eigentlichen Sinne durchführen. Hier kommt MapReduce in Spiel, was nichts anderes bedeutet, als das Reduzieren der Gesamtdatenmenge auf den gewünschten Umfang. Das erfolgt über ein API.
NoSQL-Datenbanken speichern die Daten immer so ab, wie sie auch wieder abgerufen werden sollen, also sortiert. Das Prinzip „Sortierung folgt dem Anwendungszweck“ ist bei NoSQL-Datenbanken maßgeblich für die hohe Geschwindigkeit, während die Sortierung bei SQL ja erst im Zuge einer Query stattfindet.
Cassandra von der Kommandozeile
How-Tos und Anleitungen zum Installieren von Cassandra findet man im Internet zuhauf. Auf die relativ gut dokumentierte und vergleichsweise einfache Installation eines Cassandra-Datenbankknotens soll hier nicht weiter eingegangen werden. Eine hervorragende und umfassende Dokumentation zu Cassandra einschließlich der Installation findet sich z. B. bei Tutorialspoint.
Zu Evaluierungszwecken kann man sogar auf eine komplexe Cluster-Installation verzichten. Grundlegende Einstellungen speichert Cassandra in den Dateien storage-conf.xmlundcassandra.in.sh. Letztere ist dann für den Betrieb mehrerer Cassandra-Nodes mit der gleichen Datenbank essenziell.
Prinzipiell lässt sich die aktuelle Version 2.2.1 relativ einfach per
wget http://www.us.apache.org/dist/cassandra/2.2.1/apache-cassandra-2.2.1-bin.tar.gz
in einem Rutsch als gepacktes Archiv vom Server des Projektes in einem temporären Ordner herunterladen, entpacken und dann im gewünschten Verzeichnis platzieren. Hat man die von Cassandra benötigte Umgebung zuvor durch
- Einrichten der JVM
- Setzen einiger Umgebungsvariablen
- und Anlegen der von Cassandra erwarteten Verzeichnisse
vorbereitet, lässt sich ein lokaler Cassandra-Knoten nach dem Anpassen einiger weniger Konfigurationseinträge bzw. dem Ausführen von
~/cassandra/conf/cassandra-env.sh
mit
sudo sh ~/cassandra/bin/cassandra
z. B. unter Ubuntu recht einfach starten.
Cassandra-Client
In älteren Cassandra-How-Tos findet sich häufig noch der Hinweis, den zugehörigen CLI-Client z. B. auf dem gleichen Host mit
sh ~/cassandra/bin/ cassandra-cli -h localhost -p 9160
aufzurufen. Er lässt sich für Aufgaben im Zusammenhang mit Data Definition (DDL) und Data Manipulation (DML) verwenden. Für Datenabfragen, wie man sie von MySQL & Co. kennt (MapReduce-Prinzip), ist/war er nicht gedacht.
Allerdings ist das Cassandra-CLI noch ein Überbleibsel aus der Zeit, bevor es die SQL-ähnliche Abfragesprache CQL gab. Die Cassandra-Entwickler empfehlen unbedingt, zur CQL-Shell cqlsh zu wechseln. Diese unterstützt alles, was auch mit der CLI möglich war.
Cqlsh
Eine aktuelle Cassandra-Version stellt per Default die Cassandra query language shell (cqlsh) zur Kommunikation mit dem Cassandra-Server zur Verfügung. Mit cqlsh lassen sich Schemas definieren, Daten einfügen und Abfragen absetzen. Zum Starten der Shell genügt die Eingabe von
cqlsh
womit man automatisch beim Cassandra cqlsh prompt landet. Das sieht dann z. B. an einem Linux-Rechner so aus:
[hadoop@linux bin]$ cqlsh
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.1.2 | CQL spec 3.2.0 | Native protocol v3]
Use HELP for help.
cqlsh
Hinweis: Cassandra generiert bei der Installation automatisch einen entsprechendes Cluster mit dem Namen Test Cluster, mit dem sich cqlsh automatisch verbindet. Für erste Gehversuche tut es im Zweifel aber auch eine Online-Demo mit einer CQL Shell, wie sie z. B. Planet Cassandra zur Verfügung steht. Das Eingeben von
help
liefert den zur Verfügung stehenden Befehlsvorrat, gruppiert nach Document shell commands und cql-Befehlen. Zum Verlassen der Shell dient
quit
oder
exit
Keyspaces
Beim Anlegen einer neuen Datenbank sind zuerst Container, bei Cassandra Keyspaces genannt, einzurichten, was in etwa dem Schema in einer relationalen Datenbank entspricht. Der Keyspace funktioniert wie ein Namespace für die Datenbankanwendung und kapselt die darin enthaltenen Daten in Form von Column Families, Tables und Konfigurationen. Zum Erstellen eines Keyspace „demo“ gibt man in der Cassandra-CLI
CREATE KEYSPACE demo WITH replication = {
'class': 'SimpleStrategy',
'replication_factor': '1'
};
ein. Um den neuen Keyspace zu verwenden, genügt dann ein
USE demo;
Der Prompt ändert sich dann damit zu
: cqlsh:demo>
Jetzt ist es möglich, in diesem Keyspace, Tables, bzw. Column Families anzulegen, die wiederum aus Columns und Rows bestehen können. Das Erstellen einer Tabelle users im keyspace demo, in dem dann letztendlich die Daten abgelegt werden, erfolgt dann mit
CREATE TABLE users (
firstname text,
lastname text,
age int,
email text,
city text,
PRIMARY KEY (lastname));
Damit hat man eine Tabelle mit einem einfachen primären Schlüssel lastname kreiert.
Diese Vorgehensweise zum Erstellen einer Table oder Column Family, bei der man bereits vorher die Struktur der Datenbank und der einzelnen Attribute kennt, heißt statisch.
Cassandra kennt aber auch die o. g. dynamischen Column Families. Hier werden beim Erstellen der Column Family keine Spaltendefinitionen angegeben. Vielmehr werden diese dann von der Applikation selbst generiert.
Um die einzelnen Attribute der Tabelle Users anzuzeigen, genügt das Eingeben von
DESCRIBE TABLE users;
Um erste Zeilen mit Daten in der Users-Tabelle einzufügen, dient z. B. derINSERT INTO-Befehl. Hierbei ist nach jedem Statement ENTER zu drücken, um die neue Zeile in die Tabelle zu übernehmen.
INSERT INTO users (firstname, lastname, age, email, city) VALUES ('Thomas', 'Drilling', 48, 'info@thomas-drilling.de', 'Kassel');
INSERT INTO users (firstname, lastname, age, email, city) VALUES ('Max', 'Muster', 39, 'max@muster.com', 'Augsburg');
usw. Ein
SELECT * FROM users;
liefert dann sämtliche Inhalte der Tabelle users sortiert nach „lastname“, der ja als Primärschlüssel fungiert.
Mit dem WHERE-Kommando in Verbindung mit dem SELECT-Statement, lässt sich gezielt nach einem Wert fahnden.
SELECT * FROM users WHERE lastname= 'Drilling';
Hier wird die gewollte Ähnlichkeit zu SQL sichtbar. Da Cassandra keine reinen Read-Operationen „vor“, bzw. „ohne“ Write-Operation kennt, führen INSERT und UPDATE beide zu einer Aktualisierung des betreffenden Spaltenwertes, egal ob bereits Daten existieren.
Das UPDATE-Kommando kommt z. B. zum Einsatz, um Änderungen unter Zuhilfenahme des Primärschlüssels zu übernehmen. Soll für den Eintrag lastname=Drilling (Primärschlüssel) der Wert für City aktualisiert werden, klappt das mit
UPDATE users SET city= 'Frankfurt' WHERE lastname= 'Drilling';
Die Aktualisierung lässt sich wie gehabt mit
SELECT * FROM users WHERE lastname= 'Drilling';
übernehmen. Zum Löschen einer Spalte dient das DELETE-Kommando:
DELETE from users WHERE lastname = 'Drilling';
Auch das kann mit wie folgt überprüft werden.
SELECT * FROM users;
Artikelfiles und Artikellinks
(ID:43734755)