View
267
Download
3
Category
Tags:
Preview:
Citation preview
Column Stores
Arno SchmidhauserLetzte Revision: Januar 2011
Neues technisches Umfeld• RAM Zugriff: 1 GB/sec Random (Seek Time 1-3 nsec, 3-6 Bus-
Cycles, 64 Byte Block), 10 GB/sec Maximum(Peak) • Diskzugriff: 1 MB/sec Random (Seek Time 1 msec, 1 KB Block),
100 MB/sec Stream.• Sehr performante Vektorverarbeitung in modernen CPU's mit
mehreren Cache-Levels.• Das Absuchen eines Vektors mit 106 Datensätzen à 10 Bytes
dauert ca 0.01sec bei 1GB/sec, 0.001sec bei 10 GB/sec.• Verfügbares Memory problemlos > 4 GB für Standard Server.• Memory hat kleinere Random/Stream Problematik, Durchsatz ist
unabhängiger vom Ort der Daten im Ggs. zu Disk.
Neue Anfragetypen
Früher vorallem OLTP
select * from Bestellungwhere id = 4711
insert into Bestellungvalues (…)
datensatzweise Abfragen
Heute zunehmend OLAP
select avg( betrag )from Bestellung
spaltenweise Abfragen
Leseoperation überwiegen
• Frühe Annahme: Einfügen, Ändern, Löschen machen einen relevanten Anteil der Datenbankoperationen aus.
• Neue Untersuchungen: Selbst bei OLTP-Systemen überwiegen heute die AnzahlLeseoperationen deutlich.
Viele Spalten mit wenig Werten
• Sehr viele Spalten in Datenbanksystem enthalten tatsächlich nur wenig verschiedene Werte.
• Beispiel: 29% aller Spalten (Attribute) enthalten lediglich 2 bis 32 verschiedene Werte.
Column Stores, wofür?
• Für viele Anwendungen ist die Architektur klassischer Datenbanksysteme nicht optimal. Der Datensatz als logische und technische Einheit ist nicht immer sinnvoll.
• Column Stores sind eine neue technologische Richtung. Im Fokus steht dabei:– Leseoperationen überwiegen gegenüber Änderungen.– Abfragen überstreichen oft einen grossen Teil der
vorhanden Daten. – Spaltenorientierte Abfragen überwiegen.– Ganze Spalten oder ganze DB wird im Speicher gehalten.– Vorallem numerische und kleine Datentypen, wenig
Strings.
Zeilenspeicherung
• Die klassische Datenbank-Technologie geht von OLTP-Applikationen aus:
1. Datensatzorientierte Speicherung2. Sequentielle Anhäufung von Datensätzen3. Seitenorientierte Zusammenfassung von Datensätzen
Page 1 (Disk und Memory)
Datensatz 1 Date-
satz 2 Datensatz 3
Datensatz 4 Datensatz
5 Datensatz 6
Datensatz 7 Datensatz 8
Page 2 (Disk und Memory)
Datensatz 9 Date-
satz 10 Datensatz 11
Datensatz 12 Datensatz
1 3 Datensatz 14
Datensatz 15 Datensatz 16
Spaltenspeicherung
• Wenn OLAP-Anfragen dominieren, sind spaltenorientierte Speichertechnologieneffizienter:
• Nur benötigte Spalten ins Memory laden,dafür Spalte in der ganzen Länge.
• Effiziente Aggregatbildung.• Zugehörigkeit eines Attributwertes
in einer Spalte zu einem Datensatz:1. duch die Position (Array)2. durch einen Schlüssel (ObjectId, RecordId)
Spa
lte A
Spa
lte B
Spa
lte C
Datensatz 1 w1 w1 w1Datensatz 2 w2Datensatz 3 w3 w2Datensatz 4 w4 w2Datensatz 5 w5 w3
w4 w3
w5w4
w5
Zeilen- und Spaltenspeicherung
Spa
lte A
Spa
lte B
Spa
lte C
Spa
lte D
Spa
lte E
Spa
lte N
Datensatz 1Datensatz 2Datensatz 3Datensatz 4Datensatz n
effizient
Datensatz 1Datensatz 2Datensatz 3Datensatz 4Datensatz n
ineffizient
inef
fizie
ntef
fizie
nt
Spaltenorientierte Speicherung
Datensatzorientierte Speicherung
OLT
PO
LAP
Komprimierung
• Ein wesentlicher Vorteil von Column-Stores liegt darin, dass Spalten oft eine hohe Anzahl gleicher Werte enthalten.
• Komprimierung der Daten auf der Disk beschleunigt das Laden und Speichern der Datenbank bei den Checkpoints.
• In der Regel heute im Memory dekomprimiert.• Neueste Entwicklungen jedoch so, dass Daten auch im
Memory komprimiert abgelegt sind, und erst für die Verarbeitung in der CPU (Level 2 Cache) dekomprimiert werden.
Run Length Encoding
• Sehr effizient für sortierte Spalten, Beispiel:
1 1;51 3;21 10;511331010101010
Quantity(Wert;Anzahl)
Quantityunkompr.
Delta Encoding
• Variante 1: Numerische Werte werden als Differenz zum kleinsten Wert codiert.
• Variante 2: Numerische Werte werden als Differenz zum jeweils vorhergehenden Wert dargestellt.
Bit Vector Encoding
• für Spalten mit wenigverschiedenen Werten,z.B. Geschlecht, Wochentag, Land, Status usw.
Bit Vektor Werte1000000 Montag0100000 Dienstag0010000 Mittwoch0001000 Donnerstag0000100 Freitag0000010 Samstag0000001 Sonntag
Tabelle mit Bit Vektor WertenWochenTag Artikel ID Kunden ID Menge
0000001 43 4711 1.000000010 56 4711 2.000000100 43 6900 1.00
Bit Vektor Index0000001 heisst: Datensatz 1 hat den Wert 00000010000010 heisst: Datensatz 2 hat den Wert 00000100000100 heisst: Datensatz 3 hat den Wert 0000100
Dictionary Encoding
• Lange und wiederholt vorkommende Werte werden in einen Dictionary ausgelagert:
• Wird z.B. auch bei der XML Speicherung für Element-namen verwendet!
DokumentURL Begriff ID
ti.bfh.ch Studiumti.bfh.ch Bachelor
hkb.bfh.ch Studiumhkb.bfh.ch Kunst
Dokument DictionaryURL dict ID dict ID Begriff
ti.bfh.ch 1 1 Studiumti.bfh.ch 2 2 Bachelor
hkb.bfh.ch 1 3 Kunsthkb.bfh.ch 3
Indexierungsstrategie
• Bei klassischen Datenbanken werden alle Index auf Disk gespeichert. Indexstrukturen können grösser als die Datenbank selbst sein, oft sogar bis Faktor 10.
• Column Stores und In Memory Datenbank halten Indexe nur im Memory. Indexe unterliegen keinem Recovery bei einem System Crash, sondern werden neu gebaut.
• Indexzugriffe erfordern bei Column Stores nie Disk-I/O. Indexe referenzieren nur Memory-Adressen oder Arraypositionen in Spalten, jedoch keine externen Datensatz ID's, Primary Keys o.ä.
Produktbeispiel MonetDB
• Open Source, Enge Zusammenarbeit mit Open Source Datawarehouse Tools von Pentaho.
• SQL 93 kompatibel.• ACID kompatibel, Snapshot-Isolation.• Schnelles Erzeugen und Laden von Spalten-Files mit COPY
Utility.• Extrem schnell bei spaltenorientierten Abfragen (Bis zu
Faktor 100 gegenüber mySQL).• Performance bezüglich Einfügen, Ändern, Löschen mit SQL
ist kritisch, da bei Checkpoints ganze Spalten-Files geschrieben werden.
• Kommerzielle Weiterentwicklung im Rahmen von Ingres Vectorwise.
Tabellen, Aufspaltung in Spalten
• Originale Tabelle
• Pro Attribut eine binäre Relation (BAT)im Memory mit Objekt-ID's und Attributwerten
• Binary Association Tables (BATs) sind die Grundstruktur der Tabellenspeicherung in MonetDB (und anderen ColumnStores)
Binary Association Table (BAT)
Hash Zugriff mit OID als Schlüssel
Memory Mapped File (.tail)Kompression auf Disk, um I/O zu vermindern.
Kompressiosnsvarianten siehe weiter unten
Werden beim Laden erzeugt
Indexierung
• Beim ersten Zugriff auf ein Attribut wird eine Kopie seiner BAT erstellt. Diese Kopie wird als Index nachgeführt und schrittweise verfeinert, z.B. bei der ersten Abfrage wie folgt:
> 0.1
≤ 0.1
select … from Discount where Discount > 0.1
Kopie
Einfaches Query
• Abfrage:
select * from Discount where Discount > 0.1
• Ausführung:
1. Sequentielles Scannen der Discount-BAT: alle OID's suchen, für die Discount > 0.1.
2. Mit den OID's in den übrigen BATs die anderen Attribute des Datensatzes suchen.
Aggregat Query
• Abfrage:
select Day, avg(Discount) from Discountwhere Discount = 0.065 and Day = '9/4/98'
• Ausführung ohne Index:
1. Spalten sequentiell scannen und je einen Bit-Vektor bilden: 1 = Bedingung erfüllt, 0 = Bedingung nicht erfüllt.
2. and-Verknüpfung der beiden Bit-Vektoren durchführen.3. Korrespondierende Array-Positionen in der Day- und
Discount-BAT entnehmen, avg() bilden und ausgeben.
Aggregat Query
select Day, avg(Discount) from Discountwhere Discount = 0.065 and Day = '9/4/98'
01000
01001
01000
AND
Aggregat Query mit Joins
• Beispiel einer Join-Abfrage
select o.year, sum(o.quantity)from Order o, Customer c, Product pwhere o.custID = c.custID and o.prodID = p.prodIDand p.name = 'P1'and c.region = 'europe'group by o.year
• Im folgenden soll die spaltenorientierte Verarbeitung dieser Abfrage gezeigt werden.
Join, Tabellen
OrdercustID prodID year quantity
1 1 2009 101 5 2010 102 1 2009 10003 1 2009 5003 4 2009 5003 2 2010 5002 1 2007 100
CustomercustID name region
1 C1 europe2 C2 europe3 C3 asia4 C4 asia5 C5 pacific
ProductprodID name
1 P12 P23 P34 P45 P5
Join, Spalten
• Achtung: Die Datenbank besteht physisch aus einer Sammlung von Spalten (BATs in MonetDB)
OID o.custID OID o.prodID OID o.year OID o.quantity1001 1 1001 1 1001 2009 1001 101002 1 1002 5 1002 2010 1002 101003 2 1003 1 1003 2009 1003 10001004 3 1004 1 1004 2009 1004 5001005 3 1005 4 1005 2009 1005 5001006 3 1006 2 1006 2010 1006 5001007 2 1007 1 1007 2007 1007 100
BAT BAT BAT BAT
OID c.custID OID c.name OID c.region OID p.prodID OID p.name101 1 101 C1 101 europe 201 1 201 P1102 2 102 C2 102 europe 202 2 202 P2103 3 103 C3 103 asia 203 3 203 P3104 4 104 C4 104 asia 204 4 204 P4105 5 105 C5 105 pacific 205 5 205 P5
BAT BAT BATBAT BAT
Join, Ablauf, Schritt 1 und 2
c.region = 'europe'BV1 TB1
OID c.region Bit OID c.custID custID101 europe 1 101 1 1102 europe 1 102 2 2103 asia 0 103 3104 asia 0 104 4105 pacific 0 105 5
p.name = 'P1'BV2 TB2
OID p.name Bit OID p.prodID prodID201 P1 1 201 1 1202 P2 0 202 2203 P3 0 203 3204 P4 0 204 4205 P5 0 205 5
Join, Ablauf Schritt 1 und 2
Operation Algorithmus Resultat
c.region = 'europe' auswerten
linearer Scan über c.region (Verbesserung für Stringdaten:Indexzugriff, Dictionary Lookup, Komprimierte Daten usw.)
BV1: Bit Vektor, ermittelt über c.region, welcher pro Position in der Customer Tabelle angibt, ob der Datensatz die Bedingung erfüllt.
BV1 auf c.custID anwenden Scan über BV1 und c.custID, jeweils in beiden Vektoren Position für Position vorrücken, da beide gleichviele Einträge haben. Alle custID entnehmen, welche an entsprechender Positione im Bit Vektor eine 1 haben.
TB1: Temoräre BAT mit allen custID. CustID als Hashkey
p.name = 'P1' auswerten linearer Scan über p.name (Verbesserung
für Stringdaten:Indexzugriff, Dictionary Lookup, Komprimierte Daten usw.)
BV2: Bit Vektor, ermittelt über c.region, welcher pro Position in der Product Tabelle angibt, ob der Datensatz die Bedingung erfüllt
BV2 auf p.prodID anwenden Scan über BV2 und p.prodtID, jeweils in beiden Vektoren Position für Position vorrücken, da beide gleichviele Einträge haben. Alle prodID entnehmen, welche an entsprechender Positione im Bit Vektor eine 1 haben.
TB1: Temoräre BAT mit allen prodID. ProdID als Hashkey
Join-Ablauf, Schritt 3 bis 7TB1 1
custID 2
BV3OID o.custID Bit
1001 1 11002 1 11003 2 11004 3 01005 3 0 BV41006 3 0 Bit OID o.year OID o.quantity1007 2 1 1 1001 2009 1001 10
0 1002 2010 1002 101 1003 2009 1003 1000
AND Verknüpfung 0 1004 2009 1004 500TB2 1 0 1005 2009 1005 500
prodID 0 1006 2010 1006 5001 1007 2007 1007 100
BV4OID o.prodID Bit OID o.year
1001 1 1 1001 20091002 5 0 1003 20091003 1 1 1007 20071004 1 11005 4 01006 2 0 o.year1007 1 1 2009
2007
Scan über o.custID mit Lookup in TB1. Wenn custID in TB1 vorkommt, dann in BV3 1 eintragen.
o.quantity1010100
1000100
Aus den BATs o.year und o.quantity Zeilen gemäss Bit Vektor BV4 entnehmen.
Gruppiert = Sortiert und zusammen-gefasst, z.B. über Merge-Sort
o.quantity10
Scan über o.prodID mit Lookup in TB2. Wenn custID in TB2 vorkommt, dann in BV4 1
Join-Ablauf, Schritt 3 bis 7
c.region = 'europe' auswerten linearer Scan über c.region (Verbesserung für Stringdaten:Indexzugriff, Dictionary Lookup, Komprimierte Daten usw.)
BV1: Bit Vektor, ermittelt über c.region, welcher pro Position in der Customer Tabelle angibt, ob der Datensatz die Bedingung erfüllt.
BV1 auf c.custID anwenden Scan über BV1 und c.custID, jeweils in beiden Vektoren Position für Position vorrücken, da beide gleichviele Einträge haben. Alle custID entnehmen, welche an entsprechender Positione im Bit Vektor eine 1 haben.
TB1: Temoräre BAT mit allen custID. CustID als Hashkey
p.name = 'P1' auswerten linearer Scan über p.name (Verbesserung für Stringdaten:Indexzugriff, Dictionary Lookup, Komprimierte Daten usw.)
BV2: Bit Vektor, ermittelt über c.region, welcher pro Position in der Product Tabelle angibt, ob der Datensatz die Bedingung erfüllt
BV2 auf p.prodID anwenden Scan über BV2 und p.prodtID, jeweils in beiden Vektoren Position für Position vorrücken, da beide gleichviele Einträge haben. Alle prodID entnehmen, welche an entsprechender Positione im Bit Vektor eine 1 haben.
TB1: Temoräre BAT mit allen prodID. ProdID als Hashkey
Vergleich o.custID mit Einträgen in TB1 Scan über o.custID, lookup jeder custID in TB1 BV3: Bit Vektor, welcher pro Eintrag in o.custID angibt, ob die entsprechende custID in TB1 vorkommt.
Vergleich o.prodID mit Einträgen in TB2 Scan über o.prodID, lookup jeder custID in TB2 BV4: Bit Vektor, welcher pro Eintrag in o.custID angibt, ob die entsprechende custID in TB2 vorkommt.
AND Verknüpfung auswerten AND Verknüpfung von BV3 und BV4 BV5: Bit Vektor, welcher pro Eintrag für Tabelle Order angibt, ob er den Bedingungen c.region = 'europe' und p.name = 'P1' genügt.
� BV5 auf o.year anwenden linearer Scan über BV5 und o.year TB3: Temporäre BAT mit year
BV5 auf o.quantity anwenden linearer Scan über BV5 und o.quantity TB4: Temporäre BAT mit quantity
Algorithmus zum Gruppieren anwenden
Verbund von TB3 und TB4 TB5: Temporäre BAT mit 2 Attributen (year, quantity)
TB5 sortieren nach year, summieren von quantity
Irgendeine Gruppier-Algorithmus, z.B. Sortieralgorithmus, z.B. Merge-Sort, dann zusammenfassen.
Ausgabe von year und sum(quantity)
Produktbeispiel Ingres Vectorwise
• kommerzielles Produkt. 64 Bit auf Windows, Linux und als Amazon Webservice (Amazon Machine Image).
• Datensätze, resp. Werte in den Spalten werden in Einfügereihenfolge gespeichert (RAW Mode).
• Parameter block_size definiert Blockgrösse, die für das Ablegen von Spalten benützt werden. Ein Block ist die I/O Einheit zur Disk. Jeder Block beinhaltet Statistikangaben, z.B. grösster und kleinster Spaltenwert.
• Blöcke werden komprimiert. Datenbank bestimmt automatisch Algorithmus pro Block: Run Length Encoding, Dictionary Encoding und Delta Encoding.
Produktbeispiel Ingres Vectorwise
• Von jedem Datenblock einer Spalte wird der Minimum und Maximumwert im Memory gehalten ("Index" ).
• Jede Tabellen kann einen Clustered Index haben (create index Befehl). Keine anderen Indexe sind möglich.
• Indexstrukturen werden ausschliesslich im Memory gehalten (Bei Crash zerstört).
• Änderungen werden über Positional Delta Trees verwaltet. Bei einem bestimmtem Umfang an Änderungen wird die gesamte DB auf Disk propagiert (Checkpoint).
Änderungen in Column Stores
• Einfügen/Ändern/Löschen in Column Stores werden als "notwendiges Übel" angesehen, im Gegensatz zur klassischen DB-Technologie.
Änderungen über eine bestimmte Zeit hinweg in einer "Delta-Struktur" sammeln.Bei Checkpoint anwenden auf Hauptstruktur der Datenbank.
HauptstrukturDisk/Memory
Spalte/Datensatz
Delta-Struktur (Änderungen)
Nach Checkpoint
A a einfügen aB a einfügen aC a einfügen aD d einfügen AE B ändern auf b bF C löschen d
DEF
Positional Delta Tree, PDT
• Der Positional Delta Tree ist eine hocheffiziente Delta-Struktur, damit beim Lesen von Spalten auch Änderungen miteinbezogen werden.
• Ausgangslage:– Spalten (oder Datensätze) liegen in einer bestimmten
Sortierung vor, die bei Abfragen verwendet wird.– Die Sortierung von Spalten und Datensätzen muss
daher zusammen mit der Delta-Struktur jederzeit rekonstruiert werden können.
– Die Delta-Struktur darf Abfragen nur minimal verlangsamen.
PDT-Beispiel, Tabelle
• Die SID ist die Position des Datensatzes, respektive der Spaltenwerte, auf Disk oder im Memory, wenn noch keine Änderungen stattgefunden haben.
Sortier-Schlüssel, physische Reihenfolge
PDT-Beispiel, Änderungsbefehle
• Folgende Änderungen sollen nun vorgenommen werden:
1. INSERT INTO inventory VALUES ('Berlin','table','Y',10)2. INSERT INTO inventory VALUES ('Berlin','cloth','Y',5)3. INSERT INTO inventory VALUES ('Berlin','chair','Y',20)4. INSERT INTO inventory VALUES ('Paris','sofa','Y',3)5. UPDATE inventory SET qty=13 WHERE store='London' AND
product='stool'6. DELETE FROM inventory WHERE store='London' AND product='table'
Durch die Änderungen erzeugter PDT
PDT-Beispiel, neue Tabelle
• Die nach dem Checkpoint erzeugte Tabelle sieht wie folgt aus:
Mehrschichtige Deltastruktur
• Delta-Strukturen können auch zur Realisierung von Snapshot-Isolation verwendet werden.
• Für jede neue Transaktion: Datenbankweite Delta-Struktur für die Transaktion kopieren, und mit Zeitstempel resp. Versionennummer der Transaktion versehen.
• Transaktion arbeitet mit der kopierten Delta-Struktur lokal für sich weiter.
• Beim Commit: lokale Delta-Struktur der Datenbank übergeben. Diese gleicht mit der datenbankweiten Delta-Struktur ab (Siehe Versionenverfahren für Concurrency Control).
Spaltenspeicherung in klassischen DB's
• Ideen der Spaltenspeicherung zur Abfrage-Beschleunigung existieren bereits in den klassischen Datenbanksystemen. Beispiel mit MSSQL 2008:
create index on Bestellung ( bestDatum )include ( menge )
Das Attribut menge wird damit in den Blattknoten des Index abgelegt. So wird für folgende Abfragen der Zugriff auf die Haupttabelle überflüssig:
select bestDatum, sum( menge )from Bestellunggroup by bestDatum
Spaltenspeicherung in klassischen DB's
• Pros: – Perfekt integriert in bestehende DB-Lösung. – 100% unsichtbar gegenüber Applikationen und
Clientsystemen.– Macht das Laden der Basistabelle überflüssig, wenn die
Abfrage aus allen Attributen des Index befriedigt werden kann.
• Cons:– Klassische I/O Technologie: der Index muss zuerst
geladen werden. I/O Pages sind nicht immer garantiert im Memory.
– Index kann andere Daten aus dem Memory verdrängen, da er zusätzlich Platz benötigt.
Zusammenfassung Column Stores
• Für grosse Datenbanken mit Schwergewicht OLAP Abfragen.• Abfrage-Performance kann sich um Faktor 100 verbessern,
bei vergleichbarer Hardware.• Schlechtere Update-Performance.• Gute Bulk-Load Performance, da einfache Datenstrukturen
(wenig Indexe). Eignung als Datawarehouse oder Data Mart.
DWH
Data Mart
Quelldaten
Data Mart
QuelldatenQuelldaten
ETL Column Store Load
Produkte
• MonetDB • SybaseIQ• Ingres Vectorwise• SyncSort• Vertica• Informatica
Recommended