Zurück zu Dbs2.
Diese Übung umfasst zwei Teile: Der erste Teil befasst sich mit Indexstrukturen (Aufwand: ca. 1h) und ist eher theoretischer Natur, der zweite Teil ist eine praktische Übung zu Query optimization (Aufwand: ca. 1.5h).
Vergleichen Sie B-Tree, Bitmap und Hash Table Indices anhand der folgenden drei Kriterien:
Ein B-Baum mit Grad k hat folgende Eigenschaften:
Fügen Sie in einen anfänglich leeren B-Baum mit k = 2 die Zahlen eins bis zwanzig in aufsteigender Reihenfolge ein. Wie sieht es mit der Auslastung des B-Trees aus?
Gegeben ist die folgende Tabelle Person. Wie würde ein Bitmap Index für die Spalte titel aussehen?
| person_id | name | titel |
| 1 | Alf A. Romeo | Prof. |
| 2 | Alma Nach | Dr. |
| 3 | Axel Haar | Dr. |
| 4 | Dennis Platz | Dr. habil. |
| 5 | Egon Zentrisch | Prof. |
| 6 | Heinz Fiction | Prof. |
| 7 | Jim Beam | Prof. |
| 8 | Klaus Uhr | Prof. |
| 9 | Sam Sonight | Dr. |
| 10 | Theo Dorant | Prof. |
Optimierung ist ein wichtiger Teil beim Datenbank Performance-Tuning. In dieser Übung geht es darum, nachvollziehen zu können, wie PostgreSQL intern eine Query ausführt, welche Faktoren dabei eine Rolle spielen und welche Optimierungsmassnahmen daraus abgeleitet werden können.
PostgreSQL hält alle Kataloginformationen in Tabellen. Für diese Übung sind Folgende von besonderer Relevanz: pg_stats, pg_class, pg_indexes und pg_attribute. Diese können wie normale Tabellen abgefragt werden. Als Beispiel dient folgende Query:
SELECT * FROM pg_indexes WHERE tablename = 'orders'
Diese gibt uns alle Informationen über definierte Indizes in der Tabelle orders. Statistiken, die der Optimizer für Tabellen hält, können mit der folgenden Query abgefragt werden:
SELECT * FROM pg_stats where tablename = 'orders'
Die Beschreibung dieser Zahlen finden Sie hier. Allgemeine Informationen zu einer Tabelle kann man entweder über eine Query auf pg_class oder über das \d Kommando in psql in Erfahrung bringen.
Für diese Übung benötigen wir ein Datenset von entsprechender Grösse. Wir verwenden dazu die DVD-Beispieldatenbank "Dell Store2".
Variante Windows: $ createdb -U postgres dellstore2 $ psql -U postgres -f dellstore2-normal-1.0.sql -d dellstore2 Variante Linux: $ createdb -U postgres dellstore2 $ createlang -U postgres plpgsql dellstore2 $ psql -U postgres -f dellstore2-normal-1.0.sql -d dellstore2
$ psql -U postgres -d dellstore2 -c "VACUUM VERBOSE ANALYZE"
$ psql -U postgres -d dellstore2
dellstore2=# \timing dellstore2=# SELECT count(*) FROM customers;
$ pg_ctl stop $ sudo su - # sync # echo 3 > /proc/sys/vm/drop_caches # logout $ pg_ctl start -l $PGLOG
dellstore2=> select pg_size_pretty(CAST(pg_relation_size('customers') / 7.994 * 1000 as int8)) AS bytes_per_second;
(disk_pages_read * seq_page_cost) + (rows_scanned * cpu_tuple_cost)
wobei seq_page_cost standardmässig 1.0 und cpu_tuple_cost 0.01 ist. Hinweis: disk_pages_read und rows_scanned finden Sie über die Tabelle pg_class heraus.
EXPLAIN ANALYZE SELECT COUNT(*) FROM customers WHERE age < 50;
Wie Sie sehen, wird der Suchbereich ca. um die Hälfe eingegrenzt durch die WHERE Bedingung. Wieso sind die Kosten nicht dementsprechend gesunken?
SELECT customerid, username FROM customers WHERE customerid < 10000 AND username < 'user100';
Können Sie sich vorstellen, wieso der Query Optimizer sich entschieden hat einen komplexen Query Plan mit zwei Indizes zu verwenden anstatt einfach nach username zu suchen was zum gleichen Resultat geführt hätte?
EXPLAIN ANALYZE SELECT * FROM orders, orderlines WHERE orders.totalamount = 329.78 AND orders.orderid = orderlines.orderid;