Freitag, 5. August 2011

Wie man Wartezeiten sinnvoll abkürzt oder wobei hilft mir SDO_JOIN?

Was passiert eigentlich auf einem Standard Notebook mit der Oracle Datenbank an Bord, wenn man alle Geometrien einer Tabelle mit allen (oder so gut wie allen) Geometrien einer anderen Tabellen verschneiden will?

Das habe ich mal ausprobiert am Beispiel des GfK GeoMarketing Deutschlanddatensets. Dazu habe ich mir folgendes Result Set überlegt:

Ich brauche eine Auflistung der

  • administrativen Ebene 3 (Name und Gemeindekennziffer der Stadt- und Landkreise)
  • administrativen Ebene 4 (Name und Gemeidekennziffer Gemeinden)
  • und der den Gemeinden zugeordneten 5-stelligen Postleitzahlen.
Frisch ans Werk und sozusagen straight forward habe ich es mal mit dieser SQL-Abfrage probiert:

select 
  d.id , 
  d.name "Name Stadt-/Landkreis", 
  d.new___z "Anzahl EW Stadt-/Landkreis",
  g.id "ID Gemeinde", 
  g.name "Name Gemeinde", 
  g.new___z "Anzahl EW Gemeinde",
  p.id "PLZ"
from 
  de_municipalities_2010 g,
  de_districts_2010 d,
  de_5digpc_2010 p
where
  substr(g.id,1,5) = d.id and 
  sdo_relate(g.geometry, p.geometry, 'mask=anyinteract') = 'TRUE' and 
  p.id = '16515'
group by
  d.id , 
  d.name, 
  d.new___z,
  g.id, 
  g.name, 
  g.new___z,
  p.id
order by
  d.id , 
  d.name, 
  g.id, 
  g.name,
  p.id
/
Aus Erfahrung weiss man um die Nützlichkeit von Filtern, welche die zu vergleichenden Datenmengen zunächst erst einmal einschränken. Von daher die Betrachtung erst mal nur einer einzigen Postleitzahl.

Ein bisschen mutiger geworden, wird der Filter dann gelockert, um ihn ganz zu entfernen. Denn Ziel war ja, den kompletten Datenbestand beider Tabellen räumlich in Beziehung zu setzen, um auch die Postleitzahlen zu ermitteln, welchen den Gemeinden zugeordnet sind. Das sind knapp 11600 Gemeinden und gut 8200 PLZs.

So und das war es dann auch erst mal für den Nachmittag, den Abend ... und auch am nächsten Morgen hatte sich noch kein Result Set einstellen wollen.

Also muss es wohl noch besser gehen.

Folgende überlegungen führten dann zu weiteren Vesuchen:

  • Ich stelle sicher, dass für beide Tabellen der räumliche Index benutzt wird.
  • Ich nutze erst mal nur den Primary Filter, um ein annäherndes Ergebnis zu erhalten. Danach wird der exakte Vergleich nur noch mit dem dann schon eingeschränkten Datenset vorgenommen.
Mit diesen beiden Gedanken im Hinterkopf und ggf. auch noch mal einem Blick ins Oracle Spatial Handbuch, wird man bei SDO_JOIN fündig.

Wie funktioniert dabei SDO_JOIN?

select
  rowid1 as municipalities_id,
  rowid2 as plz5_id
from
  table(
    sdo_join(
   'DE_MUNICIPALITIES_2010',
   'GEOMETRY',
   'DE_5DIGPC_2010',
   'GEOMETRY',
   'mask=anyinteract'))
/
Und siehe da: Diese Abfrage dauert keine 2 Minuten.
Allerdings fehlt ja auch noch der Join mit der 3. Tabelle und auch group by und order by sollen schon sein und kosten die Datenbank so einiges an Ressourcen und damit Zeit.

Also muss der Rest auch noch her und ergibt dann diese SQL Abfrage:

with spatial_join_result as (
select
  rowid1 as municipalities_id,
  rowid2 as plz5_id
from
  table(
    sdo_join(
   'DE_MUNICIPALITIES_2010',
   'GEOMETRY',
   'DE_5DIGPC_2010',
   'GEOMETRY',
   'mask=anyinteract')))
select 
  d.name "Name Stadt-/Landkreis", 
  d.new___z "Anzahl EW Stadt-/Landkreis",
  g.name "Name Gemeinde", 
  g.new___z "Anzahl EW Gemeinde",
  p.id "PLZ"  
from
  spatial_join_result a, 
  de_municipalities_2010 g,
  de_5digpc_2010 p,
  de_districts_2010 d  
where
  a.municipalities_id = g.rowid and
  a.plz5_id = p.rowid and
  sdo_relate(g.geometry, p.geometry, 'mask=anyinteract') = 'TRUE' and
  substr(g.id, 1, 5) = d.id  
-- Hierarchische Verknüpfung Admin Ebene 3 mit Admin Ebene 4
group by
  d.name,
  d.new___z,
  g.name,
  g.new___z,
  p.id
order by
  d.name,
  d.new___z,
  g.name,
  g.new___z,
  p.id
/
Jetzt habe ich, was ich mir zum Ziel gesetzt hatte und zwar in einer Zeit von 14 Minuten. Das reicht zwar immer noch für einen Plausch mit den Kollegen zwischendurch. Aber diese Zeit ist erst mal akzeptabel.

Für diejenigen Leserinnen und Leser dieses Blogeintrags, die im Besitz einer (gern auch mehrerer) Oracle DB Enterprise Edition Lizenz sind, sei gesagt, dass sie damit noch mehr Optimierungspotential haben. Das verheissungsvolle Wort an dieser Stelle ist Parallisierung.
Wie das funktioniert, dafür verweise ich jetzt einfach mal auf diesen Link. Denn sonst verpasse ich vielleicht noch meinen Flieger in den Urlaub.

Montag, 4. Juli 2011

Aktueller MapViewer Patch (11g PS4) released

Wir sind hier mit dem Oracle Spatial Blog zwar auf der Datenbank-Seite. Aber ohne Visualisierung sind Geodaten zwar zu benutzen im Sinne einer Prozessierung, aber halt nicht besonders anschaulich. Von daher sei die nachfolgende Mitteilung gestattet:

Der aktuelle Patch (11g PS4) für Oracle Fusion Middleware MapViewer (MapViewer version 11.1.1.5) steht hier zum Download bereit.

Donnerstag, 9. Juni 2011

Geodatenschätze heben - Räumliche Analysen und Data Mining

Über gängige räumliche Operatoren und Funktionen hinaus bietet Oracle Spatial Methoden, um den Einfluss von Nachbarschaftsbeziehungen auf der Basis der Verortung von Objekten zu untersuchen, abzuschätzen und vorauszusagen.
Diese sind den folgenden Anwendungsbereichen zugeordnet und im PL/SQL Package SDO_SAM implementiert:
  • Location Prospecting Analysis
  • Clustering Analysis
  • Spatial Mining
  • Neighborhood-Bases Estimation
Der heutige Blogeintrag gibt einen ersten kleinen Einblick in die von diesem Package bereitgetellten Methoden.

SDO_SAM.AGGREGATES_FOR_LAYER in Anwendung

Betrachten wir folgenden Anwendungsfall:
Für die Beurteilung der Auswirkungen von Fluglärm sollen die Bewohnerinnen und Bewohner im Umkreis von 5 km um die Flughäfen ermittelt werden.

Für die notwendige Analyse wird als Datengrundlage bewährtermassen das von der GfK GeoMarketing für die Oracle Datenbank bereitgestellte Deutschland-Datenset verwendet. Darin enthalten sind (u.a.) die Tabellen:

  • DE_AIRPORTS mit allen Flughäfen in Deutschland
  • DE_5DIGPC_2010 mit den 5-stelligen PLZ-Geometrien und u.a. der Population als Kennzahl
Diese nutzen wir ebenso wie die Prozedur AGGREGATES_FOR_LAYER im PL/SQL-Package SDO_SAM.
Im nachfolgenden SQL-Befehl, welcher einen View anlegt, sind die Parameter-Werte für die Prozedur kommentiert, um ihre Verwendung zu erklären.
-- Berechnet thematisches Aggregat für einen Geometrielayer 
create or replace view de_stats_pop_around_airports
as
select 
  a.name,
  a.type,
  round(b.aggregate_value) aggregate_value,
  b.geometry
from
  table(  
    sdo_sam.aggregates_for_layer(
      'DE_5DIGPC_2010',      -- Theme-Tabelle. 5-stellige PLZ Geometrien
      'GEOMETRY',            -- Geometriespalte der Theme-Tabelle
      'SUM',                 -- Aggregatsfunktion (Summe)
      'NEW___Z',             -- Zu aggregierender Wert (Bevölkerung absolut)
      'DE_AIRPORTS',         -- Data Mining Tabelle (Flughäfen)
      'GEOMETRY',            -- Geometriespalte in Data Mining Tabelle
      'distance=5 unit=km')  -- Distanzspezifikation (Umkreis von 5km um Flughäfen)
  ) b,
  de_airports a
where 
  b.region_id = a.rowid;
Die in diesem View aggregierten Daten sollen auf einer Karte dargestellt werden. Dafür benötigen wir zunächst einmal die Metadaten. Die Syntax für den entsprechenden INSERT-Befehl ist sichert vertraut.
-- Metadaten
insert into user_sdo_geom_metadata (
  table_name, 
  column_name, 
  diminfo,
  srid) 
values (
  'DE_STATS_POP_AROUND_AIRPORTS',
  'GEOMETRY',
  sdo_dim_array(sdo_dim_element('Lon',-180,180,0.005),
  sdo_dim_element('Lat',-90,90,0.005)),
  8307);
Der Rest ist dann Arbeit für den Oracle MapBuilder. Dort wird ein enstprechender Style definiert (Kreis roter Füllung und schwarzer Umrandung). Dieser Style wird für ein Theme verwendet, welches als Advanced Theme > Variable Marker definiert ist.
Das Ergebnis ist im nachfolgenden Bild dargestellt. Um die thematische Kartenebene räumlich besser einordnen zu können, wurde eine weitere Kartenebene hinterlegt, welche die Bundesländergrenzen von DE abbildet.

Thematische Karte mit Population im Umkreis von 5 km um Flughäfen dargestellt als Ranged Variable Markers
(basierend auf einem Deutschland-Datenset der GfK GeoMarketing für die Oracle DB)

Mit SDO_SAM.AGGREGATES_FOR_LAYER liegt damit ein Einstieg ins Thema vor. Weitere Tipps & Tricks zum Thema werden folgen.

Der Vollständigkeit halber sind nachfolgend noch die XML-Dokumente für den Advanced Style und das Theme eingefügt.

<?xml version="1.0" ?>
<AdvancedStyle>
  <VariableMarkerStyle basemarker="CITIES_OVER_100K" startsize="5" increment="4">
    <Buckets>
      <RangedBucket seq="0" label="<5K" low="-Infinity" high="5000" label_style="LABELS"/>
      <RangedBucket seq="1" label="5-10K" low="5000" high="10000" label_style="LABELS"/>
      <RangedBucket seq="2" label="10-20K" low="10000" high="20000" label_style="LABELS"/>
      <RangedBucket seq="3" label="20-50K" low="20000" high="50000" label_style="LABELS"/>
      <RangedBucket seq="4" label="50-100K" low="50000" high="100000" label_style="LABELS"/>
      <RangedBucket seq="5" label="100-200K" low="100000" high="200000" label_style="LABELS"/>
      <RangedBucket seq="6" label="200-500K" low="200000" high="500000" label_style="LABELS"/>
      <RangedBucket seq="7" label=">500K" low="500000" high="Infinity"/>
    </Buckets>
  </VariableMarkerStyle>
</AdvancedStyle>
<?xml version="1.0" standalone="yes"?>
<styling_rules>
    <hidden_info>
        <field column="NAME" name="Name des Flughafens"/>
        <field column="AGGREGATE_VALUE" name="Population absolut"/>
        <field column="TYPE" name="Typ des Flughafens"/>
  </hidden_info>
    <rule column="AGGREGATE_VALUE">
        <features style="V.DE_POP_AROUND_AIRPORTS"> </features>
        <label column="NAME" style="LABELS"> 1 </label>
  </rule>
</styling_rules>

Montag, 30. Mai 2011

Aus Oracle nach Google Earth mit Hilfe von KML

Das SDO_UTIL Package (Utility) bietet seit der Version 11g der Oracle Datenbank neue Möglichkeiten für einen direkten Umgang mit der Keyhole Markup Language (KML). 

So können beispielsweise spatiale Geometrien mit Hilfe der Funktion sdo_util.to_kmlgeometry in KML umgewandelt werden. Umgekehrt können mit Hilfe der Funktion sdo_util.from_kmlgeometry KML-Geometrien in spatiale Geometrien umgewandelt werden. 

In diesem Artikel erfahren Sie, wie die Funktion  sdo_util.to_kmlgeometry angewendet wird und wie Sie das Ergebnis zu einem vollständigen KML-Dokument, welches anschließend in Google Earth geladen wird, umwandeln können.  

Schauen wir uns einen einfachen Anwendungsfall an:
SELECT sdo_util.to_kmlgeometry(geometry) KML
FROM  M_ADMIN_AREA2
WHERE
feature_name = 'BERLIN';
Als Ergebnis dieser Abfrage erhalten wir eine KML-Geometrie für das Bundesland Berlin:

KML
---------------------------------------------------------------------------
<Polygon><extrude>0</extrude><tessellate>0</tessellate><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><coordinates>
13.56177,52.5804 13.54188,52.58915 13.53483,52.59068 13.50847,52.59241 13.49723,52.60583 13.49827,52.60961 13.50573,52.62563 13.51852,52.63162 13.52244,52.64464 13.5124,52.64478 13.49034,52.65466 13.48478,52.65872 
...
...
13.65677,52.52511 13.65713,52.52987 13.62592,52.53013 13.62523,52.53815 13.63451,52.53879 13.63662,52.54234 13.58706,52.54958 13.58239,52.56993 13.56894,52.57295 13.56177,52.5804
</coordinates></LinearRing></outerBoundaryIs></Polygon>
---------------------------------------------------------------------------
Wenn Sie dieses Ergebnis in einer KML-Datei abspeichern und diese Datei in Google Earth öffnen, dann wird die oben abgefragte Geometrie zunächst nicht angezeigt. Zu einem vollständigen KML-Dokument fehlen neben dem XML-Header noch einige Angaben, die wir mit Hilfe der XML DB, einem Feature welches in jeder Oracle Datenbank enthalten ist, ergänzen werden.

Überprüfen Sie zuerst, ob XML DB bei der Datenbank-Installation mit installiert wurde. Führen Sie dazu im SQL*PLUS die folgende Abfrage aus:
select comp_name, status from dba_registry where comp_name='Oracle XML Database';
Falls diese Funktionalität in Ihrer Datenbank nicht installiert sein sollte, dann können Sie das XML DB Repository mit Hilfe des folgenden Scripts nachinstallieren
 $ORACLE_HOME/rdbms/admin/catqm.sql
Kommen wir zu unserer Ausgangsabfrage zurück und ergänzen diese um die fehlenden Angaben:
SELECT
  xmlelement("kml",
   xmlattributes('http://www.opengis.net/kml/2.2' as "xmlns"),
   xmlelement("Document",
    xmlelement("Placemark",
     xmlelement("name", 'Berlin'),
     xmlelement("Description", 'Flaeche des Bundeslandes Berlin'),
     xmltype(sdo_util.to_kmlgeometry(geometry))
    )
   )
  )
FROM  M_ADMIN_AREA2 WHERE
feature_name = 'BERLIN';
 Das Ergebnis bildet ein vollständiges KML-Dokument:
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Placemark>
<name>Berlin</name>
<Description>Flaeche des Bundeslandes Berlin</Description>
<Polygon>
<extrude>0</extrude>
<tessellate>0</tessellate>
<altitudeMode>relativeToGround</altitudeMode>
<outerBoundaryIs>
<LinearRing>
<coordinates>13.56177,52.5804 13.54188,52.58915 13.53483,52.59068 13.50847,52.59241 13.49723,52.60583 13.49827,52.60961 13.50573,52.62563 13.51852,52.63162 13.52244,52.64464 13.5124,52.64478 13.49034,52.65466 ...
...
...
13.62592,52.53013 13.62523,52.53815 13.63451,52.53879 13.63662,52.54234 13.58706,52.54958 13.58239,52.56993 13.56894,52.57295 13.56177,52.5804
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
Speichern Sie das Dokument ab und öffnen Sie es in Google Earth:

Spatiale Geometrie in Google Earth
Mit Hilfe der XML-Funktionen können Sie das KML-Dokument erweitern und weitere Attribute hinzufügen. Probieren Sie diese Abfrage aus:

SELECT
  xmlelement("kml",
   xmlattributes('http://www.opengis.net/kml/2.2' as "xmlns"),
   xmlelement("Document",
    xmlelement("name", 'Berlin.kml'),
    xmlelement("StyleMap", XMLATTRIBUTES('mp' as "id"),
     xmlelement("Pair",
       xmlelement("key",'normal'),
       xmlelement("styleUrl",'#mp_border')
     )
    ),
    xmlelement("Style", XMLATTRIBUTES('mp_border' as "id"),
     xmlelement("LineStyle",
       xmlelement("color",'ffff0000'),
       xmlelement("width",'10')
     )
    ),
    xmlelement("Placemark",
     xmlelement("name", 'Berlin'),
     xmlelement("styleUrl", '#mp'),
     xmlelement("Description", 'Flaeche des Bundeslandes Berlin'),
     xmltype(sdo_util.to_kmlgeometry(geometry))
    )
   )
  )
FROM  M_ADMIN_AREA2 WHERE feature_name = 'BERLIN';
Als Ergebnis erhalten Sie einen blauen Rand um die angezeigte Geometrie:

Spatiale Geometrie mit blauer Umrandung in Google Earth

Donnerstag, 26. Mai 2011

Toleranz und Performanz bei räumlichen Abfragen

In diesem Blogeintrag soll es um die Frage gehen, ob unterschiedliche Werte für den Toleranzparameter Einfluss auf die Performanz räumlicher Abfragen haben.
Die Datenbank arbeitet mit Toleranzen sowohl bei der Definition der SDO-Metadaten als auch bei räumlichen Abfragen. Die Toleranz steht dabei für den Abstand, den 2 (Stütz-)Punkte maximal haben dürfen, um sie als identisch anzusehen. Die Toleranz ist somit ein Mass für die Genauigkeit räumlicher Daten.

Testsituation

Um die anfangs aufgeworfene Frage zu beantworten, wurden zwei Testreihen aufgesetzt, bei denen verschiedene räumliche Funktionen mit skalierenden Toleranzen zur Anwendung kommen. Zwei Testreihen deshalb, um die Auswirkungen für einen relativ kleinen (~8.200 Sätze) und einen größeren Datenbestand (~830.000 Sätze) zu untersuchen.
Die Testdaten, ausschliesslich Polygone mit den 5-stelligen Postleitzahlgeometrien von Deutschland, wurden vom Oracle-Partner GfK GeoMarketing bereitgestellt. Das verwendete Koordinatensystem ist 8307, die Metadaten sind mit einer Toleranz von 0,05 (5 cm) registriert.
An räumlichen Funktionen wurden verwendet:
  • SDO_GEOM.RELATE
  • SDO_GEOM.SDO_ALPHA_SHAPE
  • SDO_GEOM.SDO_AREA
  • SDO_GEOM.SDO_BUFFER
  • SDO_GEOM.SDO_CENTROID
  • SDO_GEOM.SDO_CONCAVEHULL
  • SDO_GEOM.SDO_CONVEXHULL
  • SDO_GEOM.SDO_CONCAVEHULL
  • SDO_GEOM.SDO_DIFFERENCE
  • SDO_GEOM.SDO_DISTANCE
  • SDO_GEOM.SDO_INTERSECTION
  • SDO_GEOM.SDO_TRIANGULATE
  • SDO_GEOM.SDO_UION
  • SDO_GEOM.SIMPLIFY_GEOMETRY
Die Toleranz wurde angefangen mit dem Wert 0.1 (10 cm) pro Iteration verdoppelt bis zum Maximalwert von ~205 (m).
Für die Testsituation wurden nach dem Anlegen der Testtabellen aktuelle Statistiken berechnet.
begin 
  DBMS_STATS.GATHER_TABLE_STATS (
    ownname => '"GFK"',
    tabname => '"TEST_TOL_IMPACT"',
    estimate_percent => 100
  );
end;
Außerdem wurden bei jeder Iteration sowohl Shared Pool als auch Buffer Cache geleert.
alter system flush buffer_cache;
alter system flush shared_pool;
-- Hierfür benötigt der Nutzer alter system Recht 
Dieses Vorgehen ist ausdrücklich nicht für produktive Umgebungen zu empfehlen, dient aber hier der Vergleichbarkeit der Ausführungszeiten.
Diese wurden gemessen, indem für jede räumliche Abfrage vorher als auch hinterher die Total Time sowie CPU Time mittels zweier PL/SQL Funktionen gemessen wurde.
-- Gesamtzeit
create or replace function measure_total_time 
return 
  pls_integer
is
begin
  return dbms_utility.get_time;
end measure_total_time;
/
-- CPU Zeit
create or replace function measure_cpu_time 
return 
  pls_integer
is
begin
  return dbms_utility.get_cpu_time;
end measure_cpu_time;
/
-- Für die Ausführung benötigt der Nutzer das Recht EXECUTE auf dem Package dbms_utility
Die Differenz der vorher und nachher gemessenen Werte jeweils geteilt durch 100 ergibt die Ausführungs- bzw. CPU-Zeit in Sekunden.
Alle Messwerte wurden in 2 Ergebnistabellen festgehalten, mit APEX-Bordmitteln ausgewertet und grafisch als 2D Line Charts mit je einer Serie pro räumlicher Funktion aufbereitet. Die Ergebnisse sind in den Abbildungen am Ende dieses Blogeintrags zu sehen.

Welche Erkenntnisse liefern die Messwerte?

  • Die Annahme, dass die Ausführungszeiten mit geringer werdenden Toleranzwerten (also höherer Genauigkeit) korreliert, hat sich bei keiner der räumlichen Funktionen bestät.
  • Die gemessenen Zeiten für Testreihe 2 (~830.000 Sätze) sind vergleichbar mit denen von Testreihe 1 (~8.200 ätze).
  • Mit gemessenen CPU-Zeiten bis maximal 0,3 sec und durchschnittlichen Gesamtzeiten von 1,3 (Testreihe 1) und 1,5 (Testreihe 2) waren die Abfragen trotz flush shared_pool und flush buffer_cache recht performant.
    Als Testsystem diente ein 64bit Laptop mit Intel i5 Prozessor und 4 GB als maximaler SGA Grösse.
An dieser Stelle möchte ich noch mal darauf hinweisen, dass im Gegensatz zu den Ausführungszeiten die jeweiligen Ergebnismengen nicht im Fokus der Tests standen.

Fazit

Räumliche Abfragen können jeweils mit einer im Hinblick
  • auf die Genauigkeit des Datenbestandes und
  • die erwartete Ergebnismenge
passenden Toleranz ausgeführt werden, ohne dass dies signifikante Auswirkungen auf die Performanz hat.

Abbildungen

Testreihe 1 - Total Time

Testreihe 1 - CPU Time

Testreihe 2 - Total Time

Testreihe 2 - CPU Time