img_header_blog

    Le moteur de requêtes Apache Drill

    [fa icon="calendar"] 20/05/20 14:46 / par Catherine Verdier

    2020-05-29-Apache Drill

    Apache Drill, qu’est-ce que c’est ?

    Apache Drill est un moteur de requêtes distribué avec lequel il est possible d’effectuer des requêtes SQL sur de multiples types de datasources (bases de données SQL ou NoSQL, fichiers Apache Parquet, fichiers CSV, JSON, … etc …)

    Il est possible d’utiliser des fichiers sources sur différents types de file systems : NFS (Network File System) ou HDFS (Hadoop Distributed File System).

    L’objectif principal de Drill est de permettre d’interroger (query) des données massives en lecture seule : les données manipulables par Drill sont “immutables”. 

    Drill s’appuie sur des systèmes de stockage optimisés : format Parquet (stockage disque) et Apache Arrow (stockage mémoire)

    Pour plus d’informations sur Apache Parquet et Apache Arrow, consultez :


    Quelques éléments en français sur Apache Drill sont disponibles sur Wikipédia:
    https://fr.wikipedia.org/wiki/Apache_Drill

     

    Le composant principal de Drill

    Le composant principal de Drill est le Drillbit.
    Il est possible de déployer Drill en cluster (un Drillbit par machine).

    Dans une configuration distribuée, les Drillbits collaborent pour traiter en mode distribué des données massives stockées en mode réparti sur un système de fichiers type HDFS.

     

    Immutabilité

    Drill ne permet pas d’effectuer des mises à jour sur les données : la commande SQL update n’existe pas sur Drill.

    La seule façon de transformer la donnée est la création de nouvelles tables en utilisant La commande dite “CTAS” (Create Table As Select).

    Le format par défaut des tables créées avec la commande CTAS est parquet, mais il est possible de le modifier (pour obtenir du CSV ou du Json par exemple).

    Il est également possible de supprimer des tables avec la commande DROP TABLE.

     

    Installation

    Téléchargez et décompressez l’archive de la dernière version:

    https://drill.apache.org/download/

     

    Démarrer Drill en Stand alone (mode “embedded”)

    Le plus simple pour démarrer avec Drill est de le lancer en mode embarqué (“embedded”).

    Pour cela, lancez la commande: $DRILL_HOME/bin/drill-embedded.

     

    $ bin/drill-embedded 

    Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512M; support was removed in 8.0

    avr. 03, 2017 2:08:12 PM org.glassfish.jersey.server.ApplicationHandler initialize

    INFOS: Initiating Jersey application, version Jersey: 2.8 2014-04-29 01:25:26...

    apache drill 1.9.0 

    "what ever the mind of man can conceive and believe, drill can query"

    0: jdbc:drill:zk=local>

     

    Nous avons maintenant accès à un Drill-shell, lequel embarque un Drillbit.

    Il est possible de taper nos requêtes directement sur ce Drill-shell, mais on peut également rentrer nos requêtes SQL sur la “Drill Web Console” disponible sur le navigateur à l’adresse suivante : http://localhost:8047

     

    Allez, tapons nos premières requêtes ...

    Ressources disponibles dans l’archive Drill

    Il est possible d’utiliser des ressources incluses dans l’archive Drill pour construire nos premières requêtes.

     

    En effet, 4 tables (en format parquet) sont mises à disposition dans le répertoire $DRILL_HOME/sample-data:

     

    • nationsMF;
    • nationsSF;
    • regionsMF;
    • regionsSF.

     

    Il est également possible d’utiliser une base de données de supermarché (constituée d’un ensemble de fichiers au format json) dans une archive .jar:

    $DRILL_HOME/jars/3rdparty/foodmart-data-json-....jar

     

    Exemples de requêtes:

    • Requête sur un fichier parquet ⇒
      select * from dfs.root.`$DRILL_HOME/sample-data/nationsMF`;

    • Requête sur les données de supermarché ⇒
      select * from cp.`employee.json`;

    Les préfixes cp et dfs.root font référence à la notion de Drill ‘storages’ que nous allons aborder dans le chapitre relatif à la “Drill Web Console”.

     

    Backquote : un caractère spécial

    Le caractère backquote “`” peut être considéré comme un caractère d’échappement “magique” pour les requêtes Drill.

    Vous pouvez l’utiliser pour les path, les colonnes avec des noms correspondant à items réservés au SQL (ex: type, date) ou comportant des caractères spéciaux:

    Par exemple, prenons un fichier comportant une colonne nommée “@timestamp”.

    select @timestamp from {TABLE_NAME} générera une exception de parsing

    tandis que

    select `@timestamp` from {TABLE_NAME} fonctionnera.

     

    Gestion mémoire du Drillbit

    Par défaut, la mémoire allouée à un Drillbit est de 8GB (cf voir ce lien).

    Pour modifier cette valeur il faut :

    1. Editer le fichier $DRILL_HOME/conf/drill-env.sh;
    2. Modifier la ligne: 

    export DRILL_MAX_DIRECT_MEMORY=${DRILL_MAX_DIRECT_MEMORY:-"8G"};

    1. Arrêter/Redémarrer le Drillbit.

     

    Drill Web Console

    Chaque Drillbit expose en local un port HTTP (8047 par défaut).

    Ce port est le port d’entrée de la “Drill Web Console”, et aussi celui de la REST API de Drill.

     

    Les possibilités offertes par la Drill Web Console sont:

    1. Contrôler les paramètres du Drillbit;
    2. La gestion des ‘Drill storages’;
    3. Consulter les logs de Drill et les logs des requêtes exécutées;
    4. Taper et exécuter des requêtes.

    Pour accéder à la Drill Web Console, entrez http://localhost:8047 dans votre navigateur.

     

    Drill storages

    Pour configurer les Drill storages, cliquez sur “Storage” dans la barre de menu de la Web Console:

     

    Aparche-drill

    Par défaut, plusieurs “plugins storages” sont disponibles :

    cp

    Ressources disponibles dans le classpath (voir la base foodmart vue plus haut)

    dfs

    file system

    hbase

    HBase (une base de données NoSQL scalable orientée colonne)

    hive

    Hive (un DatawareHouse distribué basé sur HDFS)

    kudu

    Pour des requêtes Impala ?? (plugin non documenté)

    mongo

    Mongo (une base de données NoSQL scalable orientée document)

    s3

    Système de stockage AWS (bucket)

     

    Les 2 premiers storages sont activés par défaut.

    Les autres storages plugins ont été implémentés pour accéder à d’autres systèmes de stockage de données (SGBDR, HBase ...etc …). Vous pouvez consulter la documentation pour en savoir plus.

    Pour visualiser ou éditer la configuration du ‘storage plugin’, cliquez sur le bouton “Update”.

    Les définitions des ‘Storages’ se présentent sous la forme d’un objet Json.

     

    Les descriptions des storages cp, dfs et s3 sont très voisines: elles sont toutes les 3 conçues pour travailler avec des fichiers (text, csv, json, parquet, avro ...etc…). Jetez un coup d’oeil au champ “formats.json” de l’objet json définissant un de ces 3 storages.

     

    Pour les 3 storages (cp, dfs or s3), plusieurs ‘workspaces’ sont définis. Chaque workspace correspond à un path du système de fichiers sous-jacent (comme le point d’entrée d’une base de données constituée d’un ensemble de fichiers). Un workspace peut être en lecture seule (“writable”:”false” ⇒ ce qui signifie que les commandes DROP TABLE et CTAS ne seront pas applicables) ou non (“writable”:”true”).

    Les définitions des storages dfs et s3 peuvent être étendues en ajoutant de nouveaux workspaces correspondant à d’autres paths sur le système de fichiers.

    De plus:

    • Il est possible de composer des requêtes mixant des sources provenant de différents storages;
    • Composer une requête dont la source est un répertoire est possible, pourvu que tous les fichiers de ce répertoire soient stockés sous le même format et que les données contenues dans ces fichiers correspondent tous au même schéma.

     

    La configuration de Drill: s’assurer de retrouver une configuration personnalisée après le reboot

    Par défaut, les définitions personnalisées des storages sont stockées sous le répertoire temporaire de l’opération system (/tmp pour Linux).

     

    Dans le cas de Linux, au reboot de la machine, le path /tmp est effacé.

    Voici donc comment procéder pour s’assurer de retrouver ses définitions de storages personnalisées après redémarrage:

     

    1. Allez dans $DRILL_HOME/conf et copier drill-override-example.conf dans drill-override.conf
    2. Editez drill-override.conf et ajouter la propriété
      sys.store.provider.local.path = {YOUR_PERSISTANT_PATH} à l’objet drill.exec

    ref: https://drill.apache.org/docs/storage-plugin-registration/

     

    Définition d’un storage dfs personnalisé pour une base spécifique

    Pour bien comprendre notre définition de storage personnalisé, supposons que:

    • Nous avons stocké nos données dans un répertoire “mydb” (/home/my_user/mydb);
    • Notre data provient du résultat de 3 jobs Spark dans un format json compressé (.json.gz) et que la donnée provient de 4 partitions Spark (4 fichiers résultats par répertoire).

    Notre base “mydb” se présente sous la forme suivante sur le disque:

     

    Apache Drill 2

    Notre base comprend plusieurs sous-répertoire ou entités: customer, product … etc …

    Pour pouvoir composer des requêtes sur notre base, nous avons modifié le storage dfs.

    Les lignes ajoutées apparaissent en rouge:

     

    {

      "type": "file",

      "enabled": true,

      "connection": "file:///",

      "config": null,

      "workspaces": {

        "root": {

          "location": "/",

          "writable": false,

          "defaultInputFormat": null

        },

        "tmp": {

          "location": "/tmp",

          "writable": true,

          "defaultInputFormat": null

        },

        "mydb": { [1] 

          "location": "/home/my_user/mydb",

          "writable": true,

          "defaultInputFormat": null

        }

      },

      "formats": {

        "psv": {

          "type": "text",

          "extensions": [

            "tbl"

          ],

          "delimiter": "|"

        },

        "csv": {

          "type": "text",

          "extensions": [

            "csv"

          ],

          "delimiter": ","

        },

        "tsv": {

          "type": "text",

          "extensions": [

            "tsv"

          ],

          "delimiter": "\t"

        },

        "httpd": {

          "type": "httpd",

          "logFormat": "%h %t \"%r\" %>s %b \"%{Referer}i\"",

          "timestampFormat": null

        },

        "parquet": {

          "type": "parquet"

        },

        "json": {

          "type": "json",

          "extensions": [

            "json",

            "gz"[2] 

          ]

        },

        "avro": {

          "type": "avro"

        },

        "sequencefile": {

          "type": "sequencefile",

          "extensions": [

            "seq"

          ]

        },

        "csvh": {

          "type": "text",

          "extensions": [

            "csvh"

          ],

          "extractHeader": true,

          "delimiter": ","

        }

      }

    }

    [1] mydb database

    [2] Because out job’s output files are gzipped json rows

     

    Requêtes sur mydb

    Une fois notre storage modifié et sauvegardé, nous pouvons jouer les requêtes suivantes:

     

    select * from dfs.mydb.`customer` limit 100

    select * from dfs.mydb.`product` limit 100

     

    Drill en mode distribué

    Information préalable: pour cette partie, notez que, aussi bien en mode standAlone qu’en mode distribué, il est possible d’envoyer nos requêtes sur Drill par l’intermédiaire d’un driver jdbc ou même d’un driver odbc.

     

    En mode distribué, on doit lancer un Drillbit par noeud (machine) et au moins un zookeeper (mais sur un cluster de production, il en faut idéalement au moins 3).

    Zookeeper est le point d’entrée des connexions au cluster et il est en mesure à tout instant de savoir quels sont les noeuds disponibles pour prendre en charge les requêtes.

     

    Une fois la requête envoyée à un noeud du cluster, les Drillbits coopèrent directement entre eux pour assurer son exécution optimale.

    Pour cette partie, nous nous contenterons de:

    • Lancer un seul zookeeper en local (pas de réplication);
    • Lancer un seul Drillbit en local;
    • Lancer le Drill-shell pour nous connecter au Drillbit via jdbc.

     

    Installation et démarrage de Zookeeper

    On procède en suivant les consignes de la documentation  de référence: https://zookeeper.apache.org/doc/r3.6.1/zookeeperStarted.html

     

    Démarrage du Drillbit

    Note importante: Pour pouvoir démarrer le Drillbit, le nom de votre machine ne doit pas faire référence à une adresse IP de type loopback (localhost ou 127.0.0.1) dans votre configuration machine (fichier /etc/hosts sous Linux).

     

    Une fois Zookeeper démarré, vérifiez le fichier $DRILL_HOME/conf/drill-override.conf pour définir correctement le zookeeper quorum (propriété zk.connect de l’objet json drill.exec).

     

    Si vous déployez plusieurs Drillbits, le champ drill.exec.cluster-id doit être identique dans toutes les configurations des Drillbits.

    En effet, ce cluster-id sera référencé dans l’url de connection jdbc (idem pour odbc).

     

    Comme dans le cas d’un lancement en standAlone, nous avons modifié la configuration pour ne pas perdre des configurations de storages personnalisées.

    Cependant, en mode distribué, il faudra cette fois modifier la propriété:
    drill.exec.sys.store.provider.zk.blobroot

    cf: https://drill.apache.org/docs/persistent-configuration-storage/.

     

    Pour démarrer notre Drillbit, il faut procéder ainsi:

     

    $> cd $DRILL_HOME

    $> bin/drillbit.sh start

     

    Autres commandes connexes:

    bin/drillbit.sh stop

    bin/drillbit.sh status (pour vérifier si notre Drillbit tourne ou non)

     

    Point à vérifier concernant le mode distribué

    Les définitions des storages personnalisées sont-elles stockées dans zookeeper ?

     

    Démarrage du Drill shell

    $> cd $DRILL_HOME

    $> bin/sqlline -u jdbc:drill:schema=dfs;zk={ZK_QUORUM}

     

    Note: ZK_QUORUM comme défini dans le fichier $DRILL_HOME/conf/drill-override.conf

     

    L’API REST de Drill

    Drill propose une API RESTful simplifiée disponible sur son port d’écoute HTTP (8047 par défaut).

    Pour ouvrir ce port aux autre machines du réseau local, il faut modifier la propriété drill.exec.http.host dans le fichier $DRILL_HOME/conf/drill-override.conf (définir l’adresse IP en 0.0.0.0).

    On peut utiliser l’API REST sur chacun des Drillbits du cluster (pourvu que le port 8047 soit ouvert pour chaque Drillbit)

    L’utilisation de l’API REST est très simple: il s’agit juste d’envoyer nos requêtes SQL dans un message json (mode POST HTTP).

    Pour en savoir plus sur l’API REST consultez la docuementation suivante: https://drill.apache.org/docs/rest-api/

     

    Gestion des options Drill

    Si, depuis la Drill Web Console,  on clique sur l’item “Options” de la barre de menu (côté droit), il est possible de changer les paramètres de Drill.

     

    Par exemple, on peut voir que le format de sortie par défaut (store.format) est “parquet”.

    Il est possible de le changer en json ou csv. Si on le définit à json, toutes les commandes CTAS vont produire des fichiers json.

     

    Par défaut, les fichiers parquets sont compressés en snappy: store.parquet.compression=snappy. On peut le changer en gzip pour obtenir un meilleur niveau de compression.

     

    Il est possible de faire la même opération en Drill-shell en utilisant sqlline:

     

    0: jdbc:drill:zk=local> alter system set `store.parquet.compression`='gzip';

    +-------+-------------------------------------+

    |  ok   |               summary               |

    +-------+-------------------------------------+

    | true  | store.parquet.compression updated.  |

    +-------+-------------------------------------+

    1 row selected (0,102 seconds)

     

    ou:

     

    0: jdbc:drill:zk=local> alter session set `store.parquet.compression`='gzip';

    +-------+-------------------------------------+

    |  ok   |               summary               |

    +-------+-------------------------------------+

    | true  | store.parquet.compression updated.  |

    +-------+-------------------------------------+

    1 row selected (0,102 seconds)

     

    “Session” à la place de “system” est préférable si l’on souhaite effectuer l’opération de façon ponctuelle (dans ce cas la modification ne sera opérante que jusqu’à la fin de la session sqlline et n’impactera pas les autres clients du Drillbit).

     

    Driver ODBC

    Le driver Drill ODBC n’est disponible que pour MS-Windows.

     

    Pour l’installer et le configurer, vous pouvez vous référer à la documentation suivante : https://drill.apache.org/docs/installing-the-driver-on-linux/#step-1:-download-the-drill-odbc-driver

     

    Windows vs Linux

    L’installation d’un cluster Drill (distribué donc), n’est possible que sous Linux.

    Par contre, il est parfaitement possible d’utiliser Drill en mode “embedded” (StandAlone) sous Windows.

     

    Conclusion

    De par les fonctionnalités qu’il propose, Apache Drill a été conçu comme une solution qu’on peut qualifier de concurrente à Google BigQuery, Amazon RedShift.

    Cependant, BigQuery affiche des points forts pour la manipulation des données massives qui ne sont pas disponibles avec Drill. En particulier, Drill n’effectue que des comptages exacts (comme une base de données traditionnelle) et n’implémente pas encore des algorithmes d’approximation comme HyperLogLog permettant d’obtenir des résultats de bonne qualité avec des temps de réponse bien meilleurs.

    Alors pour les passionnés de Java, et des projets Open source, il reste possible de l’enrichir pour le faire rivaliser avec les moteurs de requêtes des plus grands fournisseurs de cloud. 

    Thèmes : Actu Ysance, Data Services, Apache Drill, expert

    S'abonner au blog