Zwar sind die Zeiten, in denen ich mich mit Microsofts BI-Landschaft intensiver beschäftigt habe, schon lange vorbei, aber sollte ich jemals wieder damit anfangen, dann wäre das DAX Studio sicher ein Werkzeug, das zu berücksichtigen wäre. Vincent Rainardi verweist in seinem zugehörigen Artikel auch auf eine nützliche Liste weiterer BI Tools, die unter https://www.sqlbi.com/tools/ gepflegt wird. Ich erinnere mich noch gut daran, wie ich nach der Abwanderung von Mosha Pasumansky auf eine Weiterentwicklung des ungeheuer nützlichen MDX Studios hoffte, aber leider ist daraus offenbar nie etwas geworden.
Montag, November 05, 2018
Mittwoch, Oktober 31, 2018
Indizierung von Foreign Keys in Oracle und Postgres
Dass nicht indizierte Foreign Keys in Oracle massive Locking-Probleme hervorrufen können, habe ich vermutlich zum ersten Mal vor mehr als 15 Jahren bei Tom Kyte gelesen (ohne dass ich dazu gerade eine passende Textstelle liefern könnte). Franck Pachot hat jetzt darüber geschrieben, wie das Verhalten unter entsprechenden Bedingungen in Postgres aussieht - eine Frage, die eigentlich auf der Hand liegt, der nachzugehen mir bisher aber noch nicht in den Sinn gekommen war. Das Ergebnis lautet: bei Postgres ist die Indizierung der Foreign Keys nicht zur Vermeidung von Locks erforderlich, sondern nur zur Optimierung der Navigation von Parent zu Child. Grundlage dieses Verhaltens ist die Verfügbarkeit von "shared row locks" in Postgres (die es in Oracle nicht gibt). Die Details der Erklärung erzähle ich hier nicht nach - mir genügt die Erinnerung, dass beide RDBMS sich in diesem Punkt unterschiedlich verhalten.
Montag, Oktober 08, 2018
Transport von SQL Patches
Marco Mischke erläutert in seinem Blog, dass "SQL Patches" bei einer Migration mit Hilfe von "data pump" nicht transportiert werden, da sie nicht zum Schema der Applikation gehören. Das Package DBMS_SQLDIAG enthält aber Prozeduren, mit deren Hilfe man die Patches in einer Tabelle ablegen kann, die sich dann ihrerseits mit "data pump" transportieren lässt. Das ist also kein besonderes Hindernis, aber ein Punkt, den man im Rahmen einer Migration im Auge behalten muss.
Donnerstag, Oktober 04, 2018
Performance von lokalen und globalen Indizes partitionierter Tabellen
Richard Foote hat eine neue Artikel-Serie gestartet, in der er sich mit der Performance lokaler und globaler Indizes für partitionierte Tabellen beschäftigt. Da ich auch zu den Leute gehöre, die globale Indizes weitgehend vermeiden, finde ich Argumente, die für die globalen Indizes sprechen, grundsätzlich interessant:
- “Hidden” Efficiencies of Non-Partitioned Indexes on Partitioned Tables Part I (The Jean Genie): liefert ein sehr einfaches initiales Beispiel: eine Tabelle enthält Daten für acht Jahre und einen Index für die Spalte TOTAL_SALES, die für den Wert 42 insgesamt 10 Datensätze liefert. Bei Verwendung einer nicht partitionierten Tabelle erfordert ein Zugriff auf diese 10 Datensätze 14 consistent gets (4 für den Durchgang durch die Indexstruktur und 10 für die Datensätze) - und die gleichen 14 LIOs sind auch erforderlich, wenn man nur einen Datensatz für ein bestimmtes Jahr auswählt, da die Datumsangabe nicht Teil des Index ist und daher erst bei der Filterung berücksichtigt wird. Für den globalen Index auf einer partitionierten Tabelle ergeben sich die gleichen 14 LIOs für Fall 1, aber für den zweiten Fall sinkt die Zahl der LIOs auf 5, da hier für den Optimizer klar ist, dass nur die Partition des fraglichen Jahres den gewünschten Datensatz enthalten kann - es erfolgt also ein "partition pruning".
- “Hidden” Efficiencies of Non-Partitioned Indexes on Partitioned Tables Part II (Aladdin Sane): bis zu Oracle 8 bestand die rowid grundsätzlich aus 6 byte und enthielt "file number", "block number" und "row number". Seit der Einführung des Partitioning in Oracle 8 kann ein partitioniertes Objekt in mehreren Tablespaces abgelegt werden, was dazu führte, dass die "file number" nicht mehr eindeutig war. Daher wurde die rowid für globale Indizes um die "data object id" erweitert (und damit auf 10 byte erweitert). Diese zusätzliche Information macht das "partition pruning" möglich, da der Index in jedem einzelnen Schlüssel die dafür erforderliche Information enthält.
- “Hidden” Efficiencies of Non-Partitioned Indexes on Partitioned Tables Part III” (Ricochet): weist darauf hin, dass ein lokaler Index durch die kürzere rowid (ohne die "data object id" und daher nur 6 byte lang) etwas kleiner ist als ein entsprechender globaler Index. Für einen Zugriff, der sich auf eine Partition beschränkt, ist der lokale Index daher etwas effizienter als der globale Index (4 vs. 5 LIOs). Beim Partitions-übergreifenden Zugriff ist der globale Index dagegen deutlich effizienter, da sich das Lesen auf eine Index-Struktur beschränkt und nicht über mehrere interne Indizes erfolgen muss.
- “Hidden” Efficiencies of Non-Partitioned Indexes on Partitioned Tables Part IV” (Hallo Spaceboy) : zeigt, dass man das BLEVEL eines globalen Index dadurch reduzieren kann, dass man ihn partitioniert (nach einer anderen Spalte als dem partition key).
Wie üblich gilt, dass ich die folgenden Artikel ergänzen werde, wenn ich nicht die Lust daran verliere.
Montag, Oktober 01, 2018
Overhead für Extended Trace im SQL Server
Da ich ein großer Freund des Tracings von Datenbank-Operationen bin, finde ich Untersuchungen wie die von Nenad Noveljic zum Thema "SQL Server Extended Events Trace Overhead" sehr interessant. Im Artikel wird ein Testszenario vorgestellt, das eine relativ zweckfreie Schleife zunächst ohne und dann mit dem Event "sql_batch_completed" gegenüberstellt. Für diese stark CPU-hungrige Operation ergibt sich eine Verlangsamung um ca. 15% nach der Aktivierung des Events: die Laufzeit steigt von 61 auf 74 Sekunden - wobei die Erhöhung auf CPU-Last zurückzuführen ist, die nicht in den Event-Statistiken enthalten ist (sondern in sys.dm_exec_requests.cpu_time). Andere Events - wie etwa logout - haben nahezu keine Auswirkungen auf die Performance. Ein entsprechender Test mit Oracle und einem 10046er Trace zeigt keine entsprechende Wirkung - wobei allerdings anzumerken wäre, dass dort ein Trace mit rowsource statistics unter Umständen recht massive negative Effekte hervorrufen kann, wie Jonathan Lewis gerade mal wieder in Erinnerung gerufen hat.
Dienstag, September 18, 2018
ORA-01723 für DATE-Angaben
Nach langer Zeit mal wieder etwas Selbsterlebtes, das einen Eintrag zu verdienen scheint - wie man eine CTAS-Operation über das nls_date_format torpedieren kann:
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> create table t as select to_date(null) col1 from dual;
create table t as select to_date(null) col1 from dual
*
ERROR at line 1:
ORA-01723: zero-length columns are not allowed
SQL> alter session set nls_date_format = 'DD-MON-RR';
SQL> create table t as select to_date(null) col1 from dual;
Table created.
Somit wird die Tabelle T mit dem einen nls_date_format problemlos angelegt, während das andere Format einen Fehler "ORA-01723: zero-length columns are not allowed" hervorruft. Ist das ein Problem? Vermutlich nicht: sinnvoller wäre hier ohnehin der Einsatz eines CAST-Aufrufs, denn die folgende Variante funktioniert in beiden Fällen:
SQL> create table t as select cast(null as date) col1 from dual;
Montag, September 10, 2018
Detailinformationen zu dbms_stats in 12c
Jonathan Lewis schreibt in seinem jüngsten Blog-Artikel über einige nützliche Funktionen, die zu dbms_stats in 12c ergänzt wurden:
- report_stats_operations: liefert Basisinformationen zu den Erfassungsläufen der letzten n Tage, etwa die Start- und End-Zeit und die Anzahl erfolgreicher und fehlgeschlagener Tasks. Leider ist eine Filterung der Angaben nicht über Parameter möglich, sondern muss durch einen Pl/SQL Wrapper erledigt werden.
- report_single_stats_operation: liefert Details zu einem der von der ersten Funktion gelieferten Tasks. Über das detail_level ALL Kann man dann auch die Ursache für eine fehlschlagende Erfassung finden.
So nützlich diese Informationen sind, würde ich mir doch eher entsprechende Dictionary Views wünschen, da die Funktionsausgaben keine weitere Bearbeitung erlauben - etwa, um die Laufzeit einer Operation aus Start- und Endzeit zu ermitteln. Aber ein nützliches Hilfsmittel sind die Funktionen in jedem Fall.
Dienstag, August 21, 2018
Postgres: pg_dump blockiert DDL-Kommandos
Daniel Westermann untersucht im DBI Blog das Verhalten von DDL-Operationen im Rahmen von pg_dump. Dabei zitiert er die Postgres-Dokumentation, in der zu lesen ist:
pg_dump is a utility for backing up a PostgreSQL database. It makes consistent backups even if the database is being used concurrently. pg_dump does not block other users accessing the database (readers or writers).
Den Ergebnissen der Untersuchung nach ist das aber nicht uneingeschränkt zutreffend: während DML tatsächlich problemlos ablaufen kann, werden DDL-Kommandos offenbar während der Dump-Erstellung blockiert. Laut source code verwendet pg_dump das isolation level "repeatable read" und setzt ein AccessShareLock während der Sicherung. Dieses erlaubt Datenänderungen und auch die Ergänzung on Objekten (etwa Indizes), nicht aber die strukturelle Änderung bereits bestehender Objekte (create index, drop table, truncate table): diese Operationen bleiben bis zum Abschluss der Dump-Erstellung blockiert. Insofern ist die Dump-Erstellung zu Zeitpunkten, in denen keine DDL-Operationen zu erwarten sind, sicher eine sinnvolle Herangehensweise.
Abonnieren
Posts (Atom)