Vue d’ensemble
ClickHouse prend en charge le protocole Apache Arrow Flight — un framework RPC haute performance permettant un transport efficace de données en colonnes à l’aide du format Arrow IPC sur gRPC. L’implémentation inclut la prise en charge d’Arrow Flight SQL, ce qui permet aux outils de BI et aux applications utilisant le protocole Flight SQL d’interroger ClickHouse directement. Fonctionnalités clés :- Exécuter des requêtes SQL et récupérer les résultats au format Apache Arrow.
- Insérer des données dans des tables à l’aide du format Arrow.
- Interroger les métadonnées (catalogues, schémas, tables, clés primaires) via les commandes Flight SQL.
- Créer, lier, exécuter et fermer des instructions préparées côté serveur via Flight SQL.
- Gérer les sessions et les paramètres via les actions Flight SQL.
- Chiffrement TLS et authentification par nom d’utilisateur/mot de passe.
- Récupération incrémentielle des résultats via
PollFlightInfo. - Annulation de requêtes via
CancelFlightInfo.
Activation du serveur Arrow Flight
Pour activer le serveur Arrow Flight, ajoutez le paramètrearrowflight_port à la configuration du serveur ClickHouse :
Configuration TLS
Pour activer TLS pour l’interface Arrow Flight, configurez les paramètres suivants :grpc+tls:// au lieu de grpc://.
Authentification
L’interface Arrow Flight prend en charge deux méthodes d’authentification :Authentification de base
Les clients s’authentifient à l’aide d’un nom d’utilisateur et d’un mot de passe via l’en-tête HTTP standardAuthorization: Basic. Une fois l’authentification réussie, le serveur renvoie un Bearer token dans l’en-tête de réponse.
Authentification par Bearer token
Les requêtes ultérieures peuvent utiliser le Bearer token renvoyé par l’authentification de base via l’en-têteAuthorization: Bearer <token>. Le jeton est automatiquement actualisé à chaque utilisation et expire selon le paramètre de serveur default_session_timeout (par défaut : 60 secondes).
Exemple en Python
Gestion des sessions
L’interface Arrow Flight prend en charge les sessions ClickHouse via des en-têtes de métadonnées gRPC personnalisés :Comme Arrow Flight utilise gRPC sur HTTP/2, les noms des en-têtes de métadonnées sont sensibles à la casse et doivent être indiqués en minuscules, exactement comme illustré (par exemple,
x-clickhouse-session-id, et non X-ClickHouse-Session-Id). Cette exigence est définie par la RFC 9113, section 8.2, qui impose que les noms de champ HTTP/2 ne contiennent que des caractères minuscules. Cela diffère de HTTP/1.1, où les noms d’en-tête ne sont pas sensibles à la casse.SetSessionOptions (voir DoAction).
Référence de la configuration du serveur
Méthodes RPC prises en charge
GetFlightInfo
Exécute une requête et renvoie unFlightInfo contenant le schéma des résultats, les endpoints avec leurs tickets pour la récupération des données, le nombre de lignes et le nombre d’octets.
Accepte un FlightDescriptor, qui peut être :
- descripteur PATH : un path à composant unique interprété comme un nom de table. Génère
SELECT * FROM <table>. - descripteur CMD : soit une requête SQL brute, soit une commande protobuf Flight SQL sérialisée (voir Flight SQL Commands).
PollFlightInfo
Permet la récupération incrémentale des résultats pour les requêtes de longue durée. Au lieu d’attendre la fin complète de la requête (comme avecGetFlightInfo), PollFlightInfo renvoie les résultats bloc par bloc.
Lors du premier appel, la requête commence à s’exécuter. La réponse inclut :
- Un
FlightInfoavec les endpoints de tous les blocs de données disponibles à ce stade. - Un
FlightDescriptorpour l’interrogation suivante (si d’autres résultats sont attendus).
L’implémentation actuelle reste bloquante jusqu’à ce qu’un bloc de données soit disponible, au lieu de renvoyer immédiatement une réponse vide.
GetSchema
Renvoie le schéma Arrow du résultat d’une requête sans exécuter l’intégralité de la requête. Accepte les mêmes types de descripteurs queGetFlightInfo.
DoGet
Récupère les données pour un ticket donné. Accepte l’un des éléments suivants :- Un ticket renvoyé par
GetFlightInfoouPollFlightInfo. - Une chaîne de requête SQL brute comme valeur du ticket.
DoPut
Envoie des données vers ClickHouse. Accepte unFlightDescriptor et un flux de lots d’enregistrements Arrow.
Insertion par nom de table (descripteur PATH) :
CommandStatementUpdate :
Les clients Flight SQL utilisent CommandStatementUpdate pour exécuter des instructions DDL/DML (CREATE, INSERT, ALTER, etc.). La réponse inclut le nombre de lignes affectées.
Ingestion en masse via Flight SQL CommandStatementIngest :
Seul l’ajout à des tables existantes est pris en charge (TABLE_NOT_EXIST_OPTION_FAIL + TABLE_EXISTS_OPTION_APPEND). Les catalogues et les tables temporaires ne sont pas pris en charge avec cette commande.
transaction_id n’est pas pris en charge pour CommandStatementUpdate ni pour CommandStatementIngest. S’il est fourni, ClickHouse renvoie une erreur NotImplemented.
Seul le format
Arrow est accepté pour le transfert de données. Spécifier d’autres formats en SQL (par exemple, FORMAT JSON) entraîne une erreur.DoAction
Exécute les actions nommées. Les actions suivantes sont prises en charge :CancelFlightInfo
Annule une requête en cours d’exécution associée à unFlightInfo. L’ID de la requête est extrait du champ app_metadata du FlightInfo. Annule également tous les descripteurs de polling associés à la requête.
SetSessionOptions
Définit les paramètres du serveur ClickHouse pour la session en cours. Nécessite qu’un ID de session soit défini via l’en-têtex-clickhouse-session-id.
Types de valeurs pris en charge : string, boolean, integer, double et listes de chaînes de caractères.
Si un nom de paramètre est inconnu, l’erreur INVALID_NAME est renvoyée. Si une valeur ne peut pas être interprétée, l’erreur INVALID_VALUE est renvoyée.
GetSessionOptions
Renvoie tous les paramètres ClickHouse actuels et leurs valeurs pour la session. Renvoie une map des noms de paramètres vers des valeurs de type chaîne (interrogesystem.settings en interne).
CreatePreparedStatement
Crée une instruction préparée côté serveur et renvoie un handle d’instruction. La requête contient le texte de la requête SQL avec des placeholders?.
transaction_id n’est pas pris en charge pour cette action. S’il est fourni, ClickHouse renvoie une erreur NotImplemented.
Pour les instructions de requête, la réponse peut inclure :
dataset_schema: schéma du jeu de résultats.parameter_schema: schéma des paramètres de l’instruction.
NULL n’est pas valide pour cette requête), ClickHouse crée quand même l’instruction préparée et renvoie le handle sans dataset_schema.
dataset_schema n’est qu’une estimation, conformément à l’intention de la spécification Flight SQL : celle-ci indique que le schéma du résultat peut dépendre des paramètres, que le serveur doit fournir sa meilleure estimation et que les clients ne doivent pas présumer que ce schéma est exact. Ne vous y fiez pas : exécutez l’instruction pour obtenir le schéma qui décrit réellement les données. Dans ClickHouse, il peut différer de celui qui est effectivement servi pour deux raisons :
- L’inférence remplace chaque
?parNULL; un placeholder qui détermine une colonne du résultat est donc typé d’après ceNULLplutôt que d’après la valeur que vous liez ensuite.SELECT ? AS xinfère une colonne de typeNothing, alors que lier5renvoie unUInt8. Un placeholder utilisé uniquement dans un predicate, comme dansSELECT id, name FROM t WHERE id = ?, n’est pas concerné par ce problème, car les types du résultat proviennent de la table. - Une colonne sans équivalent Arrow tire son type Arrow de
output_format_arrow_unsupported_types, que chaque appel résout à partir de la session dont il est issu. Comme un handle appartient à l’utilisateur et non à une seule session, un appel ultérieur peut le résoudre différemment et servirbinarylà oùutf8était annoncé, ou l’inverse. Définir le mode dans la requête préparée elle-même le fixe dans les deux cas.
arrowflight.prepared_statements_lifetime_seconds contrôle le comportement d’expiration :
> 0: utilise la valeur configurée comme durée de vie de l’instruction. L’expiration est actualisée à chaque requête, aussi bien pour les instructions liées à une session que pour celles sans session.0: les instructions préparées n’expirent pas automatiquement.-1(par défaut) : si l’instruction est créée dans une session, sa durée de vie suit le délai d’expiration de cette session et est actualisée à chaque requête dans cette session. Si l’instruction est créée sans session, elle n’expire pas automatiquement.
arrowflight.max_prepared_statements_per_user.
ClosePreparedStatement
Ferme une instruction préparée et libère les ressources côté serveur associées lorsque la requête contient un identifiant d’instruction non vide. ClickHouse prend également en charge la fermeture groupée avecClosePreparedStatement lorsque le handle est vide :
- Si
x-clickhouse-session-idest présent, toutes les instructions préparées de l’utilisateur authentifié dans cette session sont fermées. - Si aucun ID de session n’est présent, seules les instructions préparées sans session de l’utilisateur authentifié sont fermées.
x-clickhouse-session-id), elle est également fermée automatiquement à la fermeture de cette session.
Flight SQL Commands
Lorsqu’un descripteurCMD contient un message Flight SQL protobuf sérialisé, ClickHouse prend en charge les commandes suivantes :
Pris en charge par GetFlightInfo / GetSchema
Pris en charge via DoPut
Non pris en charge dans ClickHouse
Ces commandes correspondent à des fonctionnalités que ClickHouse ne propose pas ; elles ne sont donc pas prises en charge par l’interface Arrow Flight SQL.Exemple complet
Query
Response
Format des données
Toutes les données sont transférées au format Apache Arrow IPC. Seul le formatArrow est pris en charge — spécifier d’autres formats ClickHouse (par exemple FORMAT JSON, FORMAT CSV) provoque une erreur.
Les types de données ClickHouse sont mis en correspondance avec les types Arrow lors de la sérialisation. Arrow Flight utilise toujours la correspondance Arrow canonique et, contrairement aux formats de sortie Arrow et ArrowStream, ne tient pas compte des paramètres output_format_arrow_* qui modifient la représentation d’un type — output_format_arrow_string_as_string, output_format_arrow_low_cardinality_as_dictionary, output_format_arrow_date_as_uint16, output_format_arrow_fixed_string_as_fixed_byte_array ainsi que les paramètres d’index de dictionary n’ont aucun effet ici. Une même requête peut donc produire un schéma différent via Arrow Flight et via FORMAT Arrow, et ce à dessein, pour deux raisons :
- Flight SQL fige le schéma de ses réponses de métadonnées.
CommandGetTables, par exemple, doit renvoyercatalog_name: utf8, db_schema_name: utf8, table_name: utf8 not null, table_type: utf8 not null, table_schema: bytes not null. Laisser un paramètre de session transformer ces colonnesutf8enbinaryrendrait ClickHouse non conforme pour tous les pilotes Flight SQL, et modifierait également le schéma par table que ClickHouse annonce danstable_schema. - Un client Flight récupère le schéma et les données lors d’appels distincts (
GetFlightInfoouGetSchema, puisDoGet). Tout paramètre capable de modifier le schéma ouvre la porte à une divergence entre le schéma annoncé et le flux livré si la session change entre-temps.
JSON, Dynamic, QBit ou AggregateFunction. Il n’existe aucune correspondance canonique à laquelle se référer : ClickHouse doit donc choisir une représentation, et output_format_arrow_unsupported_types vous permet d’indiquer laquelle :
Une colonne
AggregateFunction est le seul type à rester une colonne Arrow Binary même en mode text : sa forme textuelle correspond à l’aggregate state brut, qui n’est pas de l’UTF-8 valide, or une colonne Arrow Utf8 doit contenir de l’UTF-8 valide. Utilisez finalizeAggregation si vous souhaitez une valeur lisible.
Pour la même raison, ClickHouse remplace chaque séquence UTF-8 invalide d’une valeur text par U+FFFD (�) avant de l’écrire dans la colonne Utf8. Un Dynamic contenant une String sérialise ces octets tels quels, et ils peuvent être quelconques ; sans cela, la colonne enfreindrait la spécification Arrow et pourrait être rejetée par un client strict. Seules les valeurs qui ne constituent déjà pas du texte valide sont modifiées. Utilisez le mode binary lorsque les octets doivent être préservés à l’identique.
output_format_arrow_string_as_string ne s’applique jamais à ces colonnes, pas davantage en FORMAT Arrow — ce paramètre ne régit que les véritables colonnes String et FixedString. Ainsi, le type Arrow d’une colonne clickhouse.opaque indique toujours l’encodage qu’elle contient : Utf8 pour la forme textuelle, Binary pour la forme binaire.
C’est pourquoi un aggregate state contenu dans un Dynamic subit une perte d’information en mode text, alors qu’une colonne AggregateFunction n’en subit pas. La colonne est typée à partir de Dynamic, qui ne dit rien du contenu de ses lignes, et le schéma est figé avant qu’aucune valeur n’ait été examinée : le state ne peut donc pas se voir attribuer une colonne Binary qui lui soit propre. Utilisez le mode binary pour le conserver. Un Variant énumère ses alternatives, si bien qu’un AggregateFunction figurant parmi elles obtient bien son propre enfant Binary et n’est pas concerné.
Une telle colonne étant par ailleurs indiscernable d’une véritable colonne Utf8/Binary, elle est déclarée comme un type extension Arrow : les métadonnées du champ contiennent ARROW:extension:name = clickhouse.opaque ainsi que le nom du type ClickHouse d’origine dans ARROW:extension:metadata. Un client qui ne reconnaît pas ce nom d’extension voit le type de plain storage, conformément à ce que prescrit la spécification Arrow. Les colonnes Nested sont étiquetées sur leur propre champ : l’enfant d’un Array(JSON) porte donc l’étiquette, tout comme la clé d’un Map(JSON, ...), et non le conteneur lui-même.
L’ancien paramètre booléen output_format_arrow_unsupported_types_as_binary fonctionne toujours et équivaut à throw lorsqu’il vaut 0 et à binary lorsqu’il vaut 1. Il n’est pris en compte que tant que output_format_arrow_unsupported_types conserve sa valeur par défaut.
Compatibilité
L’interface Arrow Flight est compatible avec tout client ou outil prenant en charge le protocole Arrow Flight ou Arrow Flight SQL, notamment :- Python (
pyarrow) - Java (
org.apache.arrow.flight) - C++ (
arrow::flight) - Go (
apache/arrow/go) - les drivers ADBC (Arrow Database Connectivity)
- DBeaver et d’autres outils prenant en charge Flight SQL