H2 evolution - fonctions de fenêtre, CTE, JSON / XML dans une base de données embarquée

Il existe des projets open source qui sont devenus des succès commerciaux courants, tels que PostgreSQL / Elasticsearch. D'autres, par exemple RethinkDB, ont perdu le marché et arrêté le développement. Et le projet de base de données H2 d'une base de données embarquée écrite en java se développe et vit dans sa niche.


Pour démontrer les fonctionnalités de SonarQube, Jira, Confluence, la base de données H2 est utilisée au premier démarrage. H2 est la base pour exécuter des tests SQL en mémoire dans presque tous les projets JVM. Il existe un exemple d'application moins connue des utilisateurs - c'est l'utilisation de H2 dans un ignite-sql distribué et c'est déjà un script prêt pour la production pour utiliser une base de données intégrée dans le cadre d'une autre solution. Il y a moins d'un mois, la version 1.4.199 a été publiée dans laquelle vous pouvez désormais écrire des requêtes SQL assez complexes.

Dans les projets, je ne me suis jamais appuyé sur H2 comme base de données complète avec sauvegarde des données sur disque. Plutôt, comme module de transformation de données dans la mémoire JVM, avec une bonne prise en charge SQL. Mais pour cette application, elle était grandement limitée par le manque de fonctions de fenêtre . Et maintenant, après plus de six mois depuis le début du développement de la fonctionnalité , H2database a maintenant rattrapé SQLite . Et cela est dû au grand mérite de Yevgeny Ryazanov d'Irkoutsk - je n'ai jamais vu un rythme de développement comme le sien dans les projets open source à but non lucratif. De plus, les engagements d'autres contributeurs russophones apparaissent régulièrement dans le référentiel du projet. Et au moment de la sortie - le fondateur du projet Thomas Mueller .

H2 prend en charge les requêtes récursives (CTE) . Il s'agit de la méthode standard en SQL pour travailler avec des données hiérarchiques dans les tables et la décomposition des requêtes (ici, vous pouvez marcher sur le rake du planificateur). Les requêtes récursives sont décrites dans la publication avec des exemples.

Pour travailler avec des données mal structurées, une implémentation prochaine de la norme SQL / JSON apparaîtra. Entre-temps, pour ses besoins, il a étendu H2 avec l'aide d'un processeur XQuery 3.1 de fonction personnalisée basé sur BaseX . Le code est disponible dans le projet github H2XQueryAdapter . Il s'agit d'une fonction de table qui peut extraire des données du format XML ou JSON à l'aide de XQuery et vérifier le type et la restriction de non null pour les valeurs renvoyées par la fonction. De plus, toute la puissance des expressions SQL est disponible pour transformer le résultat d'une transformation XQuery en mémoire de processus JVM.

La fonction de table xquery () est surchargée et dispose de deux options - avec un paramètre xQuery query et une avec xQuery query et la seconde - sql query string pour former les paramètres de xQuery lui-même.

Une approche avec de telles transformations s'est avérée excellente dans un projet de traitement d'un volume de pétaoctets de données brutes dans un projet de stockage de données biomédicales .

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>') 

Cette implémentation a des limites sur le format de la requête xquery.

  • Tout d'abord, vous devez déclarer deux variables externes getHeader et getData - cela est nécessaire pour que la fonction de table ne provoque pas la transformation de données plusieurs fois, en éliminant les résultats inutiles afin d'obtenir uniquement les noms et le type de colonnes. Les appels de fonctions multiples sont des fonctionnalités de la base H2 fonctionnant avec des fonctions java renvoyant une liste de valeurs.
  • Deuxièmement, le format du résultat devrait être comme pour la sérialisation csv

     <csv> <record><1> </1>...<N> </N></record> <record><1></1>...<N></N></record> </csv> 
  • Troisièmement, vous devez déclarer le type de données, la dimension et les champs obligatoires, par exemple: décimal (20,4) non nul

Avec l'analyse de type de données de colonne, j'ai essayé de réutiliser l'analyseur SQL de H2, mais il s'est avéré être si fortement connecté à d'autres objets de base de données qu'il a refusé de fonctionner sans créer de base de données et de session. Je me console en pensant que les développeurs l'ont fait pour simplifier la conception de l'application et non pour faire un analyseur pour toutes les occasions pour les grammaires BNF.

Vous pouvez exécuter cet exemple en mode de débogage java. De nouvelles règles de transformation peuvent être développées dans l'éditeur xquery familier ou dans l' interface graphique Open Source BaseX .

Il est possible de transformer presque n'importe quelle collection java ou POJO en une table virtuelle H2. Code de projet H2POJOTable sur github. Dans l'exemple, par référence, le MemoryManagerMXBeans basé sur la plateforme se transforme en une fonction de table H2. Peut-être que l'approche sera un peu réconfortante pour ceux qui sont tristes du manque de LINQ et du support pour les opérations sur les ensembles en Java.

 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); } } 

Parfois, l'ancienne fonctionnalité de H2 tombe en panne et n'est pas tellement demandée par les utilisateurs. Par exemple, dans mes projets de travail, les programmes lisent des données à partir de l'URL AWS S3 . Par conséquent, j'espère que l'erreur connue sera toujours corrigée en acceptant ma demande d'extraction . Sur le chemin de la correction de cette erreur, des tests instables pour TLS, qui ne fonctionnent pas non plus sous Java 11.

H2 vous permet d'utiliser le pilote ODBC PostgreSQL émulant un sous-ensemble de son protocole réseau. Ce qui vous permet également théoriquement de le lier via FDW dans PostgreSQL.

En plus de la base de données elle-même, la livraison de H2 comprend également une console Web minimaliste avec prise en charge de l'auto-complétion lors de l'édition, de la servlet ou de l'option de démarrage autonome. H2 ressemble à un «couteau suisse» pour les développeurs - un outil compact et polyvalent si votre projet utilise déjà la JVM. Lorsque vous essayez d'utiliser cette console avec un pilote jdbc "tordu", le SGBD Redshift a fait sa première demande d'extraction aux yeux rouges dans le projet. Noel Grandin , l'un des participants au projet, m'a aidé à réviser le code et a accepté les corrections.

Si vous avez besoin d'un analogue de Berkeley DB Java Edition - le projet a MVStore - un stockage persistant pour les données de valeur-clé et, en combinaison avec MVCC, le "moteur" par défaut dans les versions récentes de la base de données. Il est frappant de constater que la base de données a même un support de base pour les géofonctions et la recherche en texte intégral .

Grâce aux contributeurs H2database, tout le monde utilise cette base de données et signale les erreurs! La base de données H2 se développe depuis 2005 et prend désormais en charge les fonctions de fenêtre, les requêtes récursives, c'est l'un des "moteurs" SQL les plus puissants pour le traitement des données dans la mémoire JVM et est étendu par des fonctions de table pour travailler avec des données peu structurées.

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


All Articles