983 lines
50 KiB
Markdown
983 lines
50 KiB
Markdown
# Motivation und Grundlagen
|
||
## Aufgaben und Komponenten eines DBMS
|
||
Prinzipien: Die neun Codd’schen Regeln
|
||
1. Integration: einheitliche, nichtredundante Datenverwaltung
|
||
2. Operationen: Speichern, Suchen, Ändern
|
||
3. Katalog: Zugriffe auf Datenbankbeschreibungen im Data Dictionary
|
||
4. Benutzersichten
|
||
5. Integritätssicherung: Korrektheit des Datenbankinhalts
|
||
6. Datenschutz: Ausschluss unauthorisierter Zugriffe
|
||
7. Transaktionen: mehrere DB-Operationen als Funktionseinheit
|
||
8. Synchronisation: parallele Transaktionen koordinieren
|
||
9. Datensicherung: Wiederherstellung von Daten nach Systemfehlern
|
||
|
||
Betrachtete Fragestellung
|
||

|
||
|
||
**Zentrale Komponenten**
|
||
- **Anfrageverarbeitung** : Planung, Optimierung und Ausführung deklarativer Anfragen
|
||
- **Transaktionsverwaltung** : Koordination und Synchronisation von Transaktionen, Durchführung von Änderungen, Sicherung der ACID-Eigenschaften
|
||
- **Speichersystem** : Organisation der Daten im Hauptspeicher und auf dem Externspeicher für effizienten Zugriff und Persistenz
|
||
|
||
## Relationale vs. nicht-relationale DBMS
|
||
**Relationale DBMS**
|
||
- Basis: **Relationenmodell** = Daten in Tabellen strukturiert
|
||
- Beziehungen über Werte (= Fremdschlüssel),
|
||
Integritätsbedingungen
|
||
- **SQL** als standardisierte Anfragesprache
|
||
- kommerziell erfolgreichstes Datenmodell: Oracle, IBM DB2,
|
||
MS SQL Server, SAP HANA, ...
|
||
|
||
| WEINE | WeinID | Name | Farbe | Jahrgang | Weingut |
|
||
| ----- | ----------------- | ---- | ----- | ----------- | ------- |
|
||
| 1042 | La Rose Grand Cru | Rot | 1998 | Château ... |
|
||
| 2168 | Creek Shiraz | Rot | 2003 | Creek |
|
||
| 3456 | Zinfandel | Rot | 2004 | Helena |
|
||
| 2171 | Pinot Noir | Rot | 2001 | Creek |
|
||
| 3478 | Pinot Noir | Rot | 1999 | Helena |
|
||
| 4711 | Riesling Reserve | Weiß | 1999 | Müller |
|
||
| 4961 | Chardonnay | Weiß | 2002 | Bighorn |
|
||
|
||
**Kritik an RDBMS / SQL**
|
||
- nicht skalierbar
|
||
- Normalisierung von Relationen, viele Integritätsbedingungen zu prüfen
|
||
- kann man in RDBMS auch vermeiden!
|
||
- starre Tabellen nicht flexibel genug
|
||
- schwach typisierte Tabellen (Tupel weichen in den tatsächlich genutzten Attributen ab)
|
||
- viele Nullwerte wenn alle potentiellen Attribute definiert
|
||
- alternativ Aufspaltung auf viele Tabellen
|
||
- Schema-Evolution mit **alter table** unflexibel
|
||
- tatsächlich in vielen Anwendungen ein Problem
|
||
- Integration von spezifischen Operationen (Graphtraversierung, Datenanalyse-Primitive) mit Stored Procedures zwar möglich führt aber oft zu schwer interpretierbarem Code
|
||
|
||
**NoSQL-Systeme**
|
||
- Datenmodelle
|
||
- KV-Stores
|
||
- Wide Column Stores
|
||
- Dokumenten-orientierte Datenhaltung
|
||
- Graph-Speicher
|
||
- ...
|
||
- Anfragesprache -> unterschiedliche Ansätze:
|
||
- einfache funktionale API
|
||
- Programmiermodell für parallele Funktionen
|
||
- angelehnt an SQL-Syntax
|
||
- ...
|
||
- Beispiele
|
||
- dokumentenorientierte Datenbanksysteme: MongoDB
|
||
- semistrukturierte Dokumente in JSON- bzw. BSON-Format
|
||
- Anfragen: CRUD erweitert um dokumentspezifische Suche
|
||
- Graph-Datenbanksysteme: Neo4j
|
||
- Property Graphen als Datenmodell: Knoten und Kanten mit Eigenschaften
|
||
- Anfragesprache Cypher
|
||
- Muster der Form "Knoten -> Kante -> Knoten ..."
|
||
|
||
## OLTP, OLAP und HTAP
|
||
### OLTP vs OLAP
|
||
| | Online Transactional Processing (OLTP) | Online Analytical Processing (OLAP) |
|
||
| -------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
||
| | -> Klassische operative Informationssysteme | -> Data Warehouse |
|
||
| | Erfassung und Verwaltung von Daten | Analyse im Mittelpunkt = entscheidungsunterstützende Systeme |
|
||
| | Verarbeitung unter Verantwortung der jeweiligen Abteilung | Langandauernde Lesetransaktionen auf vielen Datensätzen |
|
||
| | Transaktionale Verarbeitung: kurze Lese-/ Schreibzugriffe auf wenigen Datensätzen | Integration, Konsolidierung und Aggregation der Daten |
|
||
| | ACID-Eigenschaften | |
|
||
| | |
|
||
| **Anfragen** | |
|
||
| Fokus | Lesen, Schreiben, Modifizieren, Löschen | Lesen, periodisches Hinzufügen |
|
||
| Transaktionsdauer und -typ | kurze Lese- / Schreibtransaktionen | langandauernde Lesetransaktionen |
|
||
| Anfragestruktur | einfach strukturiert | komplex |
|
||
| Datenvolumen einer Anfrage | wenige Datensätze | viele Datensätze |
|
||
| Datenmodell | anfrageflexibel | analysebezogen |
|
||
| Antwortzeit | msecs ...secs | secs ...min |
|
||
| | |
|
||
| **Daten** | |
|
||
| Datenquellen | meist eine | mehrere |
|
||
| Eigenschaften | nicht abgeleitet, zeitaktuell, autonom, dynamisch | abgeleitet / konsolidiert, historisiert, integriert, stabil |
|
||
| Datenvolumen | MByte ...GByte | GByte ...TByte ...PByte |
|
||
| Zugriffe | Einzeltupelzugriff | Tabellenzugriff (spaltenweise) |
|
||
|
||
**OLTP: Beispiel**
|
||
```sql
|
||
BEGIN ;
|
||
SELECT KundenNr INTO KNr
|
||
FROM Kunden WHERE email = '...';
|
||
INSERT INTO BESTELLUNG VALUES (KNr, BestNr, 1);
|
||
UPDATE Artikel SET Bestand = Bestand-1
|
||
WHERE ArtNr = BestNr;
|
||
COMMIT TRANSACTION ;
|
||
```
|
||
|
||
**OLAP: Beispiel**
|
||
```sql
|
||
SELECT DISTINCT ROW Zeit.Dimension AS Jahr,
|
||
Produkt.Dimension AS Artikel,
|
||
AVG(Fact.Umsatz) AS Umsatzdurchschnitt,
|
||
Ort.Dimension AS Verkaufsgebiet
|
||
FROM (Produktgruppe INNER JOIN Produkt ON Produktgruppe.
|
||
[Gruppen-Nr] = Produkt.[Gruppen-ID]) INNER JOIN
|
||
((((Produkt INNER JOIN [Fact.Umsatz] ON Produkt.[Artikel-Nr]
|
||
= [Fact.Umsatz].[Artikel-Nr]) INNER JOIN Order ON
|
||
[Fact.Umsatz].[Bestell-Nr]= Order.[Order-ID]) INNER JOIN
|
||
Zeit.Dimension ON Orders.[Order-ID] =
|
||
Zeit.Dimension.[Order-ID]) INNER JOIN Ort.Dimension ON
|
||
Order.[Order-ID] = Ort.Dimension.[Order-ID]) ON
|
||
Produktgruppe.[Gruppen-Nr] = Produkt.[Gruppen-ID]
|
||
GROUP BY Produkt.Dimension.Gruppenname, Ort.Dimension.Bundesland,
|
||
Zeit.Dimension.Jahr;
|
||
```
|
||
|
||
### HTAP
|
||
- HTAP = Hybrid Transactional and Analytics Processing
|
||
- Ziel: schnellere Geschäftsentscheidungen durch "Echtzeit"-Verarbeitung
|
||
- OLAP und OLTP auf der gleichen Datenbank: naheliegend aber große technische Herausforderung
|
||
- sehr unterschiedliche Workloads (Anfrage- und Lastprofile)
|
||
- Transaktionsverwaltung: gegenseitige Beeinflussung von Änderungs- und Leseoperationen reduzieren
|
||
- unterschiedliche Datenorganisation (physisch, logisch)
|
||
- Herausforderungen
|
||
- Analytical (OLAP) und Transactional processing (OLTP)
|
||
- verschiedene Zugriffscharakterisiken
|
||
- verschiedene Performance-Ziele (Latenz vs. Durchsatz)
|
||
- => Unterschiedliche Optimierungen notwendig
|
||
|
||
## Disk- vs. Main-Memory-Systeme**
|
||
**Traditionelle Annahmen**
|
||
- Daten sollen dauerhauft aufbewahrt werden
|
||
- Datenbank >> Hauptspeicher
|
||
- Disk >> Hauptspeicher
|
||
- Hauptspeicher = flüchtiger (volatiler) Speicher
|
||
- Disk-IO dominiert Kosten
|
||
|
||
**Speicherhierarchie**
|
||

|
||
|
||
**Eigenschaften von Speichermedien**
|
||
| | Primär | Sekundär | Tertiär |
|
||
| --------------- | -------- | --------- | ------------ |
|
||
| Geschwindigkeit | schnell | langsam | sehr langsam |
|
||
| Preis | teuer | preiswert | billig |
|
||
| Stabilität | flüchtig | stabil | stabil |
|
||
| Größe | klein | groß | sehr groß |
|
||
| Granulate | fein | grob | grob |
|
||
|
||
**Speichermedien**
|
||
- **Primärspeicher**
|
||
- Primärspeicher: Cache und Hauptspeicher
|
||
- sehr schnell, Zugriff auf Daten fein granular: theoretisch jedes Byte adressierbar (Cachelines)
|
||
- **Sekundärspeicher**
|
||
- Sekundärspeicher oder Online-Speicher
|
||
- meist Plattenspeicher, nicht-flüchtig
|
||
- Granularität des Zugriffs gröber: Blöcke, oft 512 Bytes
|
||
- Zugriffslücke: Faktor 10^5 langsamerer Zugriff
|
||
- **Tertiärspeicher**
|
||
- Zur langfristigen Datensicherung (Archivierung) oder kurzfristigen Protokollierung (Journale)
|
||
- üblich: optische Platten, Magnetbänder
|
||
- "Offline-Speicher" meist Wechselmedium
|
||
- Nachteil: Zugriffslücke extrem groß
|
||
|
||
|
||
**Transferraten HDD vs. SSD**
|
||

|
||
|
||
**Konsequenz für disk-basierte Systeme**
|
||
- blockbasierter Zugriff mit typischen Blockgrößen ≥ 4 KB
|
||
- speziell für Magnetplatten Optimierung auf sequentielle Zugriffe
|
||
- Disklayout: Organisation der Daten auf der Disk = fortlaufende Folge von Blöcken
|
||
- sequentielles Lesen und Schreiben
|
||
- Zugriffslücke zwischen Hauptspeicher und Disk durch Caching verbergen (Lokalität von Zugriffen ausnutzen)
|
||
|
||
**Main-Memory-Datenbanken**
|
||
- klassische Annahmen nicht mehr zutreffend:
|
||
- Systeme mit Hauptspeicher im TB-Bereich verfügbar
|
||
- Datenbank kann komplett im Hauptspeicher gehalten werden (muss aber dennoch persistent sein)
|
||
- **Main-Memory-** oder **Hauptspeicher-** Datenbanken: Ausnutzung der großen Hauptspeicher und Multicore-Architekturen
|
||
- Beispiele: SAP HANA, Oracle TimesTen, SQL Server Hekaton, Hyper, MemSQL, ...
|
||
- Besonderheiten: hauptspeicheroptimierte Datenstrukturen (Main-Memory-Scans), Persistenz trotz volatilem Speicher, Datenkompression, Nebenläufigkeitskontrolle
|
||
|
||
|
||
## Klassische 5-Schichtenarchitektur
|
||
**Fünf-Schichtenarchitektur**
|
||
- Architektur für klassische DBMS
|
||
- basierend auf Idee von Senko 1973
|
||
- Weiterentwicklung von Härder 1987
|
||
- Umsetzung im Rahmen des IBM-Prototyps _System R_
|
||
- genauere Beschreibung der Transformationskomponenten
|
||
- schrittweise Transformation von Anfragen/Änderungen bis hin zu Zugriffen auf Speichermedien
|
||
- Definition der Schnittstellen zwischen Komponenten
|
||
|
||
**5-Schichtenarchitektur: Funktionen**
|
||

|
||
|
||
**5-Schichtenarchitektur: Objekte**
|
||

|
||
|
||
Erläuterungen
|
||
- mengenorientierte Schnittstelle **MOS** :
|
||
- deklarative Datenmanipulationssprache auf Tabellen und Sichten (etwa SQL)
|
||
- durch Datensystem auf satzorientierte Schnittstelle **SOS** umgesetzt:
|
||
- navigierender Zugriff auf interner Darstellung der Relationen
|
||
- manipulierte Objekte: typisierte Datensätze und interne Relationen sowie logische Zugriffspfade (Indexe)
|
||
- Aufgaben des Datensystems: Übersetzung und Optimierung von SQL-Anfragen
|
||
- durch Zugriffssystem auf interne Satzschnittstelle **ISS** umgesetzt:
|
||
- interne Tupel einheitlich verwalten, ohne Typisierung
|
||
- Speicherstrukturen der Zugriffspfade (konkrete Operationen auf B+-Bäumen und Hashtabellen), Mehrbenutzerbetrieb mit Transaktionen
|
||
- durch Speichersystem Datenstrukturen und Operationen der ISS auf interne Seiten eines virtuellen linearen Adressraums umsetzen
|
||
- Manipulation des Adressraums durch Operationen der Systempufferschnittstelle **SPS**
|
||
- Typische Objekte: interne Seiten, Seitenadressen
|
||
- Typische Operationen: Freigeben und Bereitstellen von Seiten, Seitenwechselstrategien, Sperrverwaltung, Schreiben des Logs
|
||
- durch Pufferverwaltung interne Seiten auf Blöcke der Dateischnittstelle **DS** abbilden
|
||
- Umsetzung der DS-Operationen auf Geräteschnittstelle erfolgt durch BS
|
||
|
||
## Neue Entwicklungen
|
||
Anforderungen aus neuen Anwendungen
|
||
- Nicht-Standard-Datenmodelle (siehe NoSQL-Systeme)
|
||
- flexibler Umgang mit Datenstrukturen (JSON, Schema on Read, ...)
|
||
- beschränkte (Lookups) vs. erweiterte (z.B. Graphoperationen, Datenanalysen) Anfragefunktionalität
|
||
- Skalierbarkeit zu Big Data (massiv parallele/verteilte Systeme)
|
||
- dynamische Daten / Datenströme
|
||
- ...
|
||
|
||
**Entwicklungen im Hardware-Bereich**
|
||
- Multicore- und Manycore-Prozessoren: 64+ Cores
|
||
- Nutzung erfordert Parallelisierungstechniken und Nebenläufigkeitskontrolle
|
||
- Memory Wall: Hauptspeicherzugriff als Flaschenhals
|
||
- RAM-Zugriff 60 ns, L1-Cache: 4 CPU-Zyklen -> Cache-optimierte Strukturen
|
||
- Datenbank-Accelerators
|
||
- Hardware-unterstütztes Datenmanagement: FPGA, GPU als Coprozessoren, Highspeed-Netzwerk, SSDs als zusätzliche Cache-Ebene, ...
|
||
- Persistenter Memory: nicht-volatiler Speicher
|
||
- Instant Restart / Recovery von Main-Memory-Datenbanken
|
||
|
||
**Zusammenfassung**
|
||
- Datenmanagementfunktionalitäten in vielen Softwaresystemen erforderlich
|
||
- nicht auf Implementierung kompletter DBMS beschränkt, sondern für nahezu alle datenintensiven Systeme: auch in Suchmaschinen, Datenanalyseanwendungen, eingebetteten Systemen, Visualisierungssystemen, Steuerungssystemen, Entwicklungsumgebungen, ...
|
||
- gemeinsame Aufgaben / Komponenten: Datenorganisation und -verwaltung (Indexstrukturen), Transaktionsverwaltung / Nebenläufigkeitskontrolle / Recovery, Anfrageverarbeitung
|
||
- betrifft Datenstrukturen und Algorithmen
|
||
|
||
# Speicherstrukturen für Datenbanken
|
||
## Speicher- und Sicherungsmedien
|
||
Speichermedien
|
||
- verschiedene Zwecke:
|
||
- Daten zur Verarbeitung bereitstellen
|
||
- Daten langfristig speichern (und trotzdem schnell verfügbar halten)
|
||
- Daten sehr langfristig und preiswert archivieren unter Inkaufnahme etwas längerer Zugriffszeiten
|
||
- Speicherhierarchie:
|
||
1. Extrem schneller Prozessor mit Registern
|
||
2. Sehr schneller Cache-Speicher
|
||
3. Schneller Hauptspeicher
|
||
4. Langsamer Sekundärspeicher mit wahlfreiem Zugriff
|
||
5. Sehr langsamer Nearline-Tertiärspeicher bei dem die Speichermedien automatisch bereitgestellt werden
|
||
6. Extrem langsamer Offline-Tertiärspeicher, bei dem die Speichermedien per Hand bereitgestellt werden
|
||
|
||
Zugriffslücke in Zahlen
|
||
- Zugriffslücke: Unterschiede in den Zugriffsgeschwindigkeiten auf den verschiedenen Speicherebenen
|
||
|
||
| Speicherart | Zugriffszeit | CPU cycles | typische Kapazität |
|
||
| ------------------------ | ------------ | ---------- | -------------------------- |
|
||
| CacheSpeicher | 6 ns | 12 | 256 KB (L2) bis 32 MB (L3) |
|
||
| Hauptspeicher | 60 ns | 120 | 1 GB bis 1.5 TB |
|
||
| Zugriffslücke $10^5$ | | |
|
||
| Magnetplattenspeicher | 8-12 ms | 16*10^6 | 160 GB bis 4 TB |
|
||
| Platten-Farm oder -Array | 12 ms | 24*10^6 | im TB- bis PB-Bereich |
|
||
|
||
Typische Merkmale von Sekundärspeicher
|
||
| Merkmal | Kapazität | Latenz | Bandbreite |
|
||
| --------------- | --------- | ------- | -------------------- |
|
||
| 1983 | 30 MB | 48.3 ms | 0.6 MB/s |
|
||
| 1994 | 4.3 GB | 12.7 ms | 9 MB/s |
|
||
| 2003 | 73.4 GB | 5.7 ms | 86 MB/s |
|
||
| 2009 | 2 TB | 5.1 ms | 95 MB/s |
|
||
| 2019 SSD (NVMe) | 2 TB | ?? | seq.read 3.500 MB/s |
|
||
| | | ?? | seq.write 1.600 MB/s |
|
||
|
||
Solid State Disk (SSD)
|
||
- basierend auf EEPROMs in NAND- oder NOR-Technologie
|
||
- Arrays (=Flash-Block mit ca. 128 KB) von Speicherzellen, entweder ein Bit (SLC) oder 2-4 Bit (MLC)
|
||
- MLC sind langsamer und haben verkürzte Lebensdauer
|
||
- initial ist jedes Bit auf 1 gesetzt, durch Reprogrammieren auf 0
|
||
- Löschen zurück auf 1 nur für ganzen Block
|
||
- Konsequenz: langsames Löschen (Lesen = 25 μs, Löschen = 2 ms), begrenzte Lebensdauer (ca. 100.000 Lösch-Schreib-Zyklen)
|
||
- Schnittstelle: SATA oder PCIe (NVMe)
|
||
|
||

|
||
|
||
SSDs in DBMS
|
||
- klassische, auf sequenzielles Lesen ausgerichtete, Strategien von DBMS nutzen die Stärken von Flash-Speicher nicht aus
|
||
- kleinere Blockgrößen lassen sich effizient adressieren, sollten aber ein Vielfaches der Flash-Seiten sein
|
||
- wahlfreie Lesezugriffe sind effizienter als auf Magnetplatten, sollten aber auf Größen von ca. 4 bis 16 MB begrenzt werden
|
||
- konkurrierende IO-Zugriffe sind bis zu einem gewissen Maße ohne negativen Performanzeinfluss durchführbar
|
||
|
||
**Speicherarrays: RAID**
|
||
- Kopplung billiger Standardplatten unter einem speziellen Controller zu einem einzigen logischen Laufwerk
|
||
- Verteilung der Daten auf die verschiedenen physischen Festplatten übernimmt Controller
|
||
- zwei gegensätzliche Ziele:
|
||
- Erhöhung der Fehlertoleranz (Ausfallsicherheit, Zuverlässigkeit) durch Redundanz
|
||
- Effizienzsteigerung durch Parallelität des Zugriffs
|
||
|
||
Erhöhung der Fehlertoleranz
|
||
- Nutzung zusätzlicher Platten zur Speicherung von Duplikaten (Spiegeln) der eigentlichen Daten => bei Fehler: Umschalten auf Spiegelplatte
|
||
- bestimmte RAID-Levels (1, 0+1) erlauben eine solche Spiegelung
|
||
- Alternative: Kontrollinformationen wie Paritätsbits nicht im selben Sektor wie die Originaldaten, sondern auf einer anderen Platte speichern
|
||
- RAID-Levels 2 bis 6 stellen durch Paritätsbits oder Error Correcting Codes (ECC) fehlerhafte Daten wieder her
|
||
- ein Paritätsbit kann einen Plattenfehler entdecken und bei Kenntnis der fehlerhaften Platte korrigieren
|
||
|
||
Erhöhung der Effizienz
|
||
- Datenbank auf mehrere Platten verteilen, die parallel angesteuert werden können => Zugriffszeit auf große Datenmengen verringert sich fast linear mit der Anzahl der verfügbaren Platten
|
||
- Verteilung: bit-, byte- oder blockweise
|
||
- höhere RAID-Levels (ab Level 3) verbinden Fehlerkorrektur und block- oder bitweises Verteilen von Daten
|
||
- Unterschiede:
|
||
- schnellerer Zugriff auf bestimmte Daten
|
||
- höherer Durchsatz für viele parallel anstehende Transaktionen durch eine Lastbalancierung des Gesamtsystems
|
||
|
||
|
||
RAID-Levels
|
||

|
||

|
||
|
||
| Level | Striping blockweise | Striping bitweise | Kopie | Parität | Parität dedizierte Platte | Parität verteilt | Erkennen mehrerer Fehler |
|
||
| ----- | ------------------- | ----------------- | ----- | ------- | ------------------------- | ---------------- | ------------------------ |
|
||
| 0 | √ |
|
||
| 1 | | | √ |
|
||
| 0+1 | √ | | √ |
|
||
| 2 | | √ | | √ |
|
||
| 3 | | √ | | √ | √ |
|
||
| 4 | √ | | | √ | √ |
|
||
| 5 | √ | | | √ | | √ |
|
||
| 6 | √ | | | √ | | | √ |
|
||
|
||
**Sicherungsmedien: Tertiärspeicher**
|
||
- weniger oft benutzte Teile der Datenbank, die eventuell sehr großen Umfang haben (Text, Multimedia) "billiger" speichern als auf Magnetplatten
|
||
- aktuell benutzte Datenbestände zusätzlich sichern (archivieren)
|
||
- Tertiärspeicher: Medium austauschbar
|
||
- offline: Medien manuell wechseln (optische Platten, Bänder)
|
||
- nearline: Medien automatisch wechseln (_Jukeboxes_, _Bandroboter_)
|
||
|
||
Langzeitarchivierung
|
||
- Lebensdauer, Teilaspekte:
|
||
- physische Haltbarkeit des Mediums garantiert die Unversehrtheit der Daten:
|
||
- 10 Jahre für Magnetbänder,
|
||
- 30 Jahre für optische Platten,
|
||
- Papier???
|
||
- Vorhandensein von Geräten und Treibern garantiert die Lesbarkeit von Daten:
|
||
- Geräte für Lochkarten oder 8-Zoll-Disketten?
|
||
- zur Verfügung stehende Metadaten garantieren die Interpretierbarkeit von Daten
|
||
- Vorhandensein von Programmen, die auf den Daten arbeiten können, garantieren die Wiederverwendbarkeit von Daten
|
||
|
||
|
||
## Struktur des Hintergrundspeichers
|
||
Verwaltung des Hintergrundspeichers
|
||
- Abstraktion von Speicherungs- oder Sicherungsmediums
|
||
- Modell: Folge von Blöcken
|
||

|
||
- Alternativen:
|
||
- jede Relation oder jeder Zugriffspfad in genau einer Betriebssystem-Datei
|
||
- ein oder mehrere BS-Dateien, DBS verwaltet Relationen und Zugriffspfade selbst innerhalb dieser Dateien
|
||
- DBS steuert selbst Magnetplatte an und arbeitet mit den Blöcken in ihrer Ursprungsform ( _raw device_ )
|
||
- Warum nicht immer BS-Dateiverwaltung?
|
||
- Betriebssystemunabhängigkeit
|
||
- In 32-Bit-Betriebssystemen: Dateigröße 4 GB maximal
|
||
- BS-Dateien auf maximal einem Medium
|
||
- betriebssystemseitige Pufferverwaltung von Blöcken des Sekundärspeichers im Hauptspeicher genügt nicht den Anforderungen des Datenbanksystems
|
||
|
||
Blöcke und Seiten
|
||
- Zuordnung der physischen Blöcke zu Seiten
|
||
- meist mit festen Faktoren: 1, 2, 4 oder 8 Blöcke einer Spur auf eine Seite
|
||
- hier: "ein Block — eine Seite"
|
||
- höhere Schichten des DBS adressieren über Seitennummer
|
||
|
||
Dienste des Dateisystems
|
||
- Allokation oder Deallokation von Speicherplatz
|
||
- Holen oder Speichern von Seiteninhalten
|
||
- Allokation möglichst so, dass logisch aufeinanderfolgende Datenbereiche (etwa einer Relation) auch möglichst in aufeinanderfolgenden Blöcken der Platte gespeichert werden
|
||
- Nach vielen Update-Operationen: Reorganisationsmethoden
|
||
- Freispeicherverwaltung: doppelt verkettete Liste von Seiten
|
||
|
||
Abbildung der Datenstrukturen
|
||
- Abbildung der konzeptuellen Ebene auf interne Datenstrukturen
|
||
- Unterstützung durch Metadaten (im Data Dictionary, etwa das interne Schema)
|
||
|
||
| Konz. Ebene | Interne Ebene | Dateisystem/Platte |
|
||
| ---------------- | --------------- | ------------------ |
|
||
| Relationen -> | Log. Dateien -> | Phys. Dateien |
|
||
| Tupel -> | Datensätze -> | Seiten/Blöcke |
|
||
| Attributwerte -> | Felder -> | Bytes |
|
||
|
||
- Beispiel: jede Relation in je einer logischen Datei, diese insgesamt in einer einzigen physischen Datei
|
||
|
||
|
||
## Seiten, Sätze und Adressierung
|
||
### Seite
|
||
- Block:
|
||
- kleinste adressierbare Einheit auf Externspeicher
|
||
- Zuordnung zu Seiten im Hauptspeicher
|
||
- Aufbau von Seiten
|
||
- Header
|
||
- Informationen über Vorgänger- und Nachfolger-Seite
|
||
- eventuell auch Nummer der Seite selbst
|
||
- Informationen über Typ der Sätze
|
||
- freier Platz
|
||
- Datensätze
|
||
- unbelegte Bytes
|
||
|
||
Seitenorganisation
|
||
- Organisation der Seiten: doppelt verkettete Liste
|
||
- freie Seiten in Freispeicherverwaltung
|
||

|
||
|
||
Seite: Adressierung der Datensätze
|
||
- adressierbare Einheiten
|
||
- Zylinder
|
||
- Spuren
|
||
- Sektoren
|
||
- Blöcke oder Seiten
|
||
- Datensätze in Blöcken oder Seiten
|
||
- Datenfelder in Datensätzen
|
||
- Beispiel: Adresse eines Satzes durch Seitennummer und Offset (relative Adresse in Bytes vom Seitenanfang)
|
||
|
||
Seitenzugriff als Flaschenhals
|
||
- Maß für die Geschwindigkeit von Datenbankoperationen: Anzahl der Seitenzugriffe auf dem Sekundärspeicher (wegen Zugriffslücke)
|
||
- Faustregel: Geschwindigkeit des Zugriffs ⇐ Qualität des Zugriffspfades ⇐ Anzahl der benötigten Seitenzugriffe
|
||
- Hauptspeicheroperationen nicht beliebig vernachlässigbar
|
||
|
||
|
||
Einpassen von Datensätzen auf Blöcke
|
||
- Datensätze (eventuell variabler Länge) in die aus einer fest vorgegebenen Anzahl von Bytes bestehenden Blöcke einpassen: Blocken
|
||
- Blocken abhängig von variabler oder fester Feldlänge der Datenfelder
|
||
- Datensätze mit variabler Satzlänge: höherer Verwaltungsaufwand beim Lesen und Schreiben, Satzlänge immer wieder neu ermitteln
|
||
- Datensätze mit fester Satzlänge: höherer Speicheraufwand
|
||
|
||
Verschiedene Satztypen
|
||

|
||
|
||
Sätze fester Länge
|
||
- SQL: Datentypen fester und variabler Länge
|
||
- _char(n)_ Zeichenkette der festen Länge _n_
|
||
- _varchar(n)_ Zeichenkette variabler Länge mit der Maximallänge _n_
|
||
- Aufbau der Datensätze, falls alle Datenfelder feste Länge:
|
||
1. Verwaltungsblock mit Typ eines Satzes (wenn unterschiedliche Satztypen auf einer Seite möglich) und Löschbit
|
||
2. Freiraum zur Justierung des Offset
|
||
3. Nutzdaten des Datensatzes
|
||
|
||
Sätze variabler Länge
|
||
- im Verwaltungsblock nötig: Satzlänge _l_, um die Länge des Nutzdaten-Bereichs _d_ zu kennen
|
||

|
||
- Strategie a)
|
||

|
||
- Strategie b)
|
||

|
||
|
||
Speicherung von Sätzen variabler Länge
|
||
- Strategie a): Jedes Datenfeld variabler Länge $A_i$ beginnt mit einem _Längenzeiger $al_i$, der angibt, wie lang das folgende Datenfeld ist
|
||
- Strategie b): Am Beginn des Satzes wird nach dem Satz-Längenzeiger _l_ und der Anzahl der Attribute ein Zeigerfeld $ap_1 ,..., ap_n$ für alle variabel langen Datenfelder eingerichtet
|
||
- Vorteil Strategie b): leichtere Navigation innerhalb des Satzes (auch für Sätze in Seiten => TID)
|
||
|
||
Anwendung variabel langer Datenfelder
|
||
- "Wiederholgruppen": Liste von Werten des gleichen Datentyps
|
||
- Zeichenketten variabler Länge wie _varchar(n)_ sind Wiederholgruppe mit _char_ als Basisdatentyp, mathematisch also die Kleene’sche Hülle $(char)∗$
|
||
- Mengen- oder listenwertige Attributwerte, die im Datensatz selbst denormalisiert gespeichert werden sollen (Speicherung als geschachtelte Relation oder Cluster-Speicherung), bei einer Liste von _integer_ -Werten wäre dies $(integer)∗$
|
||
- Adressfeld für eine Indexdatei, die zu einem Attributwert auf mehrere Datensätze zeigt (Sekundärindex), also $(pointer)∗$
|
||
|
||
Blockungstechniken: Nichtspannsätze
|
||
- jeder Datensatz in maximal einem Block
|
||

|
||
- Standardfall (außer bei BLOBs oder CLOBs)
|
||
|
||
Blockungstechniken: Spannsätze
|
||
- Spannsätze: Datensatz eventuell in mehreren Blöcken
|
||

|
||
|
||
Adressierungstechniken
|
||

|
||
|
||
Adressierung: TID-Konzept
|
||
- Tupel-Identifier (TID) ist Datensatz-Adresse bestehend aus Seitennummer und Offset
|
||
- Offset verweist innerhalb der Seite bei einem Offset-Wert von _i_ auf den _i_ -ten Eintrag in einer Liste von Tupelzeigern (Satzverzeichnis), die am Anfang der Seite stehen
|
||
- Jeder Tupel-Zeiger enthält Offsetwert
|
||
- Verschiebung auf der Seite: sämtliche Verweise von außen bleiben unverändert
|
||
- Verschiebungen auf eine andere Seite: statt altem Datensatz neuer TID-Zeiger
|
||
- diese zweistufige Referenz aus Effizienzgründen nicht wünschenswert: Reorganisation in regelmäßigen Abständen
|
||
|
||
|
||
TID-Konzept: einstufige Referenz
|
||

|
||
|
||
TID-Konzept: zweistufige Referenz
|
||

|
||
|
||
## Alternative Speichermodelle
|
||
- bisher klassisches N-äres Speichermodell (NSM), auch "row store"
|
||
- Vorteile:
|
||
- gesamter Datensatz kann mit einem Seitenzugriff gelesen werden
|
||
- leichte Änderbarkeit einzelner Attributwerte
|
||
- Nachteil:
|
||
- werden nur wenige Attributwerte benötigt, müssen trotzdem immer alle Attributwerte gelesen werden -> unnötiger IO-Aufwand
|
||
- Alternativen: spaltenorientierte Speichermodelle
|
||
- Zerlegung einer _n_ -stelligen Relation in eine Menge von Projektionen (z.B. binäre Relation)
|
||
- Identifikation (und Rekonstruktion) über eine Schlüsselspalte oder Position
|
||
|
||
Spaltenorientierte Datenorganisation
|
||

|
||
|
||
Alternative Speichermodelle: DSM
|
||
- Decomposition Storage Model (DSM) -> column stores
|
||
- alle Werte einer Spalte (Attribut) werden hintereinander gespeichert
|
||
- Adressierung über Position
|
||

|
||
- Kompression einfach möglich (z.B. Run length encoding)
|
||
- effizientere Scanoperationen (Feldoperationen -> bessere Cache-Nutzung)
|
||
- jedoch: Updateoperationen sind komplexer, Lesen aller Spalten aufwendiger
|
||
- Einsatz bei leseoptimierten Datenbanken
|
||
|
||
Ein Full-Table-Scan in NSM
|
||
- Im NSM-Modell stehen alle Tupel einer Tabelle sequenziell hintereinander auf einer Datenbankseite.
|
||

|
||
|
||
Ein "Full-Table-Scan" in DSM
|
||
- Im DSM-Modell stehen alle Werte eines Attributs sequenziell hintereinander auf einer Datenbankseite.
|
||

|
||
- Alle Daten, die für den "l_shipdate Scan" geladen werden sind
|
||
auch dafür relevant.
|
||
|
||
Alternative Speichermodelle: PAX
|
||
- Partition Attributes Across (PAX) als Kompromiss
|
||
- NSM: alle Spalten eines Satzes auf der gleichen Seite
|
||
- DSM: vertikale Partitionierung, Miniseiten für jeweils eine Spalte
|
||

|
||
|
||
## Main-Memory-Strukturen
|
||
Speicherstrukturen für Main-Memory-Datenbanken
|
||
- Vermeidung der seiten-basierten Indirektion (über Seitenadresse, Puffer)
|
||
- Hauptspeicherzugriffe als neuer Bottleneck ("Memory Wall")
|
||
- Cache-freundliche Datenstruktur: Hauptspeicherzugriffe tatsächlich nicht byteweise, sondern in Cachelines (64 Bytes)
|
||
- Speicherlayout: Row Store vs. Column Store - abhängig vom Workload (Reduzierung der Cache Misses)
|
||
- ggf. Partitionierung für Multicore-Systeme
|
||
- Kompression der Daten zur Reduktion des Speicherbedarfs
|
||
- Persistenz weiterhin notwendig, z.B. über Logging
|
||
- Bsp.: In-Memory-Datenstruktur für relationale Column Stores
|
||
- pro Spalte = Feld von Attributwerten
|
||
- Kompression der Attributwerte (siehe Kapitel 8)
|
||
- ggf. Strukturierung in Segmemten (Chunks) für bessere Speicherverwaltung, NUMA-Effekte
|
||
|
||
|
||
## Speicherorganisation in konkreten DBMS
|
||
Oracle: Datenbankstruktur
|
||

|
||
|
||
Oracle: Blöcke
|
||

|
||
|
||
Oracle: Aufbau von Datensätzen
|
||

|
||
- Kettadresse für _Row Chaining_ : Verteilung und Verkettung zu großer Datensätze (> 255 Spalten) über mehrere Blöcke
|
||
- row id = (data object identifier, data file identifier, block identifier, row identifier)
|
||
|
||
Zusammenfassung
|
||
- Speicherhierarchie und Zugriffslücke
|
||
- Speicher- und Sicherungsmedien
|
||
- Hintergrundspeicher: Blockmodell
|
||
- Einpassen von Sätzen in Seiten
|
||
- Satzadressierung: TID-Konzept
|
||
|
||
# Caching und Pufferverwaltung
|
||
## Aufgaben
|
||
Aufgaben der Pufferverwaltung
|
||
- Puffer: ausgezeichneter Bereich des Hauptspeichers
|
||
- in Pufferrahmen gegliedert, jeder Pufferrahmen kann Seite der Platte aufnehmen
|
||
- Aufgaben:
|
||
- Pufferverwaltung muss angeforderte Seiten im Puffer suchen => effizienteSuchverfahren
|
||
- parallele Datenbanktransaktionen: geschickte Speicherzuteilung im Puffer
|
||
- Puffer gefüllt: adäquate Seitenersetzungsstrategien
|
||
- Unterschiede zwischen einem Betriebssystem-Puffer und _einem Datenbank-Puffer_
|
||
- spezielle Anwendung der Pufferverwaltung: Schattenspeicherkonzept
|
||

|
||
|
||
Mangelnde Eignung des BS-Puffers
|
||
- Natürlicher Verbund von Relationen _A_ und _B_ (zugehörige Folge von Seiten: _Ai_ bzw. _Bj_ )
|
||
- Implementierung: _Nested-Loop_
|
||

|
||
- Ablauf
|
||
- FIFO: $A_1$ verdrängt, da älteste Seite im Puffer
|
||
- LRU: $A_1$ verdrängt, da diese Seite nur im ersten Schritt beim Auslesen des ersten Vergleichstupels benötigt wurde
|
||
- Problem
|
||
- im nächsten Schritt wird das zweite Tupel von $A_1$ benötigt
|
||
- weiteres "Aufschaukeln": um $A_1$ laden zu können, muss $B_1$ entfernt werden (im nächsten Schritt benötigt) usw.
|
||
|
||
## Suche von Seiten und Speicherzuteilung
|
||
Suchen einer Seite
|
||
- Direkte Suche:
|
||
- ohne Hilfsmittel linear im Puffer suchen
|
||
- Indirekte Suche:
|
||
- Suche nur noch auf einer kleineren Hilfsstruktur
|
||
- _unsortierte und sortierte Tabelle_ : alle Seiten im Puffer vermerkt
|
||
- _verkettete Liste_ : schnelleres sortiertes Einfügen möglich
|
||
- _Hashtabelle_ : bei geschickt gewählter Hashfunktion günstigster Such- und Änderungsaufwand
|
||
|
||
|
||
Speicherzuteilung im Puffer
|
||
- bei mehreren parallel anstehenden Transaktionen
|
||
- Lokale Strategien: Jeder Transaktion bestimmte disjunkte Pufferteile verfügbar machen (Größe statisch vor Ablauf der Transaktionen oder dynamisch zur Programmlaufzeit entscheiden)
|
||
- Globale Strategien: Zugriffsverhalten aller Transaktionen insgesamt bestimmt Speicherzuteilung (gemeinsam von mehreren Transaktionen referenzierte Seiten können so besser berücksichtigt werden)
|
||
- Seitentypbezogene Strategien: Partition des Puffers: Pufferrahmen für Datenseiten, Zugriffspfadseiten, Data-Dictionary-Seiten, usw. - eigene Ersetzungstrategien für die jeweiligen Teile möglich
|
||
|
||
## Seitenersetzungsstrategien
|
||
- Speichersystem fordert Seite $E_2$ an, die nicht im Puffer vorhanden ist
|
||
- Sämtliche Pufferrahmen sind belegt
|
||
- vor dem Laden von _E_ 2 Pufferrahmen freimachen
|
||
- nach den unten beschriebenen Strategien Seite aussuchen
|
||
- Ist Seite in der Zwischenzeit im Puffer verändert worden, so wird sie nun auf Platte zurückgeschrieben
|
||
- Ist Seite seit Einlagerung in den Puffer nur gelesen worden, so kann sie überschrieben werden (verdrängt)
|
||
|
||

|
||
|
||
Seitenersetzung in DBMS
|
||
- Fixieren von Seiten (Pin oder Fix):
|
||
- Fixieren von Seiten im Puffer verhindert das Verdrängen
|
||
- speziell für Seiten, die in Kürze wieder benötigt werden
|
||
- Freigeben von Seiten (Unpin oder Unfix):
|
||
- Freigeben zum Verdrängen
|
||
- speziell für Seiten, die nicht mehr benötigt werden
|
||
- Zurückschreiben einer Seite:
|
||
- Auslösen des Zurückschreibens für geänderte Seiten bei Transaktionsende
|
||
|
||
Seitenersetzung: Verfahren
|
||
- grundsätzliches Vorgehen beim Laden einer Seite:
|
||
- Demand-paging-Verfahren: genau eine Seite im Puffer durch angeforderte Seite ersetzen
|
||
- Prepaging-Verfahren: neben der angeforderten Seite auch weitere Seiten in den Puffer einlesen, die eventuell in der Zukunft benötigt werden (z.B. bei BLOBs sinnvoll)
|
||
- Ersetzen einer Seite im Puffer:
|
||
- optimale Strategie: Welche Seite hat maximale Distanz zu ihrem nächsten Gebrauch? (nicht realisierbar, zukünftiges Referenzverhalten nicht vorhersehbar) -> Realisierbare Verfahren besitzen keine Kenntnisse über das zukünftige Referenzverhalten
|
||
- Zufallsstrategie: jeder Seite gleiche Wiederbenutzungswahrscheinlichkeit zuordnen
|
||
|
||

|
||
|
||
Fehlseitenrate
|
||
$$F=1-p(\frac{1-F_{kalt}}{p_{DB}}) * 100%$$
|
||
- $p$: Puffergröße
|
||
- $p_{DB}$: Puffergröße, die gesamte Datenbank umfasst
|
||
- $F_{kalt}$: Fehlseitenrate beim Kaltstart (d.h. leerer Puffer) -> Verhältnis von Anzahl der in den Puffer geladenen Seiten zur Anzahl der Referenzierungen
|
||
|
||
- Gute, realisierbare Verfahren sollen vergangenes Referenzverhalten auf Seiten nutzen, um Erwartungswerte für Wiederbenutzung schätzen zu können
|
||
- besser als Zufallsstrategie
|
||
- Annäherung an optimale Strategie
|
||
|
||
|
||
Merkmale gängiger Strategien
|
||
- Alter der Seite im Puffer:
|
||
- Alter einer Seite nach Einlagerung (die globale Strategie (G))
|
||
- Alter einer Seite nach dem letztem Referenzzeitpunkt (die Strategie des jüngsten Verhaltens (J))
|
||
- Alter einer Seite wird nicht berücksichtigt (-)
|
||
- Anzahl der Referenzen auf Seite im Puffer:
|
||
- Anzahl aller Referenzen auf eine Seite (die globale Strategie (G))
|
||
- Anzahl nur der letzten Referenzen auf eine Seite (die Strategie des jüngsten Verhaltens (J))
|
||
- Anzahl der Referenzen wird nicht berücksichtigt (-)
|
||
|
||
|
||
Gängige Strategien
|
||

|
||
|
||
Klassifikation gängiger Strategien
|
||
| Verfahren | Prinzip | Alter | Anzahl |
|
||
| --- | --- | --- |
|
||
FIFO | älteste Seite ersetzt | G |-
|
||
LFU (least fre-quently used) | Seite mit geringster Häufigkeit ersetzen | - | G
|
||
LRU (least recently used) | Seite ersetzen, die am längsten nicht referenziert wurde (System R) | J | J
|
||
DGCLOCK (dyn. generalized clock) | Protokollierung der Ersetzungshäufigkeiten wichtiger Seiten | G | JG
|
||
LRD (least reference density) | Ersetzung der Seite mit geringster Referenzdichte | JG | G
|
||
|
||
Beispiel
|
||
- Folge von Seitenanforderungen #1, #2 ...
|
||
- Puffer der Größe 6
|
||

|
||
- Ablauf mit
|
||
- FIFO ...
|
||
- LFU ...
|
||
|
||
### LRU: Least Recently Used
|
||
- Idee: Seite im Puffer ersetzen, die am längsten nicht mehr referenziert wurde
|
||
- Implementierung:
|
||
- Liste oder Stack von Seiten
|
||
- Puffer-Hit bewegt Seite zur MRU-Position (Most Recently Used)
|
||
- Seite am Ende wird verdrängt
|
||

|
||
- Varianten:
|
||
- durch Interpretation der Pin-Operation: Least Recently Referenced bzw. Least Recently Unfixed
|
||
- durch Berücksichtigung der letzten $k$ Referenzierungen (d.h. auch Häufigkeit): LRU-K
|
||
|
||
LRU: Probleme
|
||
- Lock Contention in Multitasking-Umgebungen
|
||
- Zugriff auf LRU-Liste/Stack und Bewegung der Seite erfordert exklusiven Zugriff auf Datenstruktur
|
||
- aufwendige Operation
|
||
- berücksichtigt nur Alter jedoch nicht Häufigkeit
|
||
- oft gelesene Seiten mit langen Pausen zwischen den Zugriffen werden nicht adäquat berücksichtigt
|
||
- "Zerstörung" des Puffers durch Scan-Operator
|
||
- Seiten werden nur einmalig gelesen, verdrängen jedoch andere (ältere) Seiten
|
||
|
||
|
||
Lock Contention bei der Pufferverwaltung
|
||

|
||
- Sperren = Latches: leichtgewichtige (wenige CPU-Instruktionen) Objekte für kurzzeitige Sperren
|
||
|
||
Approximierende Verfahren
|
||
- Idee:
|
||
- Vereinfachung der benötigten Datenstruktur durch Approximation
|
||
- Effektivität (Trefferrate) vs. Skalierbarkeit (Anzahl der Threads)
|
||
- CLOCK: Approximation der Historie durch Bit-Schieberegister der Länge _k_
|
||
- $k= 0$: FIFO
|
||
- $k\rightarrow\infty$: LRU
|
||
- typisch: $k = 1$
|
||
|
||
### CLOCK
|
||
- Seite mit Benutzt-Bit; bei Referenzierung auf "1" setzen
|
||
- bei Seitenfehler:
|
||
- zyklische Suche
|
||
- Seite mit "0" verdrängen
|
||
- sonst Setzen auf "0"
|
||

|
||
|
||
### GCLOCK
|
||
- Verbesserung: Benutzt-Bit durch Referenzzähler _RC_ ersetzen; Dekrementierung bei Suche
|
||
- weitere Verbesserungen:
|
||
- Initialisierung des Referenzzählers
|
||
- Inkrementierung des Zählers
|
||
- seitentypspezifische Maßnahmen (für Typ _i_ : Seitengewicht $E_i$ bei Erstreferenzierung, $W_i$ bei weiterer Referenzierung)
|
||
- Altern
|
||
- Varianten: Seite _j_ von Typ _i_
|
||
- $GCLOCK(V1): RC_j := E_i ; RC_j := RC_j + W_i$
|
||
- $GCLOCK(V2): RC_j := E_i ; RC_j := W_i$ (speziell für $W_i\geq E_i$)
|
||
|
||
### DGCLOCK
|
||
- weitere Verbesserung: globaler Zähler $GC$ und Normierung der aktuellen Referenzzähler $RC$
|
||
1. Initialisierung: $RC_j := GC$
|
||
2. Referenzierung von Seite $j : GC := GC + 1 ; RC_j := RC_j + GC$
|
||
3. bei Überschreiten $GC > MIN : \forall j : RC_j := RC_j / C$
|
||
|
||
### ARC
|
||
- Adaptive Replacement Cache: neues Verfahren, das Nachteile von LRU vermeidet
|
||
- Prinzip:
|
||
- Puffergröße _c_
|
||
- Pufferverzeichnis für 2 _c_ Seiten: _c_ Pufferseiten + _c_ History-Seiten
|
||
- Liste _L_ 1 : "recency" = kurzfristiger Nutzen-> Seiten, die kürzlich einmal gelesen wurden
|
||
- Liste _L_ 2 : "frequency" = langfristiger Nutzen -> Seiten, die kürzlich mehrmals gelesen wurden
|
||
- Ausgangspunkt: einfache Verdrängungsstrategie DBL(2 _c_ )
|
||
- Ersetze die LRU-Seite in $L_1$, wenn $|L_1| = c$ , sonst ersetze LRU-Seite in $L_2$
|
||
- Ziel: Größenausgleich zwischen $L_1$ und $L_2$
|
||
- Zugriff Seite $p$: wenn Treffer -> $p$ wird MRU in $L_2$ , sonst in $L_1$
|
||
|
||
Von DBL(2c) zu ARC
|
||

|
||
- Parameter $p$ mit $0\leq p \leq c$
|
||
- $T_1$ enthält $p$ Seiten, $T_2$ enthält $c-p$ Seiten
|
||
- Wahl von $p$?
|
||
|
||
ARC: Algorithmus
|
||
- Seitenanforderungen: $x_1,x_2 ,..., x_t ,...$
|
||
- $p = 0, T_1 , B_1 , T_2 ,B_2$ sind initial leer
|
||
- Fall 1: $x_t \in T_1 \cup T_2$ /* Puffer-Hit */
|
||
- Bewege $x_t$ zu MRU von $T_2$
|
||
- Fall 2: $x_t \in B_1$
|
||
- Anpassung: $p = min\{ p +\delta_1,c\}$ mit $\delta_1 = \begin{cases} 1\quad\text{ wenn } |B_1|\geq |B_2| \\ \frac{|B_2|}{|B_1|} \quad\text{ sonst}\end{cases}$
|
||
- $REPLACE(x_t,p)$
|
||
- Bewege $x_t$ von $B_1$ zu MRU von $T_2$
|
||
- Fall 3: $x_t \in B_2$
|
||
- Anpassung: $p = max\{ p - \delta_2, 0 \}$ mit $\delta_2 = \begin{cases} 1\quad\text{ wenn } |B_2|\geq |B_1| \\ \frac{|B_1|}{|B_2|} \quad\text{ sonst}\end{cases}$
|
||
- $REPLACE(x_t,p)$
|
||
- Bewege $x_t$ von $B_2$ zu MRU von $T_2$
|
||
- Fall 4: $x_t \not\in T_1 \cup B_1 \cup T_2 \cup B_2$
|
||
- 4.A: $|L_1| = c$
|
||
- Wenn $|T_1|<c$, lösche LRU in $B_1$, $REPLACE(x_t,p)$
|
||
- sonst /* $B_1 = \varnothing$ */ lösche LRU in $T_1$
|
||
- 4.B: $|L_1|<c$
|
||
- Wenn $|L_1|+|L_2|\geq c$ , lösche LRU in $B_2$, $REPLACE(x_t,p)$
|
||
- Bewege $x_t$ zu MRU in $T_1$
|
||
|
||
ARC: $REPLACE(x_t, p)$
|
||
|
||
if $|T_1|>p$ oder ($x_t\in B_2$ und $|T_1|=p$)
|
||
Lösche LRU-Seite in $T_1$ und bewege sie zu MRU in $B_1$
|
||
else
|
||
Lösche LRU-Seite in $T_2$ und bewege sie zu MRU in $B_2$
|
||
endif
|
||
|
||
ARC: Beispiel
|
||
1. erstmalige Anforderung der Seiten $#1$ und $#2$: Aufnahme in
|
||

|
||
2. nächsten Referenzierung von $#1$: Übernahme in $T_2$-Liste
|
||

|
||
3. Seitenanforderungen $#3$, $#4$, $#1$; mit $#2$ wird diese in $T_2$ bewegt; Platz für Seite $#5$:
|
||

|
||
4. Beantwortung der Seitenanforderungen $#1$ und $#2$ aus $T_2$
|
||
5. neu angeforderten Seiten $#5$ und $#6$ in $T_1$
|
||

|
||
6. Seitenanforderung $#7$: Verdrängen von $#4$ aus $T_1$ in $B_1$
|
||

|
||
|
||
ARC: Eigenschaften
|
||
- kontinuierliche Anpassung von Parameter $p$
|
||
- Lernraten $\delta_1$ und $\delta_2$
|
||
- "Investieren in Liste mit dem meisten Profit"
|
||
- Berücksichtigung von Alter und Häufigkeit
|
||
- durch zwei Listen $L_1$ und $L_2$
|
||
- Scan-Resistenz
|
||
- einmalig gelesene Seiten nur in $L_1$, niemals in $L_2$
|
||
- Vermeidung von Lock Contention durch approximierende Varianten (CAR, CART, ...)
|
||
|
||
## Fazit
|
||
- Pufferverwaltungsstrategie mit großem Einfluss auf Performance
|
||
- in kommerziellen Systemen meist LRU mit Variationen
|
||
- besondere Behandlung von Full-Table-Scans
|
||
- weiterer Einflussfaktor: Puffergröße
|
||
- Indikator: Trefferrate (engl. _hit ratio_ )
|
||
$$hit\_ratio = \frac{\text{Anz. log. Zugriffe} - \text{Anz. phys. Zugriffe}}{\text{Anz. log. Zugriffe}}$$
|
||
- 5-Minuten-Regel (Gray, Putzolu 1997):
|
||
Daten, die in den nächsten 5 Min. wieder referenziert werden, sollten im Hauptspeicher gehalten werden
|
||
|
||
# Indexierung von Daten
|
||
## Klassifikation der Speichertechniken
|
||
Einordnung in 5-Schichten-Architektur
|
||
- **Speichersystem** fordert über Systempufferschnittstelle Seiten an
|
||
- interpretiert diese als interne Datensätze
|
||
- interne Realisierung der logischen Datensätze mit Hilfe von Zeigern, speziellen Indexeinträgen und weiteren Hilfsstrukturen
|
||
- Zugriffssystem abstrahiert von der konkreten Realisierung
|
||
|
||
Klassifikation der Speichertechniken
|
||
- Kriterien für Zugriffsstrukturen oder Zugriffsverfahren:
|
||
- organisiert interne Relation selbst (Dateiorganisationsform) oder zusätzliche Zugriffsmöglichkeit auf bestehende interne Relation (Zugriffspfad)
|
||
- Art der Zuordnung von gegebenen Attributwerten zu Datensatz-Adressen: Schlüsselvergleich = Zuordnung von Schlüsselwert zu Adresse über Hilfsstruktur; Schlüsseltransformation = Berechnung der Adresse aus Schlüsselwert (z.B. über Hashfunktion)
|
||
- Arten von Anfragen, die durch Dateiorganisationsformen und Zugriffspfade effizient unterstützt werden können
|
||

|
||
|
||
Dünn- vs. dichtbesetzter Index
|
||
- dünnbesetzter Index: nicht für jeden Zugriffsattributwert _K_ ein Eintrag in Indexdatei sondern z.B. nur für _Seitenanführer_ einer sortierten Relation
|
||
- dichtbesetzter Index: für jeden Datensatz der internen Relation ein Eintrag in Indexdatei
|
||
|
||
Geclusterter vs. nicht-geclusterter Index
|
||
- geclusterter Index: in der gleichen Form sortiert wie interne Relation
|
||
- nicht-geclusterter Index: anders organisiert als interne Relation
|
||
- Primärindex oft dünnbesetzt und geclustert
|
||
- jeder dünnbesetzte Index ist auch geclusterter Index, aber nicht umgekehrt
|
||
- Sekundärindex kann nur dichtbesetzter, nicht-geclusterter Index sein (auch: invertierte Datei)
|
||

|
||
|
||
Statische vs. dynamische Struktur
|
||
- statische Zugriffsstruktur: optimal nur bei bestimmter (fester) Anzahl von verwaltenden Datensätzen
|
||
- dynamische Zugriffsstruktur: unabhängig von der Anzahl der Datensätze optimal
|
||
- dynamische Adresstransformationsverfahren verändern dynamisch Bildbereich der Transformation
|
||
- dynamische Indexverfahren verändern dynamisch Anzahl der Indexstufen => in DBS üblich
|
||
|
||
Klassifikation
|
||

|
||
|
||
|
||
## Statische Verfahren
|
||
- Heap, indexsequenziell, indiziert-nichtsequenziell
|
||
- oft grundlegende Speichertechnik in RDBS
|
||
- direkte Organisationsformen: keine Hilfsstruktur, keine Adressberechnung (Heap, sequenziell)
|
||
- statische Indexverfahren für Primärindex und Sekundärindex
|
||
|
||
|
||
Statische Verfahren: Überblick
|
||

|
||
|
||
### Heap
|
||
Organisation
|
||
- völlig unsortiert speichern
|
||
- physische Reihenfolge der Datensätze ist zeitliche Reihenfolge der Aufnahme von Datensätzen
|
||
| | | | |
|
||
| --- | --- | --- | --- | ---
|
||
8832 | Max | Mustermann | ... | 9.1.2003
|
||
5588 | Beta | Alpha | ... | 7.3.1978
|
||
4711 | Gamma | Delta | ... | 2.5.1945
|
||
|
||
Operationen
|
||
- insert: Zugriff auf letzte Seite der Datei. Genügend freier Platz => Satz anhängen. Sonst nächste freie Seite holen
|
||
- delete: lookup, dann Löschbit auf 0 gesetzt
|
||
- lookup: sequenzielles Durchsuchen der Gesamtdatei, maximaler Aufwand (Heap-Datei meist zusammen mit Sekundärindex eingesetzt; oder für sehr kleine Relationen)
|
||
- Komplexitäten:
|
||
- Neuaufnahme von Daten $O(1)$
|
||
- Suchen $O(n)$
|
||
|
||
### Sequenzielle Speicherung
|
||
- sortiertes Speichern der Datensätze
|
||
| | | | |
|
||
| --- | --- | --- | --- | ---
|
||
4711 | Gamma | Delta | ... | 2.5.1945
|
||
5588 | Beta | Alpha | ... | 7.3.1978
|
||
8832 | Max | Mustermann | ... | 9.1.2003
|
||
|
||
Sequenzielle Datei: Operationen
|
||
- insert: Seite suchen, Datensatz einsortieren => beim Anlegen oder sequenziellen Füllen einer Datei jede Seite nur bis zu gewissem Grad (etwa 66%) füllen
|
||
- delete: Aufwand bleibt
|
||
- Folgende Dateiorganisationsformen:
|
||
- schnelleres lookup
|
||
- mehr Platzbedarf (durch Hilfsstrukturen wie Indexdateien)
|
||
- mehr Zeitbedarf bei insert und delete
|
||
- klassische Indexform: indexsequenzielle Dateiorganisation
|
||
|
||
## Indexsequenzielle Dateiorganisation
|
||
- Kombination von sequenzieller Hauptdatei und Indexdatei: indexsequenzielle Dateiorganisationsform
|
||
- Indexdatei kann geclusterter, dünnbesetzter Index sein
|
||
- mindestens zweistufiger Baum
|
||
- Blattebene ist Hauptdatei (Datensätze)
|
||
- jede andere Stufe ist Indexdatei
|
||

|
||
|
||
Aufbau der Indexdatei
|
||
- Datensätze in Indexdatei: _(Primärschlüsselwert, Seitennummer)_ zu jeder Seite der Hauptdatei genau ein Index-Datensatz in Indexdatei
|
||
- Problem: "Wurzel" des Baumes bei einem einstufigen Index nicht nur eine Seite
|
||

|
||
|
||
|
||
Mehrstufiger Index
|
||
- Optional: Indexdatei wieder indexsequenziell verwalten
|
||
- Idealerweise: Index höchster Stufe nur noch eine Seite
|
||

|
||
|
||
lookup bei indexsequenziellen Dateien
|
||
- lookup-Operation sucht Datensatz zum Zugriffsattributwert _w_
|
||
- Indexdatei sequenziell durchlaufen, dabei $(v_1,s)$ im Index gesucht mit $v_1\leq w$:
|
||
- $(v_1,s)$ ist letzter Satz der Indexdatei, dann kann Datensatz zu _w_ höchstens auf dieser Seite gespeichert sein (wenn er existiert)
|
||
- nächster Satz $(v_2,s′)$ im Index hat $v_2 > w$ , also muss Datensatz zu _w_, wenn vorhanden, auf Seite _s_ gespeichert sein
|
||
- $(v_1,s)$ überdeckt Zugriffsattributwert _w_
|
||
|
||
insert bei indexsequenziellen Dateien
|
||
- insert: zunächst mit lookup Seite finden
|
||
- Falls Platz, Satz sortiert in gefundener Seite speichern; Index anpassen, falls neuer Satz der erste Satz in der Seite
|
||
- Falls kein Platz, neue Seite von Freispeicherverwaltung holen; Sätze der "zu vollen" Seite gleichmäßig auf alte und neue Seite verteilen; für neue Seite Indexeintrag anlegen
|
||
- Alternativ neuen Datensatz auf Überlaufseite zur gefundenen Seite
|
||
|
||
delete bei indexsequenziellen Dateien
|
||
- delete: zunächst mit lookup Seite finden
|
||
- Satz auf Seite löschen (Löschbit auf 0)
|
||
- erster Satz auf Seite: Index anpassen
|
||
- Falls Seite nach Löschen leer: Index anpassen, Seite an Freispeicherverwaltung zurück
|
||
|
||
Probleme indexsequenzieller Dateien
|
||
- stark wachsende Dateien: Zahl der linear verketteten Indexseiten wächst; automatische Anpassung der Stufenanzahl nicht vorgesehen
|
||
- stark schrumpfende Dateien: nur zögernde Verringerung der Index- und Hauptdatei-Seiten
|
||
- unausgeglichene Seiten in der Hauptdatei (unnötig hoher Speicherplatzbedarf, zu lange Zugriffszeit)
|
||
|
||
|
||
Indiziert-nichtsequenzieller Zugriffspfad
|
||
- zur Unterstützung von Sekundärschlüsseln
|
||
- mehrere Zugriffpfade dieser Form pro Datei möglich
|
||
- einstufig oder mehrstufig: höhere Indexstufen wieder indexsequenziell organisiert
|
||
|
||
Aufbau der Indexdatei
|
||
- Sekundärindex, dichtbesetzter und nicht-geclusteter Index
|
||
- zu jedem Satz der Hauptdatei Satz $(w,s)$ in der Indexdatei
|
||
- _w_ Sekundärschlüsselwert, _s_ zugeordnete Seite
|
||
- entweder für ein _w_ mehrere Sätze in die Indexdatei aufnehmen
|
||
- oder für ein _w_ Liste von Adresse in der Hauptdatei angeben
|
||

|
||
|
||
Operationen
|
||
- lookup: _w_ kann mehrfach auftreten, Überdeckungstechnik nicht benötigt
|
||
- insert: Anpassen der Indexdateien
|
||
- delete: Indexeintrag entfernen
|
||
|
||
Probleme statischer Verfahren
|
||
- unzureichende Anpassung an wachsende/schrumpfende Datenmengen
|
||
- schlechte Ausnutzung von Speicher nach Seitensplits
|
||
- Bevorzugung bestimmter Attribute (Schlüssel)
|
||
- daher in den folgenden Kapiteln:
|
||
- bessere Datenstrukturen zur Schlüsselsuche als zusätzlicher Zugriffspfad = Approximation einer Funktion Schlüssel -> Speicheradresse, z.B. über Baumverfahren
|
||
- Erweiterung von Hashverfahren um Anpassung des Bildbereichs = dynamische Hashverfahren
|
||
- Behandlung von zusammengesetzten Schlüsseln = multidimensionale Zugriffsverfahren, z.B. multidimensionale Bäume oder raumfüllende Kurven
|
||
|
||
# Baumbasierte Indexstrukturen |