H2 Evolution - Fensterfunktionen, CTE, JSON / XML in einer eingebetteten Datenbank

Es gibt Open-Source-Projekte wie PostgreSQL / Elasticsearch, die sich zu einem kommerziell erfolgreichen Mainstream entwickelt haben. Andere, zum Beispiel RethinkDB, haben den Markt verloren und die Entwicklung gestoppt. Und das H2-Datenbankprojekt einer in Java geschriebenen eingebetteten Datenbank entwickelt sich und lebt in seiner Nische.


Um die Funktionalität von SonarQube, Jira, Confluence zu demonstrieren, wird beim ersten Start die H2-Datenbank verwendet. H2 ist die Basis für die Ausführung von SQL-Tests im Speicher in fast jedem JVM-Projekt. Es gibt ein Beispiel für eine Anwendung, die den Benutzern weniger bekannt ist - dies ist die Verwendung von H2 in einem verteilten ignite-sql und dies ist bereits ein produktionsfertiges Skript für die Verwendung einer eingebetteten Datenbank als Teil einer anderen Lösung. Vor weniger als einem Monat wurde die Version 1.4.199 veröffentlicht, in der Sie jetzt ziemlich komplexe SQL-Abfragen schreiben können.

In Projekten habe ich mich nie auf H2 als vollständige Datenbank mit dem Speichern von Daten auf der Festplatte verlassen. Eher als Modul zum Transformieren von Daten im JVM-Speicher mit guter SQL-Unterstützung. Für diese Anwendung war sie jedoch durch das Fehlen von Fensterfunktionen stark eingeschränkt. Und jetzt, nach mehr als einem halben Jahr seit Beginn der Entwicklung der Funktion , hat H2database SQLite eingeholt. Und das ist dem großen Verdienst von Jewgeni Rjasanow aus Irkutsk zu verdanken - ich habe bei gemeinnützigen Open-Source-Projekten noch nie ein solches Entwicklungstempo wie zuvor gesehen. Außerdem erscheinen regelmäßig Commits anderer russischsprachiger Mitwirkender im Projekt-Repository. Und im Moment der Veröffentlichung - der Gründer des Projekts Thomas Müller .

H2 unterstützt rekursive Abfragen (CTE) . Dies ist die Standardmethode in SQL, um mit hierarchischen Daten in Tabellen und der Abfragezerlegung zu arbeiten (hier können Sie auf den Rechen des Schedulers treten). Rekursive Abfragen werden in der Publikation anhand von Beispielen beschrieben.

Um mit schlecht strukturierten Daten zu arbeiten, wird eine bevorstehende Implementierung des SQL / JSON-Standards angezeigt. In der Zwischenzeit hat es H2 für seine Bedürfnisse mit Hilfe eines benutzerdefinierten XQuery 3.1-Prozessors auf Basis von BaseX erweitert . Der Code ist im Projekt github H2XQueryAdapter verfügbar . Dies ist eine Tabellenfunktion, die mithilfe von XQuery Daten aus dem XML- oder JSON-Format extrahieren und den Typ und die Einschränkung von nicht null für die von der Funktion zurückgegebenen Werte überprüfen kann. Darüber hinaus steht die volle Leistung von SQL-Ausdrücken zur Verfügung, um das Ergebnis einer XQuery-Transformation in den JVM-Prozessspeicher umzuwandeln.

Die Tabellenfunktion xquery () ist überladen und verfügt über zwei Optionen - mit einem Parameter xQuery-Abfrage und einer mit xQuery-Abfrage und der zweiten SQL-Abfragezeichenfolge, um die Parameter für xQuery selbst zu bilden.

Ein Ansatz mit solchen Transformationen erwies sich in einem Projekt zur Verarbeitung eines Petabyte-Volumens an Rohdaten in einem biomedizinischen Datenspeicherprojekt als hervorragend.

create table xresult (GR VARCHAR(500) not null,AR varchar, VER VARCHAR(50)) as select * from xquery('declare variable $getHeader as xs:boolean external := false(); declare variable $getData as xs:boolean external := true(); <csv> { if($getHeader) then( <record><mavengr>VARCHAR(500) not null</mavengr><artifactname>varchar</artifactname><versionname>VARCHAR(50)</versionname></record> ), if($getData) then(( for $row in doc("http://central.maven.org/maven2/org/springframework/spring-context/5.1.4.RELEASE/spring-context-5.1.4.RELEASE.pom")//*:dependency return <record><mavengr>{$row/*:groupId/text()}</mavengr><artifactname>{$row/*:artifactId/text()}</artifactname><versionname>{$row/*:version/text()}</versionname></record> )) } </csv>') 

Diese Implementierung hat Einschränkungen hinsichtlich des Formats der xquery-Abfrage.

  • Zunächst müssen Sie zwei externe Variablen getHeader und getData deklarieren. Dies ist erforderlich, damit die Tabellenfunktion nicht mehrmals eine Datentransformation verursacht und unnötige Ergebnisse verwirft, um nur die Namen und den Spaltentyp abzurufen. Mehrere Funktionsaufrufe sind Merkmale der H2-Basis, die mit Java-Funktionen arbeiten und eine Liste von Werten zurückgeben.
  • Zweitens sollte das Format des Ergebnisses dem der CSV-Serialisierung entsprechen

     <csv> <record><1> </1>...<N> </N></record> <record><1></1>...<N></N></record> </csv> 
  • Drittens müssen Sie den Datentyp, die Dimension und die erforderlichen Felder deklarieren, zum Beispiel: dezimal (20,4) nicht null

Beim Parsen von Spaltendatentypen habe ich versucht, den SQL-Parser von H2 wiederzuverwenden, aber es stellte sich heraus, dass er so stark mit anderen Datenbankobjekten verbunden war, dass er sich weigerte, ohne Erstellung einer Datenbank und einer Sitzung zu funktionieren. Ich tröste mich mit dem Gedanken, dass die Entwickler dies getan haben, um das Design der Anwendung zu vereinfachen und nicht für alle Gelegenheiten einen Parser für BNF-Grammatiken zu erstellen.

Sie können dieses Beispiel im Java-Debug-Modus ausführen. Neue Transformationsregeln können im bekannten xquery-Editor oder in der Open Source BaseX-GUI entwickelt werden .

Es ist möglich, fast jede Java-Sammlung oder POJO in eine virtuelle H2-Tabelle umzuwandeln. H2POJOTable Projektcode auf Github. In diesem Beispiel wird die plattformbasierte MemoryManagerMXBeans als Referenz in eine H2-Tabellenfunktion umgewandelt. Vielleicht ist der Ansatz ein wenig beruhigend für diejenigen, die über den Mangel an LINQ und die Unterstützung für Operationen an Sets in Java traurig sind.

 try (Statement statement = connection.createStatement()) { String pojoTableAlias = "create alias MemoryManagerMXBeans as $$ \n" + "import java.lang.management.ManagementFactory;\n" + "import java.lang.management.MemoryManagerMXBean;\n" + "import org.h2.expression.function.pojo.*;\n" + "import java.sql.*;\n" + "import java.util.Collections;\n" + "@CODE\n" + " ResultSet getRuntimeStat(Connection connection) throws Exception{\n" + " return H2PojoAdapter.toTable(connection, new CollectionWraper<>(MemoryManagerMXBean.class," + " ManagementFactory::getMemoryManagerMXBeans, Collections.emptyMap()));\n" + " }\n" + "\n$$"; statement.executeUpdate(pojoTableAlias); } try (Statement statement = connection.createStatement()) { try (ResultSet resultSet = statement.executeQuery("select * from MemoryManagerMXBeans()")) { int columnCount = assertResultSet(resultSet, new String[]{"memoryPoolNames", "name", "valid"}); assertThat(columnCount).isGreaterThan(1); } } 

Manchmal bricht die alte Funktionalität in H2 zusammen und wird von den Benutzern nicht so gefordert. In meinen Arbeitsprojekten lesen Programme beispielsweise Daten von der AWS S3- URL. Daher hoffe ich, dass der bekannte Fehler weiterhin behoben wird, indem ich meine Pull-Anfrage akzeptiere. Auf dem Weg zur Behebung dieses Fehlers sind instabile Tests für TLS, die auch unter Java 11 nicht funktionieren.

Mit H2 können Sie den ODBC-Treiber PostgreSQL verwenden, der eine Teilmenge seines Netzwerkprotokolls emuliert. Damit können Sie es auch theoretisch über FDW in PostgreSQL binden.

Zusätzlich zur Datenbank selbst enthält die Bereitstellung von H2 auch eine minimalistische Webkonsole mit Unterstützung für die automatische Vervollständigung beim Bearbeiten, Servlet oder eigenständigen Start. H2 sieht für Entwickler wie ein „Schweizer Messer“ aus - ein kompaktes und vielseitiges Werkzeug, wenn Ihr Projekt bereits die JVM verwendet. Beim Versuch, diese Konsole mit einem "krummen" JDBC-Treiber zu verwenden, stellte DBMS Redshift seine erste rotäugige Pull-Anforderung in das Projekt. Noel Grandin , einer der Projektteilnehmer, half mir bei der Codeüberprüfung und akzeptierte die Korrekturen.

Wenn Sie ein Analogon zu Berkeley DB Java Edition benötigen - das Projekt verfügt über MVStore - einen dauerhaften Speicher für Schlüsselwertdaten und in Kombination mit MVCC standardmäßig die "Engine" in neueren Versionen der Datenbank. Es fällt auf, dass die Datenbank sogar grundlegende Unterstützung für Geofunktionen und Volltextsuche bietet .

Dank der H2database-Mitwirkenden nutzt jeder diese Datenbank und meldet Fehler! Die H2-Datenbank wird seit 2005 entwickelt und unterstützt jetzt Fensterfunktionen und rekursive Abfragen. Sie ist eine der leistungsstärksten SQL- "Engines" für die Verarbeitung von Daten im JVM-Speicher und wird um Tabellenfunktionen für die Arbeit mit lose strukturierten Daten erweitert.

Source: https://habr.com/ru/post/de446380/


All Articles