Montag, 27. Oktober 2014

2 interessante Veranstaltungen für alle mit Fokus auf 3D: 3DGeoInfo Conference und EuroSDR / ISPRS Workshop

Diejenigen, welche mit großen Mengen an 3D Daten umgehen müssen, seien auf sehr 2 interessante Veranstaltungen hingewiesen:
  1. 3DGeoInfo Conference vom 11.-13. November 2014 in Dubai. U.a. wird es einen halbtägigen Workshop geben zum Thema "Storage and Management of Large Scale Point Cloud Data" mit Mike Horhammer, dem Lead Developer für Oracle Spatial and Graph 3D, in Kooperation mit der TU Delft.
  2. EuroSDR / ISPRS: Workshop for capturing national scale 3D models vom 27.-28. November 2014 in Southampton, UK. Das ist ein Workshop, der sich insbesondere an Landesvermessungen / Mapping Agencies richtet.

Freitag, 24. Oktober 2014

Vegetationsindex berechnen mit Oracle Spatial und Raster Algebra in der Datenbank

Seit Oracle 12c können direkt in der Datenbank Raster Algebra Operationen ausgeführt werden.
Damit ist es nun möglich, z.B. Vegetationsindizes wie NDVI für Rasterdaten zu berechnen, die als SDO_GEORASTER in der Oracle Datenbank gespeichert sind.

Hierzu sind im Wesentlichen nur 3 Schritte notwendig:
  1. Laden der Rasterdaten in die Datenbank
  2. Ausführen der entsprechenden Raster Algebra Operation
  3. Anzeige des Ergebnisses
Die 3 Schritte beschreibe ich nachfolgend ein wenig genauer.
Wer das Ganze Schritt für Schritt ausprobieren möchte, ohne die Oracle Datenbank selber installieren zu müssen, die/der kann einen Workshop mit vorkonfigurierter virtueller Maschine und Testdaten dafür nutzen.


Schritt 1: Laden der Rasterdaten

Das Laden habe ich bereits in diesem Blog Posting beschrieben. Alternativ kann man GDAL nutzen und mit Hilfe eines Kommandozeilenbefehls ein Rasterbild direkt in die Datenbank schreiben. Beispielhaft sieht der Aufruf so aus:
gdal_translate -of georaster LT50440332011261PAC01.tif \
	georaster:student/student@$ORACLE_SID,napa_landsat,image \
	-co description="(name varchar2(32), description varchar2(64), image sdo_georaster, primary key (name))" \
	-co insert="('original', 'Landsat 7 bands 2011 Ago 28', sdo_geor.init('napa_landsat_rdt$'))" \
	-co genpyramid=NN \
	-co blockbsize=1
GDAL_TRANSLATE kann optional die Tabelle NAPA_LANDSAT mit IMAGE als SDO_GEORASTER-Spalte im DB Schema STUDENT gleich miterzeugen, falls sie vorher noch nicht angelegt war.
Mit Hilfe des Werkzeuges GeoRasterViewer kann das Ergebnis des Ladevorgangs gleich überprüft werden.
Schritt 2: NDVI direkt in der Datenbank berechnen

Die dem NDVI zugrunde liegende Formel lautet:

NDVI = (NIR-RED)/(NIR+RED)

NIR entspricht dabei dem zurückgestrahlten Licht im Nahen Infrarotbereich, RED dem roten Anteil des sichtbaren Lichts. Bei Landsat-Bildern sind das die Kanäle 3 und 4.
Grundlage für die Berechnung ist das Unterprogramm RASTERMATHOP im PL/SQL Package SDO_GEOR_RA. Dieses wird genutzt, um den NDVI über das zuvor geladene Rasterbild zu rechnen.
set echo on
set serverout on

declare
  gr1 sdo_georaster;
  gr2 sdo_georaster;
  opr sdo_string2_array;
  sts sdo_number_array;
begin
  select image into gr1 from napa_landsat where name = 'original';

-- Tabelle NAPA_IMAGES wurde zuvor angelegt 

  delete from napa_images where name = 'ndvi';
  insert into napa_images 
    values ('ndvi', 'Full scene NDVI', 
            sdo_geor.init('napa_images_rdt$'))
    return image into gr2;

--
-- Raster Algebra Operation - NDVI, Normalized Difference Vegetation Index
--
-- String Array mit Formel für NDVI
    
  opr := sdo_string2_array('(({3}-{2})/({3}+{2}+0.000001))'); -- Nummerierung der Kanäle startet bei 0
  
  sdo_geor_ra.rasterMathOp(inGeoRaster  =&gr; gr1, 
                           operation    =&gr; opr, 
                           storageParam =&gr; 'celldepth=32bit_real', 
                           outGeoRaster =&gr; gr2, 
                           nodata       =&gr; 'TRUE');

-- Zusätzlich Statistiken berechnen
  sts := sdo_geor.generateStatistics(georaster      =&gr; gr2,
                                     pyramidLevel   =&gr; 0,
                                     samplingFactor =&gr; 'samplingFactor=1',
                                     samplingWindow =&gr; null,
                                     bandNumbers    =&gr; null,
                                     nodata         =&gr; 'TRUE',
                                     polygonClip    =&gr; 'FALSE');

-- Statistiken ausgeben
  dbms_output.put_line('Min    = '||sts(1));
  dbms_output.put_line('Max    = '||sts(2));
  dbms_output.put_line('Mean   = '||sts(3));
  dbms_output.put_line('Median = '||sts(4));
  dbms_output.put_line('Mode   = '||sts(5));
  dbms_output.put_line('StdDev = '||sts(6));

-- Bildpyramiden erzeugen
  sdo_geor.generatePyramid(gr2, 'resampling=NN');
  
  sdo_geor.setID(gr2, 'ndvi');
  
-- Rasterbild mit NDVI in die Datenbank schreiben
  update napa_images set image = gr2 where name = 'ndvi';
  commit;
end;
/

exit
Die mit SDO_GEOR.GENERATESTATISTICS berechneten Statistiken haben folgende Werte ergeben:
Min    = -.936254978179932
Max    = .982608675956726
Mean   = .297637717413117
Median = -.936240315437317
Mode   = -.936240315437317
StdDev = .206702946761902
Schritt 3: Ergebnis visualisieren

Der letzte Schritt ist jetzt einfach und nur eine Wiederholung dessen, was schon gemacht wurde. Diesmal nutze ich aber uDig (User-Friendly Desktop GIS) anstelle des GeoRasterViewer für die Anzeige.
uDig unterstützt den direkten Zugriff auf die Oracle Datenbank und kann sowohl mit Vektor- (SDO_GEOMETRY) als auch Rasterdaten (SDO_GEORASTER) arbeiten.

Probiert es mal aus. Nutzt den Workshop "Developing Geospatial Applications With uDig and Oracle Spatial". Einfacher geht es nicht.

Montag, 8. September 2014

Hoch- und Rechtswert von Geometrien verschieben

Heute erhielt ich die Frage, wie man mittels SQL die Hochwerte von Geometrien z.B. um 100 Meter erhöhen kann.
Die Antwort darauf ist relativ einfach: z.B. mit einer Funktion.
Für die Funktion habe ich mit folgenden Prämissen gearbeitet:
  • Bei den Geometrietypen handelt sich um Linien oder Polygone.
  • Die Geometrien sind zweidimensional.
  • Die Masseinheit für die Verschiebung ist "m".
Der Funktion gebe ich 3 Parameter mit:
  1. Ausgangsgeometrie
  2. Offset für den Rechtswert
  3. Offset für den Hochwert
Der Default für die beiden Offset-Werte ist jeweils 0.
Damit sieht die Funktion dann wie folgt aus:
create or replace function geom_add_offset(
  p_geom sdo_geometry,
  p_offset_east number default 0,               -- Offset für den Rechtswert in Metern
  p_offset_north number default 0               -- Offset für den Hochwert in Metern
) return sdo_geometry deterministic is
  l_geom sdo_geometry := p_geom ;
begin
  for i in 1..p_geom.sdo_ordinates.count loop
    if mod(i,2) = 0 then
    -- Hochwert: 2. Wert in einem Koordinatenpaar
      l_geom.sdo_ordinates(i) := l_geom.sdo_ordinates(i) + p_offset_north;
   else
    -- Hochwert: 1. Wert in einem Koordinatenpaar
      l_geom.sdo_ordinates(i) := l_geom.sdo_ordinates(i) + p_offset_east;
    end if; 
  end loop;
  return l_geom;
end geom_add_offset;
/
Diese Funktion kann ich jetzt in jedes beliebige SQL-Statement einbauen.
Beispielhaft lege ich eine neue Tabelle, welche den Hochwert aller Geometrien um 100 erhöht.
create table geom_tab_with_offset as
select
  id,
  name,
  geom_add_offset(geometry, 0, 100) as geometry
from geom_tab;
Visuell dargestellt sieht das für ein Beispiel-Polygon dann ausschnittsweise so aus:
Mit recht wenig Aufwand lässt sich also die gewünschte Verschiebung direkt mittels SQL in der Datenbank vornehmen.

Donnerstag, 28. August 2014

Freitag, 23. Mai 2014

Ein GeoRaster ETL Werkzeug als grafische Oberfläche für gdal zum Laden nach SDO_GEORASTER

In meinem letzten Blog-Posting, dem 1. zum Thema Rasterdaten, hatte ich den Georaster-Viewer vorgestellt.
Für den Einstieg ins Thema und den schnellen Erfolg, ein Rasterbild in die Datenbank zu laden, war das sicher erst mal hilfreich.
Was das Laden oder Exportieren von Rasterdaten betrifft, kommt man sicher an gdal nur schwer vorbei. Daher wird die Nutzung auch schon länger von Oracle empfohlen. Allerdings braucht es doch ein wenig Übung, auf Kommandozeilenebene damit umzugehen. (Infos u.a. hier)

Eine grafische Oberfläche vom Spatial Development Team schafft Abhilfe. Diese verwendet intern gdal. Die Rede ist vom Georaster Batch ETL Werkzeug (GDAL-based GeoRaster Concurrent Batch Loading and Exporting Wizard). Dessen neueste Version kann von den Oracle Spatial and Graph Sample Code Webseiten im OTN heruntergeladen werden. Es kann sowohl für die Version 12c als auch 11g verwendet werden. Ich habe einen ersten Test mit Version 12cR1 durchgeführt.

Nach dem Download, Auspacken und Anpassen des Shell- bzw. Batch-Skripts (startGeoRasterETL.sh bzw. startGeoRasterETL.bat) kann es auch schon losgehen. Für den Einstieg hilft zudem noch ein kleines Handbuch.
Wie der Name nahelegen soll, können mehrere Rasterdaten-Files gleichzeitig geladen werden. Diese werden ausgeählt, mit den entsprechenden Ladeparameter-Werten versehen (u.a. Blocking oder Anzahl der Pyramid Levels).
Alles zusammen wird als XML-Parameterdatei gespeichert und anschließend als Job ausgeführt.
Die vier in die Tabelle CITY_IMAGES geladenen Rasterdaten-Dateien überprüfe ich dann mit dem schon bekannten GeoRaster-Viewer. Sie wurden mit den (automatisch vergebenen) RasterIDs 49−52 geladen.
Was es mit Blocking und Pyramiden auf sich hat, darüber soll es dann in einem neuen Blog-Posting gehen.

Donnerstag, 15. Mai 2014

In wenigen Schritten zu Rasterdaten in der Oracle Datenbank

Der Management von Vektordaten (SDO_GEOMETRY) ist in diesem Blog schon recht ausführlich behandelt worden. Daher möchte ich in meinem Beitrag heute zeigen, wie auf einfache Art und Weise Rasterdaten als SDO_GEORASTER geladen werden können. Voraussetzung dafür ist, dass die Oracle Database Examples von OTN heruntergeladen und installiert werden.
Relevante Links für die Datenbank-Version 12c sind:
Was finden Sie nach der Installation vor?
Im Verzeichnis %ORACLE_HOME%\md wurden der Ordner demo und weitere themenspezifische Unterordner neu angelegt. So auch einer mit dem Namen georaster.

Für die weiteren Ausführungen nutze ich die SQL-Skripte im Ordner plsql als Basis sowie den GeoRasterViewer, der im Ordner java liegt und den ich schon mal starte.

Was wird noch benötigt? Natürlich ein paar Beispiel-Bilder. Ich nutze .tif-Dateien von San Francisco mit den zugehörigen World Files (.wld).

Von der Anzeige eines Rasterbildes aus der Oracle Datenbank heraus bin ich jetzt nur noch 3 Schritte entfernt:
  1. Anlegen einer SDO_GEORASTER-Tabelle und der zugehörigen Raster Data Table(s)
  2. Initialisieren des SDO_GEORASTER Objekts (oder gleich mehrerer)
  3. Laden des Rasterbildes über den GeoRasterViewer
Das sieht dann so aus:
-------------------------------------------------------------------
-- Schritt 1: Anlegen einer SDO_GEORASTER-Tabelle.
--            Anlegen der sogenannten Raster Data Table (RDT).
--
-- Tabelle muss eine Spalte vom Typ SDO_GEORASTER enthalten.
-------------------------------------------------------------------

drop table city_images_rdt_1 cascade constraints purge
/
drop table city_images  cascade constraints purge
/
create table city_images (
  id          number primary key,
  city        varchar2(100),      
  type        varchar2(32), 
  georaster  mdsys.sdo_georaster)
/
create table city_images_rdt_1 of mdsys.sdo_raster (
  primary key (rasterId, pyramidLevel, bandBlockNumber, rowBlockNumber, columnBlockNumber))
  lob(rasterblock) store as securefiles (nocache nologging)
/

-------------------------------------------------------------------
-- Schritt 2: Initialisieren des SDO_GEORASTER Objekts.
-------------------------------------------------------------------

insert into city_images values( 
  1, 
  'San Francisco', 
  'TIFF', 
  mdsys.sdo_geor.init('CITY_IMAGES_RDT_1'))   -- RasterID wird automatisch generiert 
/                                             -- bei fehlendem 2. Parameterwert
commit
/
Für Schritt 3 wird im GeoRasterViewer eine Verbindung auf die Datenbank geöffnet mit dem Nutzer, welcher Eigentümer der zuvor angelegten Tabellen ist.
Zunächst erscheint beim Auswählen des initialisierten SDO_GEORASTER-Objekts (es hat die automatisch generierte ID 29) eine Fehlermeldung:
Das ist richtig so. Habe ich doch das Rasterbild selbst noch gar nicht geladen.
Aber ich hole das jetzt nach mit Tools > Import into DB. Bei den Ladeoptionen entscheide ich mich dafür, kein Blocking anzuwenden.
Die Bestätigung, dass das Rasterbild geladen wurde, erfolgt prompt.
Und das Ergebnis selbst sieht dann so aus:
Ggf. müssen die Daten noch mal gelesen werden über Rasters > Refresh List, damit das Rasterbild wie erwartet angezeigt wird. Aber das war es dann auch schon.
Ausführliche Hinweise finden sich wie immer in der Online Dokumentation im Oracle Technology Network. Für die Rasterdatenverwaltung mit Oracle Spatial gibt es ein eigenes Dokument (hier der Link auf die Dokumentation für Version 12.1).

Zusätzliche Hinweise:
  • Eine Besonderheit ist bei den Beispiel-Dateien ist zu beachten. ESRI WorldFiles enthalten keine Information &uunml;ber das Bezugssystem. Daher muss die SRID beim oder nach dem Laden manuell gesetzt werden. Dazu wird die Prozedur sdo_geor.setModelSRID verwendet.
  • Wie von den Vektordaten mit SDO_GEOMETRY bekannt, werden auch für SDO_GEORASTER Metadaten registriert (also nach dem Anlegen der Tabelle in Schritt 1).
  • Der in früheren Oracle Spatial Versionen (ich habe mit 12.1 getestet) manuell für jede Tabelle mit SDO_GEORASTER anzulegende DML-Trigger (sdo_geor_utl.createDMLTrigger), wird automtisch erzeugt. Dieser trägt den Präfix GRDMLTR.
  • "Tonnenweise" Rasterdaten in Oracle Spatial gibt es übrigens im Geoproxy des Freistaates Thüringen.
-------------------------------------------------------------------
-- Prozedur zum Setzen der SRID
-------------------------------------------------------------------
declare
  geor  sdo_georaster;
begin
  select georaster into geor from city_images where id = 1 for update;
  sdo_geor.setModelSRID(geor, 26943);
  update city_images set georaster = geor where id = 1;
  commit;
end;
/

-------------------------------------------------------------------
-- Metadaten prüfen
-------------------------------------------------------------------
select * from user_sdo_geor_sysdata
/

-------------------------------------------------------------------
-- SDO_GEORASTER Objekt validieren
--
-- Jeweils erwartetes Ergebnis: isvalid = TRUE
-------------------------------------------------------------------
select 
  r.id,
  mdsys.sdo_geor.validategeoraster(r.georaster) isvalid
from 
  city_images r 
order by 
  id
/

select 
  r.id,
  mdsys.sdo_geor.schemavalidate(r.georaster) isvalid
from 
  city_images r 
order by
  id
/

Montag, 12. Mai 2014

Wieviel Speicherplatz brauchen Ihre SDO_GEOMETRY-Tabellen?

In Ergänzung zu meinem ersten Blog-Posting heute, möchte ich noch kurz eine einfache Funktion zum Berechnen des allokierten Speichers hinzufügen. Diese berücksichtigt ausschließlich Tabellen-, Lob- und Index-Segmente (ist also nicht für partitionierte Tabellen anwendbar).
create or replace function alloc_space_in_mbytes(tablename in varchar2)
return number 
is
tablesize number;
begin
  select 
    sum(bytes) into tablesize
  from (
    select 
      segment_name, 
      bytes  
    from 
      user_segments                     -- Tabellensegmente             
    where  
      segment_name = tablename
    union all
    select 
      s.segment_name segment_name, 
      s.bytes bytes
    from 
      user_lobs l,                      -- Lobsegmente
      user_segments s
    where 
      l.table_name = tablename and
      s.segment_name = l.segment_name
    union all
    select 
      s.segment_name segment_name, 
      s.bytes bytes
    from 
      user_indexes i,                   -- Indexsegmente
      user_segments s
    where 
      i.table_name = tablename and
      s.segment_name = i.index_name);

  tablesize := tablesize/1024/1024;     -- Umrechnung in MB
  return tablesize;
end;
/
Der Aufruf der Funktion kann dann wie folgt aussehen:
select
  alloc_space_in_mbytes('GEOM_TABLE_UNTRIMMED') untrimmed, 
  alloc_space_in_mbytes('GEOM_TABLE_TRIMMED') trimmed
from dual
/
Für eine Testtabelle mit 218237 Polygonen, insgesamt 60754462 Stützpunkten und vorhandenem Spatial Index ergaben sich damit folgende Werte:
  • SDO_ORDINATE_ARRAY-Werte mit überwiegend 12 bis 13 Nachkommastellen: 1643.5 MB
  • SDO_ORDINATE_ARRAY-Werte gekürzt auf 5 Nachkommastellen: 1033.5 MB

Koordinatenwerte in SDO_ORDINATE_ARRAY auf sinnvolles Mass an Nachkommastellen trimmen

Kürzlich hatte ich Gelegenheit, Blick auf SDO-GEOMETRY-Daten zu werfen, die Gaus-Krüger 3 als Bezugssystem hatten. Was mir dabei auffiel, war die immens hohe Anzahl an Nachkommastellen bei den Koordinatenpaaren (Rechts- und Hochwert). Teilweise 30 Stellen und mehr.

Aus fachlicher Sicht macht das natürlich keinen Sinn. 2 oder 3 (cm, mm) Nachkommastellen sind üblich.
Auch technisch gesehen bedingen mehr Nachkommastellen sowohl mehr Speicherbedarf als auch möglicherweise negative Einflüsse auf die Performance bei Pflege und Abfragen.

Wie kann man aber nun schnell und ohne großen Aufwand, die Nachkommastellen trimmen?

Eine entsprechende Funktion in PL/SQL Package SDO_UTIL gibt es leider (noch) nicht. Das macht aber nichts. Denn der PL/SQL-Code dafür ist schnell geschrieben:

create or replace procedure trim_ordinates(
  p_geom in out nocopy sdo_geometry,
  p_prec in number default 5                -- Anzahl der Nachkommastellen
) is
begin
  for i in 1..p_geom.sdo_ordinates.count loop
    p_geom.sdo_ordinates(i) := round(p_geom.sdo_ordinates(i), p_prec);
  end loop;
end trim_ordinates;
/

create or replace function func_trim_ordinates(
  p_geom in sdo_geometry,
  p_prec in number default 2
) return sdo_geometry is
  l_geom sdo_geometry := p_geom ;
begin
  trim_ordinates(l_geom, p_prec);
  return l_geom;
end func_trim_ordinates;
/

sho err

-- Ergebnis der Funktion testen
select func_trim_ordinates(geom,3) from geom_tab;
/

-- Update durchführen
update geom_tab set geom=func_trim_ordinates(geom,3)
/
commit
/
Was spare ich ein an Speicherplatz?
Um diese Frage zu beantworten, überprüfe ich, wieviel Bytes für einen Rechts- bzw. Hochwert mit 30 Nachkommastellen benötigt werden versus einem mit 3.
select 
  vsize(5397831.164000000816421415421630849375) "Bytes_30_Nachkommastellen", 
  vsize(5397831.164) "Bytes_3_Nachkommastellen" 
from dual
/
20 Bytes werden für 30 Nachkommastellen benötigt, aber nur 7 Bytes bei 3 Nachkommastellen.
Bei einem Koordinatenpaar sind das 14 Bytes pro Stützpunkt.
Es ist also durchaus sinnvoll, sich über die notwendige Genauigkeit für die Speicherung von Geodaten Gedanken zu machen.


Mittwoch, 30. April 2014

Kleines Experiment mit POINTONSURFACE

Im Package SDO_GEOM gibt es die Funktion SDO_POINTONSURFACE. Diese ermittelt einen Punkt, der räumlich auf der Oberfläche eines Polygons liegen soll.
Aber wie wird dieser Punkt ermittelt? Welches Ergebnis ist zu erwarten?

Um diese Fragen zu beantworten, habe ich mir eine Prozedur geschrieben, welche diese Funktion mehrfach aufruft und die zurückgegebenen Punktgeometrien in eine Tabelle schreibt.
drop table points purge;

create table points (
  id number,
  geom sdo_geometry,
  constraint points_pk primary key (id) enable);

declare
  type t_points is table of points%ROWTYPE;
  l_tab t_points := t_points();
  l_size number := 10;
  l_lastid number;
  l_pointonsurface sdo_geometry;
  l_surface sdo_geometry;

begin
  -- Fetch last id from points table
  select nvl(max(id),1) + 1 into l_lastid from points;
  select s.geom into l_surface from us_state s where s.name = 'California';

  -- Populate collection
  for i in 1 .. l_size LOOP
    -- Call POINTONSURFACE
    select sdo_geom.sdo_pointonsurface(l_surface, 0.05) into l_pointonsurface from dual;
    l_tab.extend;
    l_tab(l_tab.last).id := l_lastid;
    l_tab(l_tab.last).geom := l_pointonsurface;
    l_lastid := l_lastid + 1;

  end loop;
 
 -- Ingest table with points
  forall i in l_tab.first .. l_tab.last
    insert /*+ APPEND_VALUES */ into points values l_tab(i);
  commit; 
end;
/
Schaue ich mir die 10 Sätze in der Tabelle POINTS an, finde ich immer die gleichen Punktgeometrien: Lon=-123.00111 und Lat=37.772053.
select p.geom.sdo_point.x lon, p.geom.sdo_point.y lat from points p;
Wer also die Idee hat, diese Funktion zu verwenden, um eine Tabelle mit zufälligen Punktgeometrien zu befüllen, muss einen anderen Lösungsansatz wählen. (Einen solchen Lösungsansatz habe ich in diesem Blog-Posting vorgestellt.)

Aber was ist denn jetzt das "Geheimnis" hinter SDO_POINTONSURFACE?
Die Antwort ist (einfach):
Es wird der 1. Stützpunkt der Flächengeometrie zurückgegeben, die als Eingabeparameter übergeben wird. (Das ist in meinem Beispiel der Bundesstaat Kalifornien.)
select t.x, t.y, t.id
from us_state s, table(sdo_util.getvertices(s.geom)) t
where s.name = 'California' and t.id = 1;


Nächstes Webinar von Directions Magazine: Hochperformante Abfragen auf großen Vektordatenbeständen. Anwendung des Vector Performance Accelerator als Teil von Oracle Spatial and Graph 12c

Das nächste Webinar von Directions Magazine mit Oracle-Beteiligung trägt den Titel :

"Learn How Customers Are Experiencing 300x Performance Gains with Oracle Spatial and Graph"

Hauptthema ist die immense Beschleunigung, welche bei der Prozessierung und Abfrage von großen Datenmengen (Vektordaten) erzielt werden kann durch ein einfaches Umlegen eines "Schalters" in der Oracle Datenbank. Dieser Schalter ist der Datenbank-Parameter SPATIAL_VECTOR_ACCLERATION.

Wer also um diese Zeit gerade nichts anderes vor hat, kann sich am
  • 6. Mai 2014 
  • um 20 Uhr 
online dazuschalten.

Die Registrierung erfolgt über diesen Link: http://www.directionsmag.com/webinars/register/learn-how-customers-are-experiencing-300x-performance-gains-with-oracl/390239?DM_webinars_section&utm_medium=web&utm_campaign=390239

Ich empfehle,  sich zu registrieren, auch wenn die Live-Zuschaltung zeitlich nicht möglich ist. Die Webinare werden aufgezeichnet. Der Link zur Aufzeichnung wird hinterher an alle Registrierten verschickt.

Donnerstag, 24. April 2014

Performance bei Koordinaten-Transformationen: TRANSFORM vs. TRANSFORM_LAYER

Wenn es darum geht, die Koordinaten in einer SDO_GEOMETRY-Spalte in ein anderes
Koordinatensystem umzurechnen, nutzt man SDO_CS.TRANSFORM - ein Beispiel:
create table m_admin_area4_t31467 as
select
  feature_id,
  feature_name,
  area_id,
  name_langcode,
  feature_type,
  country_code_3,
  sdo_cs.transform(geometry, 31467) as geometry
from m_admin_area4;

Tabelle wurde erstellt.

Abgelaufen: 00:06:14.40
Die Tabelle enthält knapp 14.000 Polygone - die Umrechnung dauerte etwas mehr als
6 Minuten. So weit, so gut. Die Frage wäre allerdings, ob es nicht noch schnellere
Varianten gibt - denn stellt man sich eine Tabelle mit 100.000 Polygonen vor, wären
wir schon bei einer Stunde - und so weiter und so fort.
Es ist nicht überall bekannt, dass es neben SDO_CS.TRANSFORM noch eine weitere
Funktion SDO_CS.TRANSFORM_LAYER gibt, welche eine ganze Tabelle auf einmal
umrechnet. TRANSFORM_LAYER soll lt. Dokumentation dabei effizienter arbeiten als TRANSFORM - dafür
ist der Umgang damit etwas aufwändiger. Testen wir das einmal: Die Tabelle, die
umrechnet werden soll, muss einen Eintrag in der View USER_SDO_GEOM_METADATA
haben - ein Spatial-Index dagegen kann, muss aber nicht vorhanden sein. Zuerst sollte
man dies überprüfen.
select table_name, column_name, srid 
from user_sdo_geom_metadata 
where table_name like 'M_ADMIN%'

TABLE_NAME                       COLUMN_NAME                SRID
-------------------------------- -------------------- ----------
M_ADMIN_AREA0                    GEOMETRY                   8307
M_ADMIN_AREA1                    GEOMETRY                   8307
M_ADMIN_AREA2                    GEOMETRY                   8307
M_ADMIN_AREA3                    GEOMETRY                   8307
M_ADMIN_AREA4                    GEOMETRY                   8307
:                                :                          :
Danach kann SDO_CS.TRANSFORM_LAYER ausgeführt werden.
begin
  sdo_cs.transform_layer('M_ADMIN_AREA4', 'GEOMETRY', 'M_ADMIN_AREA4_DST', 31467);
end;
/

Abgelaufen: 00:01:38.95
Das ging schon wesentlich schneller - aber wenn wir uns die Ergebnistabelle ansehen,
dann bemerken wir schnell, dass wir noch nicht ganz fertig sind.
SQL> desc M_ADMIN_AREA4_DST
 Name                                      Null?    Typ
 ----------------------------------------- -------- ----------------------------
 SDO_ROWID                                          ROWID
 GEOMETRY                                           MDSYS.SDO_GEOMETRY
Denn diese Tabelle enthält die umgerechneten Geometrie-Objekte nebst einer ROWID aus
der Quelltabelle. Wenn man nun also die "finale" Tabelle erzeugen möchte, die
aus genau den gleichen Spalten wie die Quelltabelle besteht, so braucht es einen
weiteren Schritt.
create table m_admin_area4_t31467 as
select  
  q.feature_id,
  q.feature_name,
  q.area_id,
  q.name_langcode,
  q.feature_type,
  q.country_code_3,
  i.geometry
from 
  m_admin_area4 q join m_admin_area4_dst i on (i.sdo_rowid = q.rowid)
/

Tabelle wurde erstellt.

Abgelaufen: 00:00:20.68
Diese 20 Sekunden müssen noch hinzugerechnet werden - denn erst nun ist die
gewünschte Tabelle erstellt. Es ergeben sich also etwa 2 Minuten. Verglichen mit
den 6 Minuten und 14 Sekunden ist das doch eine erhebliche Verbesserung! Der Grund dafür
sind Initialisierungen, die bei SDO_CS.TRANSFORM immer wieder und bei TRANSFORM_LAYER
nur einmal aufgerufen werden. Allerdings ist
dieser Ansatz nicht für on-the-fly Transformationen geeignet, da man stets die
"Zwischentabelle" generieren muss. Aber im Rahmen von Ladeprozessen kann man hiermit
durchaus eine Menge Zeit sparen ...

Donnerstag, 17. April 2014

2 Freikarten für das Vor-Konferenz-Programm auf dem Geospatial World Forum (5.-9. Mai in Genf)

Oracle hat vom Partner CIRB 2 Freikarten für die Sessions am 5. Mai zur Verfügung gestellt bekommen. Diese geben wir gern an Interessierte weiter.
Bei Interesse bitte eine kurze Email an Hans Viehmann schicken.
Entschlossenheit im Entscheiden und Handeln ist gefragt: Es sind nur 2 Karten.

Freitag, 28. März 2014

Koordinatensystem einer Tabelle verändern

Hin und wieder (gerade in frühen Projektphasen) kommt es vor, dass Geodaten in Tabellen mit dem falschen Koordinatensystem ausgestattet werden - Ursache kann ein falsch eingerichteter Ladeprozess sein oder schlicht eine falsche Information. Wenn nun das Koordinatensystem geändert werden soll, stellt sich die Frage, wie man das möglichst effzient und einfach machen kann - ohne alles zu löschen und neu zu laden. Hier ein Vorschlag - so gehe ich vor:

1. Spatial Index löschen

Das Koordinatensystem ist Teil des Spatial Index - ein anderes Koordinatensystem braucht einen neuen Index. Also muss der bestehende gelöscht werden.

drop index {spatial-index-name};

Index dropped.

2. Koordinatensystem in den Daten austauschen

Hierfür müssen die SDO_GEOMETRY-Daten nicht komplett neu geladen werden. Man kann sich stattdessen die Tatsache zunutze machen, dass man sich in einer Oracle-Datenbank befindet. Das Attribut SDO_SRID (welches in jedem SDO_GEOMETRY die Koordinatensystem-ID enthält) kann einfach per SQL UPDATE Kommando aktualisiert werden. Der Rest der Daten muss nicht angefasst werden (Achtung: Der Alias - hier: "a" - ist bei diesem SQL UPDATE wichtig).

update {table-name} a set a.{geometry-column}.sdo_srid = {neue SRID};

XXXX rows updated.

3. Koordinatensystem in USER_SDO_GEOM_METADATA ändern

Auch im Spatial Dictionary muss das Koordinatensystem ausgetauscht werden. Der Eintrag in USER_SDO_GEOM_METADATA muss dem in den SDO_GEOMETRY-Instanzen entsprechen.

update USER_SDO_GEOM_METADATA set SRID = {neue SRID} 
where TABLE_NAME = '{table-name}' and COLUMN_NAME = '{geometry-column}';

1 row updated.

Es kann natürlich auch sein, dass die Dimensionsinformation auch noch aktualisiert werden muss. Für Längen- und Breitengrade kann DIMINFO wie folgt versorgt werden.

update USER_SDO_GEOM_METADATA 
set DIMINFO = SDO_DIM_ARRAY(SDO_DIM_ELEMENT('X',-180,180,0.05),SDO_DIM_ELEMENT('Y',-90,90,0.05))
where TABLE_NAME = '{table-name}' and COLUMN_NAME = '{geometry-column}';

1 row updated.

4. Index neu bauen

Das sollte einfach sein ...

create index  {spatial-index-name} on {table-name} ({geometry-column})
indextype is mdsys.spatial_index;

Index created.

Mittwoch, 12. Februar 2014

Neuer Oracle Spatial Blog: Direkt vom Spatial Development Team in New Hampshire

Direkt vom Oracle Spatial Development Team wird nun auch ein Blog in englischer Sprache angeboten. Dieser wird sich natürlich mit spannenden Fragen rund um die Nutzung von Oracle Spatial and Graph auseinandersetzen.
Zu finden ist dieser hier. Einfach mal reinschauen.

Hinweise zu Postings und Wünsche für spezielle Themen können als Kommentare eingebracht werden. (Das gilt natürlich genauso für diesen Blog.)

Mittwoch, 5. Februar 2014

APEX, Geodaten und Karten: Interaktives Webseminar am 19. Februar

Die Arbeit mit Positionen und Koordinaten, also Geodaten, spielt in mehr und mehr Anwendungsgebieten eine Rolle. Die meisten empfinden die Arbeit mit Geodaten in der Oracle-Datenbank aber als eher kompliziert - doch das ist gar nicht so. In diesem interaktiven Webseminar am 19. Februar erfahrt Ihr, wie einfach es ist, mit Koordinaten in der Datenbank zu arbeiten und diese als Karte in einer APEX-Anwendung darzustellen. Die Teilnehmer des Webseminars werden also selbst eine APEX-Anwendung erstellen, mit der man ...

  • ... mit dem Smartphone aufgenommene Bilder hochladen
  • ... die Position extrahieren und als Koordinate speichern
  • ... und die Bilder schließlich auf einer Karte darstellen ...

... kann. Es wird genug Freiraum geben, dass man alle Schritte selbst auf einer eigenen Umgebung durchführen kann - und bei Bedarf kann man sich per Chat mit dem Moderator oder oder den anderen Teilnehmern austauschen.

Das Webseminar beginnt um 09:30 Uhr und wird gegen 11:30 bis 12:00 Uhr zu Ende sein. Das Meeting wird mit Webex durchgeführt - die genauen Einwahldaten werden noch bekanntgegeben. Mehr Informationen zum Webseminar finden sich auf der Anmeldeseite. Am besten also gleich anmelden.