Mittwoch, März 13, 2013

XML DB Einführung

Eine schöne Einführung zum Thema XML DB gibt Ulrike Schwinn im aktuellen DBA Community Tipp Oracle XML DB für DBAs. Besonders interessant fand ich darin die Erläuterungen zu den Native Oracle XML DB Web Services, mit deren Hilfe man seit 11.1 mit minimalem Konfigurationsaufwand eine web service Schnittstelle verfügbar machen kann, über die z.B. PL/SQL-Prozeduren via HTTP aufgerufen werden können und ein XML-Ergebnis liefern (authentication vorausgesetzt). Eine noch detailliertere Anleitung mit allen erforderlichen Schritten findet man einmal mehr bei Tim Hall.

Dienstag, März 12, 2013

Data Warehousing mit Oracle

Dieser Tage ist es mir endlich gelungen, das Buch Data Warehousing mit Oracle von Claus Jordan, Dani Schnider, Joachim Wehner und Peter Welker fertig zu lesen. Dass die Lektüre relativ lange dauerte, ist insofern erstaunlich, als der Band mit 227 Seiten recht überschaubar ist - und es sich um ein sehr gutes Buch handelt; die Dauer der Leseoperation erklärt sich aus Wait Events, die mit dem Buch nichts zu tun hatten ...

Aber der Reihe nach: Data Warehousing mit Oracle ist 2011 im ehrwürdigen Hanser Verlag erschienen und bereits auf dem Umschlag geben die Autoren ihre Zugehörigkeit zum renommierten Beratungshaus trivadis zu erkennen und werden im Vorwort als DWH-Berater mit langjähriger Projekterfahrung ausgewiesen - und zumindest im Fall des Herrn Schnider kann ich mich an diverse interessante Blog-Artikel erinnern, die ich gelegentlich auch schon mal hier erwähnt habe. Der Band ist - wie erwähnt - recht schmal, dabei aber sehr klar gegliedert: einem Einleitungskapitel folgen Erläuterungen zu folgenden Themen:
  • Data Warehouse Grundlagen: liefert zahlreiche Definitionen und erklärt die theoretischen Grundlagen des Themas (mit kurzem Verweis auf die Positionen von Inmon und Kimball). Neben eher allgemeinen  Definitionen der relevanten Terminologie erscheinen vor allem präzise Vorschläge zu Konventionen und Vorgehensweisen - angefangen bei den Bezeichnungen der Architektur-Ebenen (Stage, Cleansing, Core - darüber dann die Data Marts), über Vorschläge zur Historisierung bis hin zu Namenskonventionen für instrumentierende Metadaten-Spalten.
  • Datenintegration: liefert Vorschläge zur Implementierung von Quality Checks und Data Profiling, erklärt unterschiedliche Vorgehensweisen zur Delta-Extraktion und beschäftigt sich eingehend mit der Implementierung und Optimierung von ETL-Prozessen.
  • Aufbau und Betrieb eines Data Warehouse: geht genauer auf die Rolle der Schichten der DWH-Architektur ein und liefert präzise Aussagen zu Funktion und Abgrenzung der Elemente. An vielen Stellen werden auf Erfahrungswerten basierende Praxishinweise gegeben: etwa der, dass ein Operational Data Store (ODS) zur Bereitstellung sehr aktueller Daten in vielen Fällen die erforderliche Mühe nicht lohnt. Daneben gibt es eine ganze Reihe präziser Vorschläge zur Datenmodellierung und zur Implementierung von Transformationen (etwa zur Versionierung von Dimensionen). Nach einer kurzen Einführung zum Thema MOLAP folgen praktische Hinweise zur Verwendung von Oracle-Features: Aussagen zu empfohlenen Blockgrößen, PGA- und SGA-Dimensionierung, Parallelisierung, Statistikerhebung, Partitionierung, Indizierung, Backup + Recovery etc. Darüber hinaus liefert das Kapitel Vorschläge zum Entwicklungsprozess, zum Einsatz von Versionsverwaltungs-Repositories und zum Deployment von Änderungen und geht recht intensiv auf das Performance-Monitoring im DWH ein.
  • Business Intelligence-Plattformen: ein recht kurzes Kapitel mit einer Vorstellung von BI-Plattformen im Allgemeinen und der OBIEE im Besonderen. Recht instruktiv, aber mit 10 Seiten doch sehr knapp.
Im Zusammenhang der Implementierungsvorschläge erscheinen neben SQL-Code auch Hinweise auf die entsprechenden Optionen der ETL-Tools von Oracle (OWB, ODI), wobei Oberflächenscreenshots die Ausnahme bleiben (was ich erwähne, weil ich in der Vergangenheit ziemlich viele Bücher aus dem Microsoft-Umfeld gelesen/durchgeblättert habe, die nicht viel mehr als kommentierte Screenshot-Sammlungen darstellten).

Zu den Pluspunkten des Buches gehören aus meiner Sicht die klare Struktur und die hohe (inhaltliche und sprachliche) Präzision der Erläuterungen. Die Autoren kommen nie ins Plaudern, sondern immer sehr schnell auf den Punkt - den Inhalt hätte man ohne große Mühe auf die doppelte Länge bringen können: mein Dank an die Verfasser, dass sie darauf verzichtet haben. Gut gefallen mir die Konventionsvorschläge, bei denen ich mich gelegentlich auch schon bedient habe, und die klaren Stellungnahmen zu zahlreichen praktischen Problemen. Bei den recht umfangreichen Ausführungen zum Thema Performance habe ich fast ausschließlich Aussagen gefunden, die sich mit meinen Ansichten decken, und nichts, was meinen deutlichen Widerspruch hervorrufen würde.

Schwieriger ist die Suche nach Kritikpunkten. An einigen Stellen wird die Darstellung doch etwas zu knapp, etwa im letzten Kapitel, bei dem ich nach Lektüre des letzten Satzes ("Der Aufruf existierender bzw. das Definieren neuer Reports erfolgt direkt von der OBIEE-Homepage") kurz darüber nachdachte, ob da vielleicht Seiten fehlten...

Insgesamt halte ich Data Warehousing mit Oracle für ein sehr lesenswertes Buch: sowohl Einsteiger als auch erfahrene DWH-Entwickler/-DBAs/-Architekten werden hier jede Menge interessanter Informationen finden, die in der praktischen Arbeit mit Oracle-DWHs sehr nützlich sein können.

Erwähnenswert ist vielleicht auch noch die "patentierte Bindung", die dafür sorgt, dass das Buch offen liegen bleibt - meistens jedenfalls ...

Montag, März 11, 2013

Analytics mit row-Angabe in der window clause

Kim Berg Hansen, der Steven Feuerstein regelmäßig bei der PL/SQL Challenge unterstützt, erläutert das unterschiedliche Verhalten von row- und range-Angaben (letztere sind der default) in der window clause von Analytics, wobei sein Beispiel eine analytische Summenfunktion zur Ermittlung einer rolling sum ist (also einer Summe bis zum gegebenen Satz): mit dem default (range) erscheint für gleiche Werte in der ORDER BY-Sortierspalte auch die gleiche aggregierte Summe, was nicht unbedingt intuitiv ist. Möchte man eine rolling sum haben, die für jeden Satz die bis dorthin aggregierten Summen ausweist, so muss man eine window clause mit row-Angabe verwenden - also z.B.:

sum(sal) over (partition by deptno
                   order by sal
                    rows between unbounded preceding and current row)

Neben dem plausibleren Ergebnis hat die Verwendung der row-Angabe auch den Vorteil, dass sie im Fall der Verschachtelung mehrerer analytischer Funktionen einen WINDOW NOSORT-Schritt an einer Stelle möglich macht, an der sonst eine zusätzliche Sortierung erfolgen müsste. Daher liefert der Herr Hansen folgende Merksätze:
  • If I am doing analytic on the entire partition (or entire resultset), then I skip the window clause (that is: I do not write ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING).
  • But once I have an ORDER BY, I generally do not rely on default window clause, but rather explicitly writes either ROWS or RANGE BETWEEN.
Meine Zusammenfassung ist in diesem Fall übrigens (wieder einmal) deutlich unverständlicher als die Quelle, die den Fall anhand kompakter Beispiele nachvollziehbar erläutert.

Mittwoch, März 06, 2013

SQL_ID ohne SQL_TEXT

Julian Dontcheff liefert eine Erklärung für das Phänomen, dass in V$SQL SQL_ID-Angaben erscheinen, zu denen V$SQLTEXT keinen Text liefern kann:
These are Oracle internal or so called pseudo cursors which are just structures providing direct access database objects by avoiding the overhead of writing an explicit SELECT statement. These structures access directly most of the time the data dictionary tables, CLOBs and BLOBs. Sometimes even NCHAR and NVARCHAR2.
Zu diesen SQL_IDs gibt es also tatsächlich keine Texte, weil es sich nicht um SQL-Statements handelt. Im Artikel wird (mit Verweis auf ein MOS-Dokument) auch noch eine View-Definition geliefert, mit deren Hilfe ein paar Informationen zu den Zugriffen zusammengestellt werden können.

Dienstag, März 05, 2013

Index-Duplikate

Bei Jonathan Lewis findet sich eine interessante Liste von Möglichkeiten, wie man in USER_IND_COLUMNS eine (anscheinend) gleiche Spaltenkombination in gleicher Reihenfolge für zwei verschiedene Indizes (anscheinend) einer Tabelle erhalten kann, ohne den Fehler ORA-01408: such column list already indexed hervorzurufen. Zu den Möglichkeiten gehören:
  • Verwendung eines nosegment Index
  • Anlage von Cluster und im Cluster integrierter Tabelle jeweils mit Index
  • Verwendung unterschiedlicher Schemata
  • Verwendung von blank oder unsichtbarem Sonderzeichen in Spaltennamen
Leider wurde ich für meinen Beitrag (Änderung der Definition von USER_IND_COLUMNS) disqualifiziert: "I think I’m going to disqualify you for tampering with intent to discredit data dictionary views." Womit er natürlich wieder mal Recht hat, der Herr Lewis.

Data Explorer

Dieser Tage wurde ein Public Preview von Microsofts Data Explorer zum Download bereit gestellt und von sachkundiger Seite kommentiert. Chris Webb liefert in diesem Zusammenhang die Definition:
In a nutshell, Data Explorer is self-service ETL for the Excel power user – it is to SSIS what PowerPivot is to SSAS. In my opinion it is just as important as PowerPivot for Microsoft’s self-service BI strategy.
Im gleichen Artikel gibt's neben grundsätzlichen Informationen noch diverse Links auf offizielle Aussagen von Microsoft. Zusätzlich hat der Herr Webb noch eine detaillierte Anleitung zum Thema Importing Data From Multiple Log Files Using Data Explorer veröffentlicht, das den Einsatz von Data Explorer am Beispiel des Imports der Statistiken seines Blogs vorführt. Wenn man an den Statistiken des Herrn Webb nicht so sehr interessiert ist, kann man auch der (möglicherweise noch detaillierteren) Anleitung folgen, mit der Dan English  die Installation des Tools und das Einlesen von Daten aus der Internet Movie Database (imdb) vorstellt. Und sollte das noch nicht genügen, dann gäbe es noch einen Artikel von Jason Thomas mit einem weiteren Tutorial und Links auf diverse weitere Blogs, auf deren Erwähnung ich an dieser Stelle verzichte.

Chris Webb geht dann noch einen Schritt weiter und zeigt in zwei Artikeln, wie man mit Hilfe des Data Explorer geographische Daten über Web Service nach Excel importieren kann. Das alles sieht recht harmlos aus und dürfte anhand der Anleitungen sehr leicht nachvollziehbar sein.

Samstag, März 02, 2013

Stack Profiler für Oracle

Tanel Poder ist fürchterlich produktiv dieser Tage, so dass ich kaum nachkomme, seine Artikel zu lesen (bzw. Podcasts anzuschauen) - oder gar darüber zu schreiben. Im Artikel Troubleshooting high CPU usage with poor-man’s stack profiler – in a one-liner! zeigt er, wie man (in Abwesenheit von SQL Monitoring, also in jedem Fall unterhalb von 11g) mit Hilfe seines (Solaris) Scripts os_explain (das seiner Meinung nach auch für andere OS anzupassen ist) bestimmen kann, welcher Aufruf den größten Anteil an der Laufzeit einer Query hat. Im Beispiel zeigt er das Ergebnis am Beispiel eines Zugriffs auf DBA_LOCK_INTERNAL. Natürlich gäbe es da auch noch ein paar andere Trace-Möglichkeiten, aber zur Untersuchung einer aktuell laufenden Operation ist das allemal ein nettes zusätzliches Werkzeug.

Kostenlose Joins

Randolf Geist präsentiert in seinem Blog ein interessantes Beispiel, in dem ein über Nested Loops verarbeiteter Outer Join mit einer Join-Bedingung, die auf der Seite der driving table eine Spalte anspricht, die immer NULL ist, vom CBO als nahezu kostenlos betrachtet wird: die Gesamtkosten der Query entsprechen denen des Zugriffs auf die driving table und der CBO addiert nur die Kosten eines einzigen Lookups, da er - aus guten Gründen - annimmt, dass die Lookups keine Treffer liefern können. Allerdings weist Randolf darauf hin, dass die Loops offenbar trotzdem ausgeführt werden, was die Entscheidung, die Kosten weitgehend zu ignorieren, doch ein wenig fragwürdig erscheinen lässt. Hier die entsprechenden rowsource Statistiken meiner Windows8-Spieldatenbank (11.2.0.1):

-------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name   | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |        |      1 |        |   1000K|00:00:01.54 |   82063 |
|   1 |  NESTED LOOPS OUTER          |        |      1 |   1000K|   1000K|00:00:01.54 |   82063 |
|   2 |   TABLE ACCESS FULL          | T1     |      1 |   1000K|   1000K|00:00:00.73 |   82063 |
|   3 |   TABLE ACCESS BY INDEX ROWID| T2     |   1000K|      1 |      0 |00:00:00.55 |       0 |
|*  4 |    INDEX RANGE SCAN          | T2_IDX |   1000K|      1 |      0 |00:00:00.26 |       0 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("T1"."NULL_FK"="T2"."ID")

Demnach fällt für step 3 und 4 Arbeit an (wie die Starts und A-Time anzeigen), allerdings offenbar nicht im Bereich der Lesezugriffe (Buffers = 0). Aber immerhin erkennt der CBO, dass es sich hier um einen Sonderfall handelt, der eine korrigierte Kalkulation verdient.

In einem zweiten Artikel "Cost-free" joins - 2 untersucht Randolf Geist das Verhalten von MERGE Joins, die der CBO bekanntlich relativ selten auswählt, da sie in der Regel das Sortieren beider Datenquellen erfordern (sofern diese nicht schon durch einen vorangehenden Schritt - etwa einen INDEX RANGE SCAN - sortiert sind). Interessant ist der Hinweis, dass die Reihenfolge der Datenquellen (anders als beim HASH JOIN) keine größere Rolle spielt und dass es nicht möglich ist, diese Reihenfolge zu ändern (ebenfalls anders als beim HASH JOIN). Der Fall, in dem ein kostenloser Join auftritt, ist hier ein MERGE Outer Join einer sehr großem Tabelle, die mit einer Lookup-Tabelle verknüpft wird, auf die ein INDEX UNIQUE SCAN erfolgt - wobei der Effekt problematisch wird, sobald Parallelisierung ins Spiel kommt. Aber da der Fall etwas unübersichtlich ist, kopiere ich an dieser Stelle einfach das Fazit des Artikels:
For MERGE JOINs there are some special cases where the current costing model doesn't properly reflect the actual work - together with some strange behaviour of the MERGE JOIN code when using Parallel Execution this can lead to questionable execution plans preferred by the optimizer.
Carefully check the resulting execution plans when using Parallel Execution and MERGE JOINs get preferred by the optimizer.