Leopold-Franzens-Universität Innsbruck Institut für Informatik Datenbanken und Informationssysteme Evaluierung der Unterschiede von geographischen Daten in relationalen und in Graphdatenbanken Bachelor-Arbeit Roman Reinold betreut von Dipl-Ing. Nikolaus Krismer Prof. Dr. Günther Specht Innsbruck, 5. Januar 2017 Zusammenfassung Diese Bachelorarbeit befasst sich mit der Verarbeitung geographischer Daten in verschiedenen Datenbanken und dem Vergleich dabei auftretender Ausführungszeiten. Es werden Unterschiede auf Grund der Art der Datenbank erwartet. Als relationale Datenbank wird PostgreSQL mit der Erweiterung PostGIS verwendet. Dieser wird die Graphdatenbank Neo4J gegenüber gestellt. Um ein erfolgreiches Importieren in die jeweilige Datenbank zu erreichen, müssen die Daten in ein passendes Format gebracht werden. Damit die Ergebnisse vergleichbar sind, werden auf beiden Datenbanken die selben Abfragen verwendet. Es wird die Dauer vom Versenden der Anfrage bis zum Erhalten der Resultate gemessen. Im Rahmen einer Evaluierung der Ergebnisse werden die zeitlichen Unterschiede erläutert und mögliche Erklärungsversuche aufgezeigt. Abstract This bachelor project discusses the work of geographic data in various databases and the comparison of occurring execution times. The differences mainly expected due to the type of the database. As a relational database PostgreSQL is used with the extension PostGIS. Opposite to that the graph database Neo4J will take place. To guarantee a successful import into the respective databases, the data must be changed in a suitable format. In order to obtain comparable results on both databases the same queries will be used. The duration from sending the request until receiving the results will be measured. As a part of evaluating the results, the temporal differences will be illustrated and possible explanation results presented. Inhaltsverzeichnis 1 Einleitung 1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Ziel der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . 1 1 3 2 Problemstellung 2.1 Vorgehensweise . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Geografische Fragestellungen . . . . . . . . . . . . . . . . 2.3 Offene Fragestellungen . . . . . . . . . . . . . . . . . . . . 5 5 6 9 3 Technologien 3.1 PostgreSQL . . . . 3.1.1 PostGIS . . 3.1.2 PGRouting 3.2 Graphdatenbanken 3.3 Neo4J . . . . . . . 3.4 Osm2po . . . . . . 3.5 WKT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Umsetzung 4.1 Formatierung und Beschaffung der Daten . . 4.2 Import der Daten . . . . . . . . . . . . . . . . 4.2.1 Import PostGIS . . . . . . . . . . . . 4.2.2 Import Neo4j . . . . . . . . . . . . . . 4.3 Datenverarbeitung und Erstellen der Queries 4.3.1 Queries in PostGIS . . . . . . . . . . . 4.3.2 Queries in Neo4j . . . . . . . . . . . . 5 Evaluierung 5.1 Nearest Node . . . . . . 5.2 Shortest Path (Dijkstra) 5.3 Isochronenberechnung . 5.4 Neo4j versus PostGIS . . . . . . . . . 6 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 12 14 15 17 20 20 . . . . . . . 23 23 24 24 25 26 26 29 . . . . 35 36 37 38 38 41 III INHALTSVERZEICHNIS Literaturverzeichnis IV 43 Roman Reinold Kapitel 1 Einleitung 1.1 Motivation Die Entwicklung von interaktiven, geographischen Karten in Applikationen oder in Apps auf mobilen Geräten schreitet immer weiter voran. Nachdem 1991 das World Wide Web das erste mal öffentlich zugänglich war, gab es mit Xerox PARC Map Viewer 1993 schon den ersten webbasierten Mapserver. Basierend darauf wurde ein Jahr später (1994) der erste interaktive Online-Kartendienst The World Wide Earthquake Locator veröffentlicht. Mit dem 1996 erschienen Center for Advanced Spatial Technologies Interactive Mapper wurde dem Benutzer die Möglichkeit gegeben einen geographischen Bereich auszuwählen und mit verschiedenen Layer personalisierte Karten zu erstellen. Im selben Jahr wurde Mapquest, der erste Dienst mit Adressenvergleiche und Routing, herausgebracht. In den darauffolgenden Jahren wurden diverse Arten von Web Map Services verkündet bis 2004 OpenStreetMap 1 , ein unter open-source Lizenz stehender Kartendienst, gegründet wurde. Ein Jahr danach wurde von Google der bekannte Kartendienst Google Maps veröffentlicht. Dieser wurde schnell sehr beliebt, unter anderem weil es Benutzer möglich war Google Map Services in die eigene Webseite zu integrieren. Auf Grund von immer mehr Daten in Form von Häuser, Straßen oder anderen infrastrukturellen Erweiterungen dauern auch die Abfragen auf die darunterliegende Datenbank immer länger. Ebenso werden komplexere Anfragen, die vorher so nicht denkbar waren, möglich. Die Anbieter dieser Karten sind daher gefordert unter anderem die Datenbankzugriffe in der kürzestmöglichen Zeit dem Benutzer bereitzustellen. Momentan werden von den bekanntesten und größten Kartenanbietern wie zum Bei1 https://www.openstreetmap.org 1 KAPITEL 1. EINLEITUNG Abbildung 1.1: Beispielbild, Java OpenStreetMap Dezember 2015 spiel OpenStreetMap objektrelationale Datenbanken für die Anfragen verwendet 2 . Es stellt sich somit die Frage ob es nicht bessere, schnellere Arten von Datenbanken für die Verarbeitung geographischer Daten gibt. Wenn jetzt diese Daten welche für Wegberechnungen wichtig sind näher betrachtet werden, ist der Aufbau von geographischen Daten visuell als Graph vorstellbar. Wie in Abbildung 1.1 ersichtlich, können Straßen und Gebäude als Verknüpfung vieler Kanten und Knoten dargestellt werden. 2 http://blog.cleverelephant.ca/2009/04/openstreetmap-moves-to-postgresql. html 2 Roman Reinold KAPITEL 1. EINLEITUNG Da diese Graphen genau die Art und Weise wiederspiegeln wie sie in einer Graphdatenbank abgespeichert sind, wäre es naheliegend geographische Daten in solcher Datenbank abzuspeichern. Wenn es möglich wäre die Datenverarbeitung, gespeichert in einer Graphdatenbank, so zu optimieren, dass es effizienter und schneller als in relationalen Datenbanken, wäre das eine mögliche Verbesserung im Bezug auf die Performanz von Online Karten. 1.2 Ziel der Arbeit Ziel der Arbeit ist die Evaluation der Unterschiede in der Verarbeitung von geographischen Daten sowohl in einer relationalen, als auch in einer Graphdatenbank. Hierbei ist es wichtig die genauen Unterschiede bezügliche der Geschwindigkeit der Datenbankabfragen zu erkunden. Da in diesem Kapitel bereits die Motivation und die Ziele der Arbeit erläutert wurden, wird anschließend mit der Abgrenzung bzw. Problemstellung fortgefahren. Dort wird detailierte auf das gegenwärtige Problem eingegangen und präzise festgelegt welche Arbeiten in dieser Bachelorarbeit verrichtet werden. Dazu wird abgegrenzt welche Technologien, aktuelle Versionen dieser und auf welchen Systemen die Evaluierung stattfindet. In Kapitel 3 werden die verwendeten Technologien vorgestellt und kurz erläutert. Besonderes Augenmerk wird dabei auf die Wahl der Datenbanken und die dazugehörigen Algorithmen, mit welchen die Datenverarbeitung stattfinden wird, gelegt. Im Anschluss wird in Kapitel 4 auf die detailierte Umsetzung dieser Arbeit eingegangen und die Vorgehensweise geschildert. Dieses wird grundlegend in zwei Teile aufgegliedert. Im Ersten wird auf die Datenverarbeitung, zu der auch Formatkonvertierungen zählen, eingegangen und der Import in die jeweiligen Datenbanken besprochen. Im zweiten Teil werden dann die Datenbankabfragen, dazu gehörende Algorithmen und erkennbare Unterschiede präsentiert. In Kapitel 5 werden die ausgearbeiteten Ergebnisse der Bachelorarbeit aufgeführt und erklärt. Abschließend wird in Kapitel 6 noch ein kurzer Ausblick auf mögliche Weiterentwicklungen gegeben, die auf diese Arbeit aufbauen könnten. Roman Reinold 3 Kapitel 2 Problemstellung 2.1 Vorgehensweise Um die Arbeit und die dazugehörige Evaluierung nicht zu komplex zu gestalten wird diese abgegrenzt. Die Ausarbeitung der Unterschiede wird ausschließlich auf zwei Datenbanken ausgearbeitet. Einerseits wird die objektrelationale Datenbank PostgreSQL in der Version 9.5.4, andererseits die Graphdatenbank Neo4J in der Version 3.0.4 verwendet. Damit mit geografischen Daten auf diesen Datenbanken effizient gearbeitet werden kann, können bestimmte Erweiterungen bzw. Bibliotheken integriert werden. Somit gibt es für Neo4j die Library Neo4J Spatial, welche es erlaubt spezielle geografische Operationen auf Daten auszuführen. Beispiele hierfür sind spatial.intersects oder spatial.withinDistance. Genauer gesagt ist es möglich spatial indexes auf bereits vorhandene Daten hinzuzufügen und darauf geografische Funktionen wie das Suchen von Daten innerhalb eines bestimmten Bereiches oder die Distanz zwischen zwei Punkte. Für PostgreSQL ist die Erweiterung PostGIS (2.2.1) verfügbar, welche geografische Objekte und Funktionen umfasst. Zusammen bilden sie eine vollständige spatial database, im deutschsprachigen Raum auch als räumliche Datenbank bzw. Geodatenbank bezeichnet. Außerdem wird das Modul PgRouting (2.2.3) verwendet, mit dem zu einer PostGISDatenbank Funktionalitäten zur Routenplanung hinzugefügt werden können. PgRouting ermöglicht das Erstellen von Topologien und Lösen von Problemen wie das Finden des kürzesten Pfades und stellt dafür unter anderem Implementierungen des bekannten und verbreiteten DijkstraAlgorithmus zur Verfügung. Diese beiden Datenbanken stehen unter einer open-source Lizenz, sind also frei verfügbar und stellen außerdem alle benötigten Funktionen be5 KAPITEL 2. PROBLEMSTELLUNG reit um typische Abfragen auf einer Geodatenbank zu verarbeiten. Da somit zwei Vertreter unterschiedlicher Datenbank-Arten gewählt sind ist es möglich die geforderten Fragen zu beantworten ohne eine weitere Datenbank zu benötigen. Der Zugriff auf die Datenbanken erfolgt über ein Java Programm, um eine möglichst ähnliche Situation zu simulieren. Eventuelle benötigte API’s oder Frameworks werden im Laufe der Arbeit besprochen. Geografische Daten, welche für den Vergleich von Abfragen der beiden erwähnten Datenbanken importiert werden, werden von OpenStreetMap bereitgestellt. Als Evaluierungsregion werden hier Daten, welche die Stadt Innsbruck benutzt. Der Download der Karte wird von der Seite Geofabrik 1 bereitgestellt und ist eine *.osm.pbf Datei. Um die Datei in ein passendes Format für den Import in die PostgreSQL Datenbank zu bringen wird das Tool osm2po verwendet. Dieses wird in der Version 5.1.5 benutzt und kann OpenStreetMap-Daten in mehrere sql-File konvertieren. Für ein erfolgreiches Importieren in die Neo4j Datenbank werden das aus PostgreSQL exportierbare csv-File durch den csv-Importer von Cypher, der Abfragesprache von Neo4j, die Knoten und Kanten importiert und manuell zu einem Graphen zusammengefügt. 2.2 Geografische Fragestellungen Die Abfragen an die Datenbanken woraus sich dann statistische Ergebnisse evaluieren lassen, beschränken sich auf drei Hauptteile: 1. Die Distanz zwischen zwei Punkten, auch Nearest Node genannt. Diese Abfrage ist auch unter der Bezeichnung Nearest Neighbor bekannt. 1 6 download.geofabrik.de Roman Reinold KAPITEL 2. PROBLEMSTELLUNG Abbildung 2.1: Nearest Node Beispiel, Quelle: Neo4j Browser Der Startknoten kann entweder ein vorgegebener Punkt aus den OpenStreetMap Daten sein oder ein frei gewählter Punkt, welcher Breiten- und Längengrad beinhaltet. Weiters wird sich die Berechnung ausschließlich auf die Entfernung der Luftlinie zwischen den zwei Knoten beziehen. Beziehungen zwischen den Knoten spielen bei dieser Berechnung keine Rolle. In Abbildung 2.1 stellt der grüne Knoten den Startpunkt dar. Der blaue Knoten ist das Ergebnis der Nearest Node Suche und somit der näheste Punkt zum Startpunkt. Eine andere Berechnung ist Nearest Edge, die näheste Kante zu einem Punkt oder einer Kante. Dies wird in dieser Arbeit jedoch nicht behandelt. 2. Zweiter Vergleich ist der kürzeste Pfad von von einem Punkt zu einem anderen Punkt. In Englisch ist dies auch als Shortest Path Problem bekannt. Roman Reinold 7 KAPITEL 2. PROBLEMSTELLUNG Abbildung 2.2: Nearest Node Beispiel, Quelle: Neo4j Browser Mit grün und blau wird der Start- und Zielknoten gekennzeichnet. Die daraus errechnte kürsteste Lösung für die Wegfindung sind die orangen Punkte die Start und Ziel verbinden. In der Graphentheorie ist dieses Problem durch das Finden eines Pfades zwischen zwei Punkten oder Knoten sodass die Summe der Gewichte minimal ist, definiert [THC10]. Als Gewicht kann zum Beispiel die Distanz oder die benötigte Zeit zwischen diesen Knoten vorgestellt werden. In Abbildung 2.2 ist ein gerichteter Graph zu sehen, erkennbar an den Pfeilen zwischen den Knoten. Für die Berechnung wird vernachlässigt ob es sich um einen gerichteten oder ungerichteten Graphen handelt. Um das Problem des kürzesten Pfades zu lösen wird der Algorithmus von Dijkstra verwendet. 3. Abschließend wird noch eine Isochronenberechnung evaluiert. Hierfür werden in dieser Arbeit nur unimodale Isochrone berechnet. 8 Roman Reinold KAPITEL 2. PROBLEMSTELLUNG Abbildung 2.3: Nearest Node Beispiel, Quelle: Neo4j Browser Die Berechnung der Isochrone werden alle Knoten gemessen die innerhalb einer bestimmten Zeit von einem vorgegebenen Punkt aus erreichbar sind. Ähnlich dazu ist die Isodistanz, welche die Knoten beinhaltet die sich in einer gewählten Distanz einfinden lassen. In Abbildung 2.3 wird der grüne Knoten als Startpunkt gewählt. Alle innerhalb einer vorgegebenen Zeit oder Distanz erreichbaren Knoten sind mit blau gekennzeichnet. Die roten Knoten konnten demnach nicht in der gegebenen Zeit oder Distanz erreicht werden. 2.3 Offene Fragestellungen Daraus ergeben sich folgende drei Forschungsfragen: 1. Wie groß ist der Unterschied der Ausführungszeiten der Nearest Node Suche zwischen PostGIS und Neo4j? Roman Reinold 9 KAPITEL 2. PROBLEMSTELLUNG 2. Wie groß ist der Unterschied der Ausführungszeiten von Wegfindungen zwischen PostGIS und Neo4j? 3. Wie groß ist der Unterschied der Ausführungszeiten von einer Isochronenberechnung zwischen PostGIS und Neo4j? Benutzte Algorithmen wie der Algorithmus von Dijkstra werden während der Arbeit genauer unter die Lupe genommen. Als Kosten für den DijkstraAlgorithmus und auch die Isochronenberechnung werden einerseits die Höchstgeschwindigkeit der Wege benutzt. Andererseits wird konstant eine maximal erlaubte Geschwindigkeit von 5 km/h gewählt, welche das Gehen eines Fußgängers darstellen soll. Beschleunigung und Verzögerung werden in dieser Arbeit nicht berücksichtigt. Weitere Datenbankabfragen werden nicht betrachtet. Import und Testen von Daten aus anderen Karten wie beispielsweise Google Maps werden folglich in dieser Arbeit nicht benutzt. 10 Roman Reinold Kapitel 3 Technologien Im folgendem Kapitel werden die Technologien erläutert, die im Rahmen dieser Bachelorarbeit verwendet wurden. 3.1 PostgreSQL PostgreSQL ist ein objektrelationales Datenbankmanagementsystem (ORDBMS) und steht unter einer open-source Lizenz [Mom00]. Die Entwicklung begann bereits 1977 und seit 1997 wird die Software von einer Open-Source-Community weiterentwickelt [Jub15]. Heute gehört dieses DBMS zu den bedeutendsten im Open-Source Bereich und darüber hinaus. Die aktuelle Version von PostgreSQL ist 9.6.1 (Oktober 2016) und wurde im September 2016 veröffentlicht. Wie viele andere relationale Datenbanken ist PostgreSQL vollständig ACID-konform. In relationalen Datenbanken wird eine einzige logische Operation Transaktion genannt. In diesem Zusammenhang werden die ACID-Eigenschaften wie folgt beschrieben [Jub15]: • Atomarität (atomicity): Wenn ein Teil einer Transaktion scheitern, so scheitert die komplette Transaktion. • Konsistenz (consistency): Diese Eigenschaft stellt sicher, dass die Datenbank von einem konsistenten Zustand in den nächsten übergeht. • Isolation (isolation): Nebenläufige Ausführungen von Transaktionen enden in einem Datenzustand als wären sie seriell ausgeführt worden. • Dauerhaftigkeit (durability): Transaktionen die erfolgreich ausgeführt worden sind, sind persistent auch bei einem Serverausfall. Die Ausführung von Datenbankabfragen in PostgreSQL kann über mehrere Wege geschehen. Zum einen ist das Kommandozeilen-Tool psql verfüg11 KAPITEL 3. TECHNOLOGIEN bar, zum anderen werden auch graphische Benutzeroberflächen wie pgAdmin angeboten. Darüber hinaus ist es auch möglich über eine Datenbankschnittstelle von Java die Abfragen auszuführen. PostgreSQL/PostGIS JDBC Um PostgreSQL Abfragen über ein Java Programm auszuführen kann eine JDBC Verbindung 1 benutzt werden. Das Paket, das dafür benötigt wird ist java.sql.*. Zusätzlich wird ein JDBC-Driver benötigt, der als getrenntes JAR-Archiv angeboten wird. So ist es möglich sich mit Benutzername und Passwort über ein Java Programm auf die PostgreSQL Datenbank zu verbinden. Listing 3.1: PostgreSQL-JDBC-Verbindung C l a s s . forName ( ” o r g . p o s t g r e s q l . D r i v e r ” ) ; c = DriverManager . g e t C o n n e c t i o n ( ” j d b c : p o s t g r e s q l : / / l o c a l h o s t :5432/ p o s t g i s ” , ” p o s t g r e s ” , ” p o s t g r e s ”) ; Nach erfolgreichem Verbinden zu der Datenbank können die Queries als String einem Statement übergeben werden. Dieses wird dann mit executeQuery ausgeführt und das Ergebnis in einem ResultSet gespeichert. Anschließend kann über dieses ResultSet mit einer Schleife durchlaufen werden um die Ergebnisse zu erhalten. Indexes PostgreSQL unterstützt verschiedene Arten von Indexes: reguläre BBäume, Hash Indexes, Generalized Search Tree (GiST), Generalized Inverted Index (GIN) und Space-Partitioning Trees Generalized Search Tree (SP-GiST)[Hsu12]. Sollten diese unzureichend sein, besteht die Möglichkeit neue index Operatoren und Modifizierungen zu erstellen. Es können auch eigene Index Typen erstellt werden. PostgreSQL bietet ein sehr großes Angebot an Erweiterungen, darunter auch PostGIS. 3.1.1 PostGIS PostGIS ist eine Geodatenbankerweiterung für das PostgreSQL Datenbankmanagementsystem. Eine Geodatenbank ist eine Datenbank die spezielle Datentypen für geometrische Objekte definiert und es erlaubt geometrische Daten in regulären Datenbanktabellen zu speichern [Hsu14]. 1 12 https://www.postgresql.org/docs/7.4/static/jdbc.html Roman Reinold KAPITEL 3. TECHNOLOGIEN Sie bietet spezielle Funktionen und Indexes für die Verarbeitung und Abfrage der Daten mit SQL. Geometrische Funktionen PostGIS bietet über 300 Funktionen und Operationen 2 . Um eine bessere Übersicht zu haben werden diese in verschiedene Gruppen unterteilt. Fast alle Funktionen beginnen mit ST, wobei das S hier für spatial steht und das T für temporal. Beispiele für diese Funktionen sind: • ST Distance - berechnet die Distanz zwischen zwei geometrischen Punkten (der <−> Operator ist ähnlich dazu und liefert ebenso die Distanz zurück) • ST X - gibt die X Koordinate eines Punktes zurück • ST AsGeoJson - gibt eine Geometrie als GeoJSON Element zurück Indexes bei PostGIS Indexes für Geodatenbanken werden spatial index 3 genannt. Sie werden benutzt um geographische Datenbankabfragen zu optimieren. Konventionell Indextypen sind keine effiziente Benutzung für geographische Abfragen wie zum Beispiel der Berechnung einer Distanz zwischen zwei Punkten. Um in einer PostGIS Datenbank einen spatial index zu verwenden, wird USING GIST verwendet. Ohne diese Schlüsselwörter wird in einer PostgreSQL Datenbank ein B-Baum für den Index verwendet. B-Bäume können allerdings nur für Basisoperationen wie =, <, <=, >, >=, <>, BETWEEN und IN verwendet werden. Spatial Indexes bieten komplexere Vergleiche. Während ein GIST index nur die bounding box (Fläche definiert mit zwei Längen- und Breitengraden) 4 indexiert, muss der B-Baum die komplette Geometrie indexieren, was oft auch größer als die mögliche Indexierung sein kann. PostGIS ist frei zugänglich und steht unter einer open-source Lizenz names GNU (General Public License). Die erste Version wurde 2001 von Refractions Research unter der GNU General Public License veröffentlicht. Nach einigen Entwicklungsstadien kam 2005 die erste stabile Version 2 http://postgis.net/docs/reference.html http://revenant.ca/www/postgis/workshop/indexing.html 4 http://wiki.openstreetmap.org/wiki/Bounding_Box 3 Roman Reinold 13 KAPITEL 3. TECHNOLOGIEN auf den Markt. Mit 2.0 wird das seit der PostgreSQL 9.1 bestehende PostgreSQL-Extensions-System genutzt. Die aktuellste Version von PostGIS ist 2.3.1 (November 2016). Der Zugriff auf PostGIS erfolgt mit den selben Werkzeugen (psql, pgAdmin) wie bei PostgreSQL-Datenbanken. Auch vorhandene PostgreSQLSchnittstellen zu diversen Programmiersprachen können für den Zugriff benutzt werden. Beispiele sind Java/JDBC-Verbindung oder die C-Bibliothek libpg. Um eine PostgreSQL-Datenbank mit PostGIS zu erweitern kann folgende Datenbankabfrage benutzt werden. Listing 3.2: PostGIS Erweiterung in PostgreSQL CREATE EXTENSION p o s t g i s ; Geometry PostGIS erweitert PostgreSQL um die Datentypen geometry und geography. Die meisten Funktionen die mit dem PostGIS Paket eingeführt werden sind mit Geometrietypen wie points, linestrings, polygons kompatibel. PostGIS benutzt eine Tabelle names geomtry columns welche Metadaten die mit den geometrischen Spalten in Verbindung stehen in der Datenbank speichert[Hsu14]. SRID SRID steht für spatial reference identifier und wird verwendet um ein Koordinatensystem eindeutig zu spezifizieren. Dieser Identifikator ist als Integervariable verspeichert und steht mit dem Hauptschlüssel der Metatabelle spatial ref sys in Verbindung. Die spatial ref sys Tabelle beinhaltet den Namen des spatial reference system, die benötigten Parameter um auf ein anderes System zu zugreifen und von welcher Autorität das System definiert wurde[Hsu14]. 3.1.2 PGRouting PgRouting5 ist eine Open Source Erweiterung für PostGIS und PostgreSQL Geodatenbanken und bietet Algorithmen und andere geographische Funktionalitäten. Der Vorgänger pgDijkstra, geschrieben von Sylvain Pasche von Camptocamp, wurde später von Orkney erweitert und zu pgRouting umbenannt. Das Projekt wird gegenwärtig von Georepublic 6 , iMaptools 7 und einer breiten Benutzergemeinde unterstützt, 5 http://pgrouting.org/ https://georepublic.info/en/ 7 http://imaptools.com/ 6 14 Roman Reinold KAPITEL 3. TECHNOLOGIEN gewartet und weiterentwickelt. Um die PostgreSQL/PostGIS-Erweiterung in eine Datenbank zu importieren wird folgender Code benutzt. Listing 3.3: pgRouting Import in PostgreSQL CREATE EXTENSION p g r o u t i n g ; Eine Vorbedingung für pgRouting ist das Vorhandensein der PostGISErweiterung. Wenn geographische Daten in eine Datenbank geladen werden um mit pgRouting zu arbeiten sind typischerweise keine Topologie Informationen vorhanden. Unter Topologie versteht man die Beschreibung von Nachbarschaftsbeziehungen zwischen geographischen Objekten 8 . Für die Erstellung einer benutzbaren Topologie müssen die Daten als Knoten und Kanten in den Tabellen der Datenbank dargestellt sein. Um dies zu erreichen werden Daten mit Hilfsprogrammen wie unter anderemosm2po oder osm2pgrouting konvertiert. PgRouting bietet dem Benutzer eine Reihe von verschiedenen Algorithmen. Ein Beispiel für einen kürzesten Pfad“-Algorithmus wäre dijkstra. ” Auch Funktionen für eine Isochronen- und Isodistanzberechnung wie driving distance werden angeboten. 3.2 Graphdatenbanken Graphdatenbanken9 basieren auf der Graphentheorie und verwenden Graphen um stark vernetzte Informationen darzustellen und abzuspeichern. Eine Graphdatenbank besteht grundsätzlich aus Knoten, Kanten und Eigenschaften. Knoten repräsentieren Entitäten wie Menschen, Geschäfte oder Accounts. Diese sind grob gesagt das Äquivalent zu Zeilen in einer relationalen Datenbank oder ein Dokument in einer dokumentenbasierten Datenbank. Kanten, auch als Beziehungen bekannt, sind die Linien welche zwei Knoten verbindet. Diese stellen die Art der Beziehung zwischen zwei Punkten dar. Kanten können gerichtet oder ungerichtet sein. 8 http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.1.7592&rep= rep1&type=pdf 9 https://en.wikipedia.org/wiki/Graph_database Roman Reinold 15 KAPITEL 3. TECHNOLOGIEN Abbildung 3.1: Knoten und Kanten, Quelle: Neo4j-Browser Konzepte Eigenschaften sind entsprechende Informationen. Sowohl Knoten als auch Kanten können Eigenschaften, auch Properties genannt, besitzen. Hier wird auch oft von einem Property-Graphen gesprochen. Abbildung 3.2: Kanten Eigenschaften, Quelle: Neo4j-Browser Konzepte Abbildung 3.3: Knoten Eigenschaften, Quelle: Neo4j-Browser Konzepte 16 Roman Reinold KAPITEL 3. TECHNOLOGIEN Wie auch Kanten bestimmte Typen haben können (im oberen Beispiel Typ Beziehung), kann mit Labels Knoten einen bestimmten Typ zugewiesen werden. Die Kategorisierung von Knoten via Labels in einer Graphdatenbank erlaubt die Erstellung von einfachen und effizienten Subgraphen [Bru14]. Zum Beispiel kann einem Knoten das Label Person zugewiesen werden um dann Berechnungen nur mit Personen machen zu können. In Graphdatenbanken sind Pfadfindungsabfragen sehr gut geeignet, da die benutzt werden können um komplizierte Datenbankabfragen zu vereinfachen [Bru14]. Beispiele hierfür wären Breitensuche, Tiefensuche oder auch die Berechnung von kürzeste Pfade zwischen zwei Knoten. Die Art der darunterliegenden Speicherung verschiedener Graphdatenbanken variiert. Während einige ein relationales Schema benutzen und die Graphdaten in einer Tabelle speichern, benutzen andere typische NoSQL-Strukturen wie key-value“-, dokumentenbasierte Speicherung. ” Manche verwenden auch Graphen für die Speicherung. Um Daten von einer Graphdatenbank erhalten zu können werden im Vergleich zu relationalen Datenbanken andere Konzepte beziehungsweise eine neue Abfragesprache benötigt. Da es bis jetzt noch keinen Standard bezüglich der Abfrage von Graphdatenbanken gibt, wurden eine Vielzahl unterschiedlicher Abfragesprachen entwickelt. Darunter auch Cypher, welche von Neo4J entwickelt wurde. Verglichen mit relationalen Datenbanken sind Graphdatenbanken oft schneller für assoziative Datensets und sind oft näher an der Struktur von objektorientierten Applikationen. Da Graphdatenbanken keine teuren JOIN Operationen benötigen ist die Skalierbarkeit oft höher bei großen Mengen von Daten. Die momentan am meisten verbreitete und bekannteste Graphdatenbank ist Neo4j [ran16]. 3.3 Neo4J Neo4j ist eine in Java implementierte Open-Source-Graphdatenbank. Neo4j ist ACID-konform , was bedeutet dass die häufig gewünschten Eigenschaften Atomarität, Konsistenz, Isolation und Dauerhaftigkeit erfüllt sind. Sie gelten als Voraussetzung für die Verlässlichkeit von Systemen. Eine detailierte Beschreibung kann hier [Bru14] nachgelesen werden. Die Entwicklung von Neo4j hat 2003 gestartet und seit 2007 ist das Projekt öffentlich verfügbar. Die erste Version (1.0) ist im Februar 2010 erschienen. Neo4j 2.0 folge im Dezember 2013 und der aktuelle Stand der Version liegt bei 3.1 welche im September 2016 veröffentlicht wurde. Roman Reinold 17 KAPITEL 3. TECHNOLOGIEN Entwickelt wurde Neo4j von Neo Technology, einem Unternehmen mit Sitz in Schweden und der USA. Wie es für Graphdatenbanken üblich ist erfolgt die Speicherung der Daten in Form von Kanten, Knoten und Eigenschaften. Jede Kante oder jeder Knoten kann eine beliebige Anzahl von Eigenschaften besitzen. In Neo4j kann sowohl Kanten als auch Knoten ein Label zugewiesen werden, welche benutzt werden um Suchen einzugrenzen. Cypher Ein Alleinstellungsmerkmal von Neo4j ist auch die deklarative Abfragesprache Cypher. Ihre ausdrucksstarke und relativ einfache Benutzbarkeit macht Cypher für jegliche Art von Benutzer attraktiv, auch für die nicht so technischen[Bru14]. Deklarative Sprachen erlauben es einem Benutzer Abfragen zu stellen ohne der Datenbank genaue Angaben zu machen was zu tun ist. CREATE stellt eine analoge Operation zu INSERT dar, welche von SQL bekannt ist. Das typische SELECT FROM WHERE wurde vor Neo4j 2.0 mit START und MATCH realisisert. Seit der Einführung von Labels wird allesdings nur noch MATCH benötigt und START ist ein optionaler Part geworden. Um ein Ergebnis zurückzugeben wird das Schlüsselwort RETURN und die Variablen, welche ausgegeben ausgegeben werden sollen benutzt. Mit der Version 2.0 erschienenes Feature war die Integration von Indexes in Cypher, welche vorher separat unterstützt wurden. Indexes bei Neo4j Neo4j ermöglicht das Erstellen von Indexes um die Performanz von Datenbankabfragen zu verbessern. Diese Indexes können auf Eigenschaften von Knoten oder Kanten angewendet werden. Diese indexierten Spalten können dann zum Beispiel mit einem MATCH verwendet werden um die Ausführung einer Cypherabfrage zu optimieren. Die Erstellung eines Index kann mit folgendem Befehl mittels Cypher ausgeführt werden. Listing 3.4: Neo4j Index Erstellung CREATE INDEX ON :< l a b e l n a m e > (<property name >) Der : Operator bedeutet hier dass auf einen Labelname zugegriffen wird. Es besteht auch noch eine ältere Version von Indexes (legacy indexes) die vor dem Erscheinen von Neo4j 2.0 benutzt wurde. Da diese ohnehin 18 Roman Reinold KAPITEL 3. TECHNOLOGIEN schon veraltet sind und so gut wie nicht mehr benutzt werden, wird hier nicht genauer darauf eingegangen. Neo4j JDBC Es gibt die Möglichkeit Neo4j über ein Java Programm mittels einer JDBC [neo16b] Verbindung. JDBC oder Java Database Connectivity ist eine API für die Programmiersprache Java. Diese definiert den Zugriff eines Clients auf eine Datenbank und beinhaltet verschiedene Methoden um Datenbankzugriffe über Java auszuführen. Mit dieser Verbindung können Neo4j-Queries einfach in einem String gespeichert werden und dann über eine Methode run ausgeführt werden. Die Neo4j Datenbank muss vorher allerdings gestartet sein um mit Java eine Verbindung aufbauen zu können. Neo4j Java API Für die Verwendung von Neo4j wird auch eine Java API angeboten [neo16a]. Mit dieser API ist es sowohl möglich Cypher Abfragen auszuführen, oder direkt über die API 10 Datenbankabfragen zu senden. Es wird das Interface GraphDatabaseService benutzt um die Datenbank zu starten, eine Verbindung aufzubauen und Abfragen an diese zu senden. Zu den schon bekannten Funktionalitäten von Neo4j bietet diese API auch noch eine Bibliothek um über die Knoten zu traveriseren 11 (Traversal Framework ). Folgende Hauptkonzepte können benutzt werden um eine Traversierung zu ändern oder etwas hinzuzufügen. • Pathexpanders - definiert was zu traversieren ist, typischerweise die Art der Beziehung und die Beziehungsrichtung • Order - die Reihenfolge der Traversierung, depth-first oder breathfirst • Uniqueness - die Definition dass Knoten und/oder Beziehungen nur einmal durchlaufen werden • Evaluator - definiert was zurückzugeben ist und wann die Traversierung stoppen oder weiterlaufen soll • Starting nodes - der Knoten an dem die Traversierung beginnt 10 https://neo4j.com/docs/java-reference/current/javadocs/ https://neo4j.com/docs/java-reference/current/index.html# tutorial-traversal 11 Roman Reinold 19 KAPITEL 3. TECHNOLOGIEN 3.4 Osm2po Osm2po ist eine freie Software die sowohl ein converter als auch eine routing engine ist. Dieses Werkzeug kann aus OpenStreetMap erstellte xml-Dateien in SQL-Dateien umwandeln. Während osm2pgrouting, ein Tool welches OpenStreetMap-Daten in eine PostGIS Datenbank importiert, limitiert bezüglich des verfügbaren Speichers auf einem PC ist, kann osm2po auch mit sehr großen Datensets wie Europa arbeiten. Die erstellten SQL-Dateien enthalten insert-Statements welche die Daten in die Datenbank importieren und unter anderem kompatibel mit pgRouting und Quantum GIS 12 sind. Es läuft unter Windows, Unix und Mac solange eine Java Version von 6 oder höher vorhanden ist. 3.5 WKT WKT oder auch Well-Known-Text ist eine Auszeichnungssprache (engl. markup language), die dazu verwendet wird Geometrien alphanumerisch darstellen zu können. Das binäre Äquivalent die Well-Known-BinaryRepräsentation (WKB), ist eine übertragbare Repräsentation der Geometrien als eine kontinuierliche Byte-Datenkette. Beide wurden vom Open Geospatial Consotrium (OGC) definiert und in dem Standard Simple feature access spezifiziert. WKT Geometrien werden unter anderem von Funktionen von PostGIS benutzt, welche diese ins oder von der WKT Repräsentation konvertieren können um sie für Menschen lesbar zu machen. Beispiele für primitive Geometrien in der Well-Known-Text-Repräsentation sind: 12 20 http://www.qgis.org/en/site/ Roman Reinold KAPITEL 3. TECHNOLOGIEN Abbildung 3.4: Well-Known-Text Geometrien, https://en.wikipedia.org/wiki/Well-known text Roman Reinold Quelle: 21 Kapitel 4 Umsetzung In diesem Kapitel wird die Beschaffung und Formatierung der benötigten Daten erläutert, welche anschließend in die Datenbanken importiert werden. Abschließend wird in diesem Kapitel die Verarbeitung der Daten anhand von Datenbankabfragen erklärt. 4.1 Formatierung und Beschaffung der Daten Ziel ist es die benötigten Daten eines ausgewählten Bereiches, der im Falle dieser Arbeit Innsbruck ist, in ein Format zu konvertieren welches für den Import verwendet wird. Zunächst werden die Daten in Form einer Datei von der Seite download.geofabrik.de heruntergeladen. Aus den drei zu Verfügung stehenden Formaten .osm.pbf, .shp.zip und .osm.bz2 wurde das Erste gewählt. Grund dafür ist die geringere Größe der Datei. Eine weitere Begründung ist, dass der ausgewählte Konverter osm2po diesen Typ in ein sql-File für PostGIS parsen kann, welches auch kompatibel mit pgRouting ist. Anschließend wird mit dem Tool osm2po und dem unten abgebildeten Kommanodzeilenaufruf ein sql-File erstellt. Listing 4.1: Parsen der OpenStreetMap Datei in ein sql-File j a v a −Xmx512m −j a r osm2po − 5 . 1 . 5 / osm2po−c o r e −5.1.5 − s i g n e d . j a r p r e f i x=a t cmd=t j s p i n n s b r u c k . osm . pbf Hierbei wird mit einem gewöhnlichen Java-Aufruf die Datei osm2pocore-5.1.5-signed.jar ausgeführt. Der Java-Parameter -Xmx512m“ ist ” ein Java-Parameter und bedeutet, dass für diese Aktion 512 MB an Speicher reserviert werden. Alle Parameter die nach der jar-Datei aufgelistet sind, sind jene, die für osm2po benötigt werden. Um eine eindeutige 23 KAPITEL 4. UMSETZUNG Identifizierung der Dateien und Tabellen gewährleisten zu können wird hier der Präfix (prefix=at) gewählt. Der verbleibende Parameter (cmd=tjsp) spezifiziert, welche Aktion(en) osm2po auführen soll und ist als Sequenz von Einzelaktionen zu verstehen. • t - ist für das Parsen, die Validierung und das Vorbereiten der OpenStreetMap-Datei zuständig. • j - steht für das Zusammenführen der Knoten, Wege und deren Beziehungen, welche in PostGIS in Tabellenform dargestellt werden. • s - wird für die Transformierung und Erstellung der Topologie wird s benutzt. Zusätzlich gibt es noch eine Konfigurationsdatei (osm2po.config), in welche zusätzlich Einstellungen für den ParseVorgang bereitstellt. Für eine detailierte Beschreibung kann auf der Webseite von osm2po nachgelesen werden 1 . • p - wird angegeben, um diese Datei in den Vorgang mit einzubinden wird der Buchstabe p benutzt. Am Ende des Kommandozeilenaufrufes wird noch die gewünschte OpenStreetMap-Datei angegeben. Nach erfolgreicher Ausführung wird von osm2po ein, mit dem vorher übergebenen Präfix benannter Ordner erstellt, in dem alle benötigten Dateien enthalten sind. 4.2 4.2.1 Import der Daten Import PostGIS Bevor mit dem Import fortgesetzt wird ist es wichtig dass unsere PostgreSQL Datenbank die Erweiterung PostGIS enthält. PgRouting kann in dem Zuge ebenfalls der Datenbank hinzugefügt werden. Anschließend werden mit unten stehenden psql Statements die zwei Dateien at 2po vertex.sql und at 2po 4pgr.sql in die Datenbank importiert. Listing 4.2: Import der sql-Dateien in PostGIS p s q l −h l o c a l h o s t −U p o s t g i s −d p o s t g i s −q −f at / a t 2 p o v e r t e x . s q l p s q l −h l o c a l h o s t −U p o s t g i s −d p o s t g i s −q −f at / at 2po 4pgr . s q l 1 24 osm2po.de Roman Reinold KAPITEL 4. UMSETZUNG Ersteres beinhaltet hier die Knoten, die an jedem Ende eines Weges auftreten aber auch eine Spalte namens geom vertex. Die Werte in dieser Spalte repräsentieren den Längen- und Breitengrad des Punktes in einem geometrischen Format. Die zweite Datei umfasst die Wege und alle dazu benötigten Werte um damit arbeiten zu können. Dazu zählen unter anderem die OpenStreetMap ID. Als Spalten präsent sind, Anfangs- und Endpunkte der Wege, welche wiederum die Knoten darstellen. Sehr wichtig sind die Kosten (cost-Spalte) welche unter anderem für die Benutzung des Dijkstra-Algorithmus und auch für die Isochronenberechnung benötigt werden. 4.2.2 Import Neo4j Cypher, die Abfragesprache von Neo4j, bietet einen Import mit Hilfe von CSV-Dateien an. Um die Daten in dieses Format umzuwandeln wurden mit folgenden Befehlen von PostgreSQL die aktuellen Daten in der PostGIS Datenbank exportiert und in zwei csv-Dateien kopiert. Listing 4.3: Export von PostGIS in ein csv-File p o s t g i s=# \ copy ( s e l e c t ∗ from a t 2 p o 4 p g r ) TO ˜/ Downloads / e x p o r t p g s q l . c s v CSV HEADER; p o s t g i s=# \ copy ( s e l e c t ∗ from a t 2 p o v e r t e x ) TO ˜/ Downloads / e x p o r t p g s q l v e r t e x . c s v CSV HEADER; Anschließend wurde mit folgenden Cypher Befehlen der Import in die Neo4j Datenbank fortgesetzt. Listing 4.4: Import in Neo4j Datenbank via Cypher - Knoten u s i n g p e r i o d i c commit l o a d c s v with h e a d e r s from ” f i l e : / e x p o r t p g s q l v e r t e x . c s v ” a s row c r e a t e ( : node { osm id : row . osm id } ) ; Wenn sehr große Mengen von Daten importiert werden können hier die Schlüsselwörter using periodic commit benutzt werden, welche Neo4j die Anweisung geben nach einer bestimmten Anzahl von Zeilen immer wieder einen Commit zu machen. Das reduziert den Speicher Overhead der Transaktion. Standardwert ist 1000, aber es kann jede andere beliebige Ganzzahl übergeben werden. Die zwei darauffolgenden Zeilen geben an, dass eine bestimmte csv-Datei mit Header zeilenweise einer Variable zugewiesen werden. Anschließend werden mit create die Knoten erstellt, wobei die OpenStreetMap ID als Eigenschaft eines Knotens gesetzt wird. Der nachfolgende Aufruf wird für den Import der Wege/Kanten benutzt. Roman Reinold 25 KAPITEL 4. UMSETZUNG Listing 4.5: Import in Neo4j Datenbank via Cypher - Kanten u s i n g p e r i o d i c commit l o a d c s v with h e a d e r s from ” f i l e : / e x p o r t p g s q l . c s v ” a s row match ( s o u r c e : node { osm id : row . o s m s o u r c e i d } ) match ( t a r g e t : node { osm id : row . o s m t a r g e t i d } ) merge ( s o u r c e ) −[ e : edge ]−>( t a r g e t ) s e t e . osm id=row . osm id , e . osm name=row . osm name , e . km=row . km, e . kmh=row . kmh Der Unterschied zum Import der Knoten ist, dass hier mit dem Wort merge die gesuchten Anfangs- und Endpunkte mit einer Beziehung verbunden werden, welche den Weg zwischen den Knoten repräsentiert. Mit set werden einige Eigenschaften der Beziehung festgelegt. Zum Beispiel die Länge des Weges in Kilometern oder wie hoch die Höchstgeschwindigkeit in km/h ist. Wie an dem Import der Kanten ersichtlich ist, wurde das Graphennetz manuell erstellt. Jede Kante wird jeweils auf den Anfangs- und Endknoten abgebildet. Diese wurden schon beim ersten Import erstellt, so dass nun nur die Verbindung zwischen diesen erstellt werden. 4.3 4.3.1 Datenverarbeitung und Erstellen der Queries Queries in PostGIS Als erstes wurde zusätzlich zu der vorhandenen cost-Spalte eine weitere Spalte (cost2) mit unten angeführtem Statement erstellt. Listing 4.6: Erstellung der cost2 Spalte mit 5 km/h a l t e r t a b l e a t 2 p o 4 p g r add column c o s t 2 double p r e c i s i o n ; UPDATE a t 2 p o 4 p g r SET c o s t 2 =( subquery . km/ 5 ) FROM (SELECT id , km FROM a t 2 p o 4 p g r ) AS subquery WHERE a t 2 p o 4 p g r . i d=subquery . i d ; Die Werte in diesen Spalten stellen die Kosten dar um von einem Knoten zum anderen zu kommen. Die Einheit dieser Werte ist h für Stunden. In Kapitel 2 wurde besprochen, dass zwei unterschiedliche Kosten verwendet werden. Dies findet sich in der Query in Listing 4.6 wieder. 26 Roman Reinold KAPITEL 4. UMSETZUNG Nearest Node Folgendes Statment stellt eine Nearest Node Query ausgehend von einem frei gewählten Punkt mit Längen- und Breitengrad dar. Listing 4.7: Nearest Node PostGIS SELECT Find SRID ( ’ p u b l i c ’ , ’ a t 2 p o v e r t e x ’ , ’ geom vertex ’ ) AS s r i d , osm id , ST AsGeoJson ( g e o m v e r t e x ) AS n e a r e s t n o d e , ST AsGeoJson ( q u e r y P o i n t ) AS s t a r t p o i n t , ST Di st anc e ( g e o m v e r t e x : : geography , q u e r y P o i n t : : geography , t r u e ) FROM a t 2 p o v e r t e x , (SELECT ST GeomFromText ( ’POINT( 1 1 . 4 0 5 0 5 7 4 7 . 2 6 1 6 8 0 ) ’ , 4 3 2 6 ) AS q u e r y P o i n t ) AS a ORDER BY g e o m v e r t e x <−> q u e r y P o i n t ASC LIMIT 1 ; Am Anfang der Query wird mit Find SRID die SRID zurückgegeben. Die Definition dieser SRIDs wird durch das Open Geospatial Consortium (kurz OGC) verwaltet, eine nichtstaatliche Freiwilligenorganisation. 2 Als Startpunkt wird ein Punkt mit den Koordinaten (11.405057 47.261680) gewählt. Dieser wird zuerst mit POINT als WKT-Repräsentation3 erstellt. Da PostGIS aber mit Geometrien arbeitet, muss der Punkt erst mit ST GeomFromText in eine ST Geometry umgewandelt werden. Um diesen Schritt nicht immer wieder machen zu müssen, wurde das Ergebnis in der Variable queryPoint gespeichert. Anschließend wird von diesem Punkt mit der Funktion ST Distance zu jedem anderen Punkt in der Tabelle at 2po vertex die Distanz ausgerechnet und aufsteigend nach der Distanz sortiert. Die Symbole <−> haben eine ähnliche Bedeutung wie ST Distance und berechnen die Distanz zwei Punkten. Da ST Distance mit Parameter vom Typ geometry das Ergebnis in diesem Fall in Grad liefert, werden die Knoten vorher nach geography gecastet werden um die Distanz in Meter zu erhalten. Mit LIMIT 1 wird nur der näheste Knoten zurückgegeben, da die anderen nicht benötigt werden. Um den Startpunkt und den dazu nähesten Punkt in einem repräsentatiblen Format geliefert zu bekommen, werden mit ST AsGeoJson JSON-Objekte 4 aus den zwei Punkten erzeugt. 2 https://de.wikipedia.org/wiki/Open_Geospatial_Consortium https://en.wikipedia.org/wiki/Well-known_text 4 https://en.wikipedia.org/wiki/JSON 3 Roman Reinold 27 KAPITEL 4. UMSETZUNG Wegfindung/Shortest Path Dijkstra Für die Wegfindung zwischen zwei Punkten wird hier der DijkstraAlgorithmus verwendet. Da pgRouting schon einen vordefinierten Dijkstra 5 anbietet, war es nicht nötig diesen selbst zu implementieren. Listing 4.8: Shortest Path Dijkstra SELECT seq , i d 1 AS node , i d 2 AS edge , d i . c o s t , km, kmh FROM p g r d i j k s t r a ( ’ SELECT id , s o u r c e , t a r g e t , c o s t FROM a t 2 p o 4 p g r ’ , 5 0 , 1 0 , f a l s e , f a l s e ) AS d i JOIN a t 2 p o 4 p g r ON d i . i d 2 = at 2po 4pgr . id ; Diese Dijkstra-Implementierung benötigt als Eingabeparameter erstmals eine andere SQL-Query, welche die Spalten der Kanten, Anfangs- und Endpunkte jener Kanten als auch der Kosten definiert. Die weiteren Parameter des Algoritmus’s sind der gewählte Start- und Zielpunkt und zwei boolsche Werte für directed und has rcost. Der Wert von directed sagt aus, ob die Graphen gerichtet sind oder nicht. has rcost würde benötigt werden, falls in der Query vorher als letzter optionaler Parameter die Reverse Cost mitgegeben wurde, welche das Inverse zur Cost ist. Da beides in diesem Fall nicht gebraucht wird, wurden sie auf false gesetzt. Die Rückgabewerte des Dijkstra-Algorithmus von pgRouting bestehen aus vier Spalten. seq welche einfach von 0 beginnend eine Sequenznummer zählt. id1 beinhaltet die ID der Knoten und id2 die der Kanten. Zuletzt wird noch die cost Tabelle zurückgegeben, welche die Kosten, die schon als Eingabeparameter übergeben wurden, beinhaltet. Da auch die Tabellen in der die Länge der Wege und die maximale Geschwindigkeit interessant sind wurde das Ergebnis mit der selben Tabelle gejoined. Isochronenberechnung Für die isochrone Wegfindung wurde ein Algorithmus von pgRouting verwendet: pgr drivingDistance 6 . Listing 4.9: Wegfindung isochrone 5 http://docs.pgrouting.org/v2.1.0-beta/src/dijkstra/doc/dijkstra_v2. html 6 http://docs.pgrouting.org/2.0/en/src/driving_distance/doc/dd_ driving_distance.html 28 Roman Reinold KAPITEL 4. UMSETZUNG SELECT seq , i d 1 AS node , i d 2 AS edge , ( d i . c o s t ∗ 3 6 0 0 ) AS c o s t i n s e c , (km∗ 1 0 0 0 ) AS meter FROM p g r d r i v i n g D i s t a n c e ( ’ SELECT i d AS id , s o u r c e : : i n t 4 AS s o u r c e , t a r g e t : : i n t 4 AS t a r g e t , c o s t 2 : : f l o a t 8 AS c o s t FROM a t 2 p o 4 p g r ’ , 5 , ( 1 2 0 / 3 6 0 0 : : f l o a t ) , f a l s e , f a l s e ) AS d i JOIN a t 2 p o 4 p g r ON d i . i d 2 = at 2po 4pgr . id ; Diese Funktion führt einen Dijkstra-Algorithmus aus und benutzt die Kosten, um jeden Knoten im Netzwerk (ausgehend vom Startknoten) zu erreichen. Der einzige Unterschied bezüglich der Signatur dieser Funktion verglichen mit dem prg dijkstra ist, dass anstatt dem Zielpunkt ein Wert für die maximalen Kosten benutzt werden. In diesem konkreten Beispiel ist das 2 Minuten oder auch 120 Sekunden. Auch die Spalten mit den Rückgabewerten (seq, id1, id2, cost) sind dieselben wie bei dem Dijkstra-Algorithmus aus Listing 4.8. 4.3.2 Queries in Neo4j Wie in PostGIS wurde auch in Neo4j eine cost2 -Spalte mit einer konstanten Geschwindigkeit von 5 km/h erstellt um einen Fußgänger darstellen zu können. Listing 4.10: Nearest Node u s i n g p e r i o d i c commit l o a d c s v with h e a d e r s from ” f i l e : / e x p o r t p g s q l . c s v ” a s row match ( ) −[ e : edge {km : row . km, kmh : row . kmh}] −() s e t e . c o s t 2=e . km/ t o F l o a t ( 5 ) Hier wurde zunächst auf die Kante mit den gegebenen km und kmh Eigenschaften gematched und dann das Attribut cost2 gesetzt. Nearest Node Der in Listing 4.11 stehende Code stellt eine Nearest-Node Query ausgehend von einem frei gewähltem Punkt in Neo4j dar. Listing 4.11: Nearest Node match ( n : node ) Roman Reinold 29 KAPITEL 4. UMSETZUNG with min ( d i s t a n c e ( p o i n t ( n ) , p o i n t ( { l a t i t u d e : 4 7 . 2 6 1 6 8 0 , l o n g i t u d e : 1 1 . 4 0 5 0 5 7 } ) ) ) a s mini match ( n : node ) where d i s t a n c e ( p o i n t ( n ) , p o i n t ( { l a t i t u d e : 4 7 . 2 6 1 6 8 0 , l o n g i t u d e : 1 1 . 4 0 5 0 5 7 } ) ) = mini r e t u r n mini a s d i s t a n c e , n a s n e a r e s t N o d e Anfangs werden geographische Punkte mit der Funktion point von den gewählten Koordinaten (11.405057 47.261680) und allen anderen Knoten in der Datenbank erstellt. Geographische Punkte können nur dann erstellt werden wenn entweder ein Knoten die Eigenschaften longitude und latitude als Gleitkommazahlen beinhaltet oder jene direkt als Werte der point Funktion übergeben werden. Die Umwandlung in diese Punkte wird benötigt, weil die distance Funktion nur mit diesen arbeiten kann. Diese Funktion berechnet in diesem Beispiel alle Distanzen zwischen dem gegebenen Punkt und allen anderen in dem Netzwerk. Mit min wird dann nur der kleinste Wert dieser Distanzen zurückgegeben. Da nur die kleinste Distanz vorhanden ist und nicht welcher Knoten zu dieser gehört, muss diese jetzt nochmal mit allen anderen verglichen werden um den richtigen Knoten zu finden. Wegfindung/Shortest Path Dijkstra Für die Wegfindung in Neo4j wurde eine externe Bibliothek benutzt um auch hier eine Dijkstra Wegsuche mit Cypher ausführen zu können. Die Bibliothek APOC 7 (Awesome Procedures On Cypher) wurde entwickelt, damit in Neo4j mehrere Prozeduren bezüglich Datenintegration, Graphalgorithmen und Datenumwandlung verfügbar sind und ist im Rahmen einer open-source Lizenz auf github erhältlich. Listing 4.12: Shortest Path Dijkstra match ( s t a r t P o i n t : node { i d g i s : ’ 5 0 ’ } ) , ( endPoint : node { i d g i s : ’ 1 0 ’ } ) CALL apoc . a l g o . d i j k s t r a ( s t a r t P o i n t , endPoint , ’ edge ’ , ’ c o s t ’ ) YIELD path , w e i g h t r e t u r n path , w e i g h t Um bei dieser Implementierung die benötigten Parameter angeben zu können, müssen zuerst der Start- und Endpunkt gesucht werden. Der Aufruf einer externen Funktion über Cypher wird mit dem Schlüsselwort CALL bewerkstelligt. Die Übergabeparameter des Dijkstra-Algorithmus sind hier Startpunkt, Endpunkt, die Art der Beziehung zwischen den Punkten (edge in diesem 7 30 https://github.com/neo4j-contrib/neo4j-apoc-procedures Roman Reinold KAPITEL 4. UMSETZUNG Fall) und die Eigenschaft, welche die Kosten darstellt. Die Rückgabewerte, die der kürzeste Pfad und die zusammengefassten Kosten sind, werden dann mit YIELD den Variablen path und weight zugewiesen und schlussendlich ausgegeben. Da die Java API von Neo4j eine Version des Dijkstra Algorithmus enthält, wurde diese ebenso getestet. Folgender Code ist äqivalent zum vorherigen Beispiel mit der Cypher Realisierung. Listing 4.13: Shortest Path Dijkstra / Java API Node s t a r t = graphDB . findNode ( La be l . l a b e l ( ” node ” ) , ” id gis ” , startPoint ) ; Node end = graphDB . findNode ( La be l . l a b e l ( ” node ” ) , ” i d g i s ” , endPoint ) ; D i j k s t r a a l g o = new D i j k s t r a ( PathExpanders . allTypesAndDirections () , CommonEvaluators . doubleCostEvaluator ( cost ) ) ; Path path = a l g o . f i n d S i n g l e P a t h ( s t a r t , end ) ; Die ersten beiden Zeilen sind notwendig um den Start- und Endpunkt zu finden. Danach wird die Dijkstra Ausführung definiert. Mit PathExpanders.allTypesAndDirections() werden alle Typen und Richtungen erlaubt. Für die Evaluierung werden die Kosten verwendet. Letzte Zeile führt den Algorithmus schlussendlich aus. Isochronenberechnung Für die Isochronenberechnung wurde zuerst eine Realisierung mittels Cypher angegangen. Folgender Code repräsentiert diese Herangehensweise. Listing 4.14: Wegfindung isochrone match ( n : node ) where n . i d g i s = ’5 ’ with n match path=(n ) −[∗] −( e ) with e , min ( r e d u c e ( c o s t =0.0 , r IN r e l s ( path ) | c o s t + toFloat ( r . cost2 ) ∗3600) ) as c o s t where c o s t < 300 return cost , c o l l e c t ( e ) as i s o c h r o n e s o r d e r by c o s t Als erstes wird hier der Startknoten gewählt und gesucht. Danach werden alle möglichen Pfade vom Startknoten zu jedem anderen Knoten gesucht. Die reduce Funktion von Cypher evaluiert den Ausdruck für jedes Roman Reinold 31 KAPITEL 4. UMSETZUNG Element einer Liste und akkumuliert sie. In diesem konkreten Beispiel werden für jeden Pfad r in dem vorher gesuchten Pfad die Kosten der einzelnen Beziehungen zusammengezählt und in einer cost Variable gespeichert. Mit min wird für jeden möglichen Pfad zu einem bestimmten Knoten nur der kürzeste gewählt. Danach werden alle Pfade genommen die unter drei Minuten (300 Sekunden) liegen und zurückgegeben. Das Problem bei dieser Implementierung der Isochronenberechnung ist die 3. Zeile, welche alle möglichen Pfade berechnen muss. Bei einer Datenbank mit über 10000 Knoten würde das viel zu lange dauern. Aus diesem Grund könnte mit folgender Zeile ein Maximum von Beziehungen (0 bis 5 Beziehungen in folgendem Beispiel) für jeden Pfad festlegen, was aber nicht mehr eine Isochronenberechnung darstellen würde, da es einen Pfad geben könnte der mehr Beziehungen hätte und trotzdem in einer gewählten Zeit zu finden ist. match path=(n ) − [ ∗ 0 . . 5 ] − ( e ) Da für dieses Problem mit Cypher keine performante Lösung gefunden wurde, wurde die Neo4j Java API benutzt. Mit Hilfe dieser API wurde eine optimierte Berechnung für die Isochronenberechnung, wie unten abgebildet, gefunden. Node s t a r t N o d e = graphDB . findNode ( La be l . l a b e l ( ” node ”) , ” i d g i s ” , ”50”) ; String cost = ” cost2 ”; d o u b l e maxCost = 3 0 0 . 0 ; T r a v e r s a l D e s c r i p t i o n t = graphDB . traversalDescription () . breadthFirst () . evaluator ( Evaluators . excludeStartPosition () ) . e v a l u a t o r ( new CustomEvaluator ( maxCost , c o s t ) ) ; Traverser r e s u l t = t . t r a v e r s e ( startNode ) ; Der erste Schritt ist, wie in den vorherigen Beispielen auch die Suche nach dem Startknoten. Anschließend wie die cost2 Spalte definiert und eine maximale Zeitspanne von 300 Sekunden festgelegt. Bei der TraversalDescription wurde festgelegt, dass eine Breitensuche für das Traversieren benutzt werden soll. Weiters wird die Startposition nicht mit in die Lösung aufgenommen, da diese bei einer Isochronenberechnung nicht benötigt wird. Zuletzt wurde für das Stoppen der Traversierung ein eigener Evaluator geschrieben. Dieser erhält als Eingabewerte die 32 Roman Reinold KAPITEL 4. UMSETZUNG maximale Anzahl der Kosten die erreicht werden sollen und den Namen der Kostenspalte. Bei jeder Ankunft eines Konten werden die Kosten der letzten Beziehung zu den vorherigen dazu gezählt und überprüft ob es noch unter dem maximalen Wert ist. Ansonsten stoppt dieser die Traversierung und gibt die traversierten Pfade zurück. Roman Reinold 33 Kapitel 5 Evaluierung Dieses Kapitel beschreibt und erklärt die Ergebnisse. Die Tests wurden auf einem Fedora 24 (64-bit Version) Betriebssystem durchgeführt. Die Hardware ist ein Intel Core i5-3570 CPU mit 4 x 3.4 GHz, 8 GB RAM(Corsair XMS3), HDD Festplatte (Seagate Barracuda 7200 1000GB SATA 6Gb/s). Das empfohlene Tool JUnit-Benchmark1 konnte aufgrund unzureichender Genauigkeit nicht für die Evaluierung verwendet werden. Es misst nur in den Millisekundenbereich. Für diese Arbeit ist aber eine Messung in den Nanosekundenbereich erforderlich. Deshalb ist das Benchmarking mit Java selbst implementiert wurden. Es wurde jede Datenbankabfrage 10000 mal durchgeführt. Die ersten 20 sind Warm-Ups (Aufwärmdurchläufe, die das Laden von Klassen, Variablen und andere Initialisierungen durchführen) und werden somit nicht in die Evaluierung mit einfließen. Von den restlichen Ausführungszeiten wurde der Median berechnet. Für jede Abfrage wurde jeweils ein neuer zufälliger Punkt innerhalb von Innsbruck gewählt. Hierfür wurden zuerst zufällige Punkte via Längen- und Breitengrade erstellt. Anschließend wurde von allen Punkten in der Datenbank mit ST ConvexHull ein Polygon von Innsbruck dargestellt. Abschließend wurde mit ST Within geprüft ob der zufällige Punkt innerhalb dieses Polygons liegt oder nicht. Nur Punkte die innerhalb liegen wurden für die Evaluierung benutzt. Für die Suche nach dem kürzesten Pfad zwischen zwei Knoten und die Isochronenberechnung wird von einem zufälligen Punkt aus zuerst der näheste Punkt in der Datenbank gesucht und dieser dann für die Evaluierung benutzt. Somit ist die Zeit bzw. der Weg zwischen dem zufälligen Punkt und dem nähesten in der Datenbank nicht mitberechnet. 1 http://labs.carrotsearch.com/junit-benchmarks-tutorial.html 35 KAPITEL 5. EVALUIERUNG 5.1 Nearest Node Zuerst ist getestet worden ob sich Distanz zwischen Neo4j und PostGIS unterscheidet. Tabelle 5.1: Nearest Node Tabelle mit fixem Startpunkt und Distanz Startknoten (11.405057 47.261680) (42.965112 83.984310) (102.965112 103.984310) Distanz PostGIS 21.629 m 4202367.569 m 5003314.791 m Distanz Neo4j 21.613 m 4188183.630 m 4906404.384 m Wie zu erkennen ist, ergeben die beiden Funktionen für die Suche des nähesten Knoten nicht die selbe Distanz. Dies lässt sich auf eine unterschiedliche Berechnung zurückführen. Neo4j rechnet auf einer Sphäre und benutzt einen Radius von Radius 6378137. Die Berechnung von PostGIS benutzt eine erdähnliche Form und kommt daher auf einen etwas anderen Wert. Daraus ist zu schließen, dass die Berechnung von PostGIS etwas präziser ist als die von Neo4j. Ob das einen Unterschied auf die Ausführungszeiten der Queries nach sich zieht ist nicht trivial ermittelbar und wurde deshalb nicht näher untersucht. Tabelle 5.2: Nearest Node Tabelle ohne Index Neo4j (JDBC-Cypher) 0.206 ms PostGIS (JDBC) 59.061 ms Neo4j ist bei der Ausführung ohne Indexes schneller als PostGIS. Tabelle 5.3: Nearest Node Tabelle mit Index Neo4j (JDBC-Cypher) 0.208 ms PostGIS (JDBC) 0.566 ms Bei Neo4j wurde jeweils ein Index auf die Eigenschaften longitude und latitude bei den Knoten erstellt. Diese beiden Eigenschaften werden benötigt, um einen Punkt (point()) daraus zu machen. Wie ersichtlich ist, macht es bei Neo4j kaum einen Unterschied ob hier ein Index benutzt wird. Bei PostGIS wurde ein GIST-Index auf die Spalte geom vertex in der Tabelle at 2po vertex gelegt. Damit hat sich die Ausführungszeit enorm verringert. Grund dafür ist, dass PostGIS diese Daten intern nun als Baum darstellt und so die Suche bei geographischen Daten sehr viel 36 Roman Reinold KAPITEL 5. EVALUIERUNG schneller erfolgen kann. 5.2 Shortest Path (Dijkstra) Tabelle 5.4: Dijkstra Tabelle ohne Index Neo4j (JDBC-Cypher) 0.200 ms 0.144 ms Neo4j (Java API) 31.523 ms 36.269 ms PostGIS (JDBC) 16.826 ms 16.865 ms Geschwindigkeit max. 5 km/h Bei der Ausführung vom Dijkstra Algorithmus ist die Cypher-Variante von Neo4j über JDBC deutlich die mit der kürzesten Ausführungszeit. Tabelle 5.5: Dijkstra Tabelle mit Index Neo4j (JDBC-Cypher) 0.160 ms 0.146 ms Neo4j (Java API) 31.523 ms 36.269 ms PostGIS (JDBC) 16.826 ms 16.865 ms Geschwindigkeit max. 5 km/h Wenn bei Neo4j einen Index auf die Eigenschaft id gis gelegt wird, wäre die Suche nach den Knoten schneller wenn bestimmte Knoten benutzt werden würden. Da aber die Knoten mit der Nearest Node Query gesucht werden kann hier keine Verbesserung erzielt werden. Bei der reinen Ausführung vom Dijkstra Algorithmus kann mit Indexes auch keine Verkürzung der Zeit erreicht werden. Bei PostGIS werden keine Spalten benutzt auf die ein GIST-Index gelegt werden könnte, somit ändert sich auch hier nichts bezüglich der Ausführungszeit. Roman Reinold 37 KAPITEL 5. EVALUIERUNG 5.3 Isochronenberechnung Tabelle 5.6: Isochrone Wegsuche ohne Index max Zeit 300 sec 300 sec 900 sec 900 sec Geschw 5 km/h max 5 km/h max Neo4j (Java API) 0.0145 ms 0.0148 ms 0.0149 ms 0.0146 ms Neo4j (JDBC) - PostGIS 16.477 ms 16.576 ms 16.711 ms 24.937 ms Wie in Tabelle 5.5 zu erkennen ist, liegt Neo4j mit dem Traversier Framework weit vor PostGIS. Da die Cypher Variante von Neo4j erst alle möglichen Pfade in der ganzen Datenbank berechnet und erst nachher anhand der Kosten die richtigen zurück gibt war es in absehbarer Zeit nicht möglich ein Ergebnis der Ausführungszeit zu erhalten. Daher fehlen die Werte für Neo4J(JDBC) in Tabelle 5.6. Bei der isochronen Wegsuche wurde bei Neo4j versucht Indexes auf diverse Eigenschaften zu legen. Es konnte jedoch bei der Traversierung keine Verbesserung erzielt werden. Bei PostGIS werden keine Spalten benutzt auf die ein GIST-Index gelegt werden könnte, somit konnte hier keine Optimierung der Ausführungszeit erreicht werden. 5.4 Neo4j versus PostGIS In diesem Abschnitt werden nochmal die Unterschiede der Evaluierungen zwischen Neo4j und PostGIS durch gegangen. Wie aus den Ergebnissen der Datenbankabfragen zu sehen ist sind Graphdatenbanken bei Abfragen die mit Traversieren gelöst werden können, schneller. Abfragen die das Durchgehen eines Pfades beinhalten, sind somit gut geeignet für Graphdatenbanken. Aktionen die bei Neo4j verhältnismäßig viel Zeit kosten, sind das Suchen von bestimmten Knoten oder Kanten. Da diese bei relationalen Datenbanken als Tabelle dargestellt werden, sind diese Datenbanken bei derartigen Suchen schneller. Bei Abfragen, bei denen PostGIS eine Spalte benutzt, auf die ein GISTIndex gelegt werden kann, ist es möglich die Dauer der Ausführung stark zu reduzieren und sogar schneller als Neo4j zu sein. Gewöhnliche Indexes hingegen haben bei relationalen Datenbanken wenig bis gar keinen 38 Roman Reinold KAPITEL 5. EVALUIERUNG Einfluss wenn dabei geographische Daten verarbeitet werden. Unabhängig von unterschiedlichen Ausführungszeiten haben sowohl Neo4j als auch PostGIS einiges an Hilfe anzubieten, um die Realisierung dieser Abfragen zu erleichtern. Neo4j bietet verschiedene Wege wie Cypher oder API’s um Queries auszuführen. Weiters gibt es hilfreiche Bibliotheken wie die APOC-Bibliothek, welche eine Reihe von Funktionalitäten bereitstellt. PostgreSQL bietet mir PostGIS und Pgrouting sehr viele verschiedene Algorithmen und Funktionen. Roman Reinold 39 Kapitel 6 Ausblick Ziel dieser Arbeit war es die Unterschiede im Hinblick der Ausführungszeit der Queries zu evaluieren. Nach Testen der Datenbankabfragen wurden die Ergebnisse verglichen und interessante Resultate gefunden. Somit wurden auch Antworten auf die in Kapitel 2 aufgezeigten Forschungsfragen gefunden: 1. Wie groß ist der Unterschied der Ausführungszeiten der Nearest Node Suche zwischen PostGIS und Neo4j? Nach dem Erstellen von einem spatial Index in PostGIS kommt mit der Ausführungszeit sehr nahe an Neo4j heran. Trotzdem ist Neo4j mit etwa 0.2 ms drei mal so schnell als PostGIS mit 0.6 ms. 2. Wie groß ist der Unterschied der Ausführungszeiten von Wegfindungen zwischen PostGIS und Neo4j? Der Unterschied von 0.2 ms (Neo4j JDBC) zu 17 ms (PostGIS) ist schon etwas größer. Leider gibt es mit pgRouting nicht die Möglichkeit Spalten mit einem spatial Index zu verwenden. Die Neo4j API hingegen ist mit 35 ms schon deutlich langsamer. 3. Wie groß ist der Unterschied der Ausführungszeiten von einer Isochronenberechnung zwischen PostGIS und Neo4j? Bei Neo4j war es mit Cypher nicht möglich eine Isochronenberechnung zu implementieren die in realistischer Zeit auszuführen ist. PostGIS ist mit 16 ms schon deutlich schneller. Wenn das Traversal Framework der Neo4j API benutzt wird, werden sehr schnelle Ausführungszeiten von 0.014 ms erreicht. Aufbauend auf dieser Arbeit könnten noch einige Punkte thematisiert 41 KAPITEL 6. AUSBLICK werden. Es wurde kein besonderes Augenmerk auf die Optimierung der Queries gelegt. Wie sich in der Arbeit herausstellte, hilft die Verwendung von Spatial Indexes bei PostGIS enorm dabei die Ausführungszeit zu reduzieren. So ein Index wurde jedoch nur bei der Suche des nähesten Knotens verwendet. Grund dafür ist, dass für die Suche des kürzesten Pfades und der Isochronenberechnung Funktionen der PostGIS-Erweiterung PgRouting verwendet wurden. Diese Funktionen benutzen aber nur normale Spalten. GIST-Indexes können nur auf Spalten gelegt werden welche Daten in einem geographischen Format beinhalten. Daher konnte bei diesen Queries nicht der Vorteil von diesen Indexes benutzt werden. Ein offener Aspekt ist, Funktionen für diese Probleme zu implementieren, die derartige Spalten benutzen. Es ist somit sehr wahrscheinlich, dass diese Methoden eine stark reduzierte Ausführungszeit hervorbringen würden. Ebenso interessant wäre es bei Neo4j eine Lösung für die Isochronenberechnung mittels Cypher zu finden, die anhand der Ausführungszeit mit PostGIS mithalten kann. Eine Möglichkeit ist es die Evaluierung mit der aktuellen Neo4j Version 3.2 oder zukünftige Versionen durchzuführen. 42 Roman Reinold Literaturverzeichnis [Bru14] R. V. Bruggen: Learning Neo4j, Packt Publishing, 2014. [Cor14] P. Corti: PostGIS Cookbook, Packt Publishing Ltd., 2014. [Hsu12] L. Hsu: PostgreSQL Up and Running, O’Reilly Media, 2012. [Hsu14] L. Hsu: PostGIS in Action, Manning Publications, 2014. [Jor14] G. Jordan: Practical Neo4j, Apress, 2014. [Jub15] S. Juba: Learning PostgreSQL, Packt Publishing Ltd., 2015. [Mom00] B. Momjian: PostgreSQL Introduction and Concepts, Pearson Education, 2000. [neo16a] The Neo4j Java Developer Reference v3.0, https://neo4j.com/docs/java-reference/current/index.html, 2016, zuletzt besucht am 13.12.2016. [neo16b] Using Neo4j from Java, https://neo4j.com/developer/java/, 2016, zuletzt besucht am 13.12.2016. [osm16] Osm2po, http://osm2po.de/, 2016, zuletzt besucht am 13.12.2016. [pgr16] pgRouting, http://pgrouting.org/, 2016, zuletzt besucht am 13.12.2016. [ran16] DB-Engines Ranking of Graph DBMS, http://dbengines.com/en/ranking/graph+dbms, 2016, zuletzt besucht am 13.12.2016. [THC10] R. L. R. C. S. Thomas H. Cormen, Charles E. Leiserson: Introduction to Algorithms, 2010. [Vuk14] A. Vukotic: Neo4j in Action, Manning Publications, 2014. 43