Descripción general
ClickHouse admite el protocolo Apache Arrow Flight: un framework de RPC de alto rendimiento para el transporte eficiente de datos en formato columnar mediante Arrow IPC sobre gRPC. La implementación incluye compatibilidad con Arrow Flight SQL, lo que permite a las herramientas de BI y a las aplicaciones que usan el protocolo Flight SQL consultar ClickHouse directamente. Capacidades clave:- Ejecutar consultas SQL y recuperar resultados en formato Apache Arrow.
- Insertar datos en tablas con el formato Arrow.
- Consultar metadatos (catálogos, esquemas, tablas y claves primarias) mediante comandos de Flight SQL.
- Crear, vincular, ejecutar y cerrar sentencias preparadas en el servidor mediante Flight SQL.
- Administrar sesiones y ajustes mediante acciones de Flight SQL.
- Cifrado TLS y autenticación mediante nombre de usuario y contraseña.
- Recuperación incremental de resultados mediante
PollFlightInfo. - Cancelación de consultas mediante
CancelFlightInfo.
Habilitar el servidor Arrow Flight
Para habilitar el servidor Arrow Flight, añada el ajustearrowflight_port a la configuración del servidor de ClickHouse:
Configuración de TLS
Para habilitar TLS en la interfaz Arrow Flight, configure los siguientes ajustes:grpc+tls:// en lugar de grpc://.
Autenticación
La interfaz Arrow Flight admite dos métodos de autenticación:Autenticación básica
Los clientes se autentican con un nombre de usuario y una contraseña mediante el encabezado HTTP estándarAuthorization: Basic. Tras autenticarse correctamente, el servidor devuelve un token Bearer en el encabezado de la respuesta.
Autenticación con token Bearer
Las solicitudes posteriores pueden usar el token Bearer devuelto por la autenticación básica a través del encabezadoAuthorization: Bearer <token>. El token se renueva automáticamente con cada uso y caduca según la configuración del servidor default_session_timeout (valor predeterminado: 60 segundos).
Ejemplo de Python
Gestión de sesiones
La interfaz Arrow Flight admite sesiones de ClickHouse mediante encabezados de metadatos gRPC personalizados:Como Arrow Flight usa gRPC sobre HTTP/2, los nombres de los encabezados de metadatos distinguen entre mayúsculas y minúsculas y deben especificarse en minúsculas exactamente como se muestra (por ejemplo,
x-clickhouse-session-id, no X-ClickHouse-Session-Id). Esto es obligatorio según la RFC 9113, Sección 8.2, que exige que los nombres de campo de HTTP/2 contengan únicamente caracteres en minúsculas. Esto difiere de HTTP/1.1, donde los nombres de los encabezados no distinguen entre mayúsculas y minúsculas.SetSessionOptions (consulte DoAction).
Referencia de la configuración del servidor
Métodos RPC compatibles
GetFlightInfo
Ejecuta una consulta y devuelve unFlightInfo que contiene el esquema del resultado, endpoints con tickets para recuperar los datos, el número de filas y la cantidad de bytes.
Acepta un FlightDescriptor, que puede ser:
- PATH descriptor: Una ruta de un solo componente interpretada como nombre de tabla. Genera
SELECT * FROM <table>. - CMD descriptor: Una cadena de consulta SQL sin procesar o un comando protobuf serializado de Flight SQL (consulta Comandos de Flight SQL).
PollFlightInfo
Permite recuperar resultados de forma incremental en consultas de larga duración. En lugar de esperar a que se complete toda la consulta (como haceGetFlightInfo), PollFlightInfo devuelve los resultados bloque por bloque.
En la primera llamada, la consulta empieza a ejecutarse. La respuesta incluye:
- Un
FlightInfocon endpoints para todos los bloques de datos disponibles hasta ese momento. - Un
FlightDescriptorpara el siguiente sondeo (si se esperan más resultados).
La implementación actual se bloquea hasta que haya un bloque de datos disponible, en lugar de devolver de inmediato una respuesta sin datos.
GetSchema
Devuelve el esquema de Arrow del resultado de una consulta sin ejecutar la consulta completa. Acepta los mismos tipos de descriptor queGetFlightInfo.
DoGet
Recupera datos para un ticket determinado. Acepta una de estas opciones:- Un ticket devuelto por
GetFlightInfooPollFlightInfo. - Una cadena con una consulta SQL sin procesar como valor del ticket.
DoPut
Envía datos a ClickHouse. Acepta unFlightDescriptor y un flujo de lotes de registros de Arrow.
Inserción por nombre de tabla (descriptor PATH):
CommandStatementUpdate:
Los clientes de Flight SQL usan CommandStatementUpdate para ejecutar sentencias DDL/DML (CREATE, INSERT, ALTER, etc.). La respuesta incluye el número de filas afectadas.
Ingesta masiva mediante Flight SQL CommandStatementIngest:
Solo se admite agregar datos a tablas existentes (TABLE_NOT_EXIST_OPTION_FAIL + TABLE_EXISTS_OPTION_APPEND). Los catálogos y las tablas temporales no son compatibles con este comando.
transaction_id no es compatible con CommandStatementUpdate ni con CommandStatementIngest. Si se proporciona, ClickHouse devuelve un error NotImplemented.
Solo se acepta el formato
Arrow para la transferencia de datos. Especificar otros formatos en SQL (por ejemplo, FORMAT JSON) genera un error.DoAction
Ejecuta acciones identificadas por nombre. Se admiten las siguientes acciones:CancelFlightInfo
Cancela una consulta en ejecución asociada a unFlightInfo. El ID de la consulta se extrae del campo app_metadata de FlightInfo. También cancela cualquier descriptor de sondeo asociado a la consulta.
SetSessionOptions
Establece la configuración del servidor de ClickHouse para la sesión actual. Requiere que se haya establecido un ID de sesión mediante el encabezadox-clickhouse-session-id.
Tipos de valores admitidos: string, boolean, integer, double y listas de string.
Si no se reconoce el nombre de una configuración, se devuelve el error INVALID_NAME. Si no se puede interpretar un valor, se devuelve el error INVALID_VALUE.
GetSessionOptions
Devuelve todos los ajustes actuales de ClickHouse y sus valores de la sesión. Devuelve un mapa de nombres de ajustes a valores de tipo cadena (consultasystem.settings internamente).
CreatePreparedStatement
Crea una sentencia preparada en el servidor y devuelve un identificador de sentencia. La solicitud contiene el texto de la consulta SQL con marcadores de posición?.
transaction_id no es compatible con esta acción. Si se proporciona, ClickHouse devuelve un error NotImplemented.
Para las sentencias de consulta, la respuesta puede incluir:
dataset_schema: esquema del conjunto de resultados.parameter_schema: esquema de los parámetros de la sentencia.
NULL no es válido para esa consulta), ClickHouse igualmente crea la sentencia preparada y devuelve el identificador sin dataset_schema.
dataset_schema es solo una aproximación, tal como establece la especificación de Flight SQL: esta indica que el esquema del resultado puede depender de los parámetros, que el servidor debe ofrecer su mejor aproximación y que los clientes no deben dar por supuesto que el esquema es exacto. No dependa de él; ejecute la sentencia para obtener el esquema que describe los datos. En ClickHouse puede diferir del que realmente se sirve por dos motivos:
- La inferencia sustituye cada
?porNULL, de modo que un marcador de posición que determina una columna del resultado recibe su tipo a partir de eseNULLy no del valor que enlace después.SELECT ? AS xinfiere una columna de tipoNothing, pero al enlazar5se sirve unUInt8. Un marcador de posición usado únicamente en un predicado, como enSELECT id, name FROM t WHERE id = ?, no presenta este problema, porque los tipos del resultado provienen de la tabla. - Una columna sin equivalente en Arrow toma su tipo de Arrow de
output_format_arrow_unsupported_types, que cada llamada resuelve a partir de la sesión desde la que se realiza. Como un identificador pertenece al usuario y no a una sola sesión, una llamada posterior puede resolverlo de forma distinta y servirbinarydonde se había anunciadoutf8, o al revés. Establecer el modo dentro de la propia consulta preparada lo fija para ambos casos.
arrowflight.prepared_statements_lifetime_seconds controla el comportamiento de expiración:
> 0: usa el valor configurado como duración de la sentencia. La expiración se renueva con cada solicitud, tanto para las sentencias asociadas a una sesión como para las sin sesión.0: las sentencias preparadas no expiran automáticamente.-1(predeterminado): si la sentencia se crea en una sesión, su duración sigue el tiempo de espera de esa sesión y se renueva con cada solicitud de esa sesión. Si la sentencia se crea sin una sesión, no expira automáticamente.
arrowflight.max_prepared_statements_per_user.
ClosePreparedStatement
Cierra una sentencia preparada y libera los recursos asociados del lado del servidor cuando la solicitud contiene un identificador de sentencia no vacío. ClickHouse también admite el cierre masivo conClosePreparedStatement cuando el identificador está vacío:
- Si
x-clickhouse-session-idestá presente, cierra todas las sentencias preparadas del usuario autenticado en esa sesión. - Si no hay ningún ID de sesión, cierra solo las sentencias preparadas sin sesión del usuario autenticado.
x-clickhouse-session-id), también se cierra automáticamente cuando se cierra esa sesión.
Comandos de Flight SQL
Cuando un descriptorCMD contiene un mensaje protobuf de Flight SQL serializado, ClickHouse admite los siguientes comandos:
Admitido a través de GetFlightInfo / GetSchema
Compatibles mediante DoPut
No admitido por ClickHouse
Estos comandos corresponden a funciones que ClickHouse no ofrece, por lo que no son compatibles con la interfaz Arrow Flight SQL.Ejemplo completo
Query
Response
Formato de datos
Todos los datos se transfieren en formato Apache Arrow IPC. Solo se admite el formatoArrow; especificar otros formatos de ClickHouse (por ejemplo, FORMAT JSON, FORMAT CSV) provoca un error.
Los tipos de datos de ClickHouse se asignan a tipos de Arrow durante la serialización. Arrow Flight siempre usa la correspondencia canónica de Arrow y, a diferencia de los formatos de salida Arrow y ArrowStream, no respeta las opciones output_format_arrow_* que modifican la representación de un tipo: 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 ni las opciones de índice de diccionario tienen efecto aquí. Por tanto, una misma consulta puede producir un esquema distinto a través de Arrow Flight que a través de FORMAT Arrow, y esto es intencionado, por dos razones:
- Flight SQL fija el esquema de sus respuestas de metadatos.
CommandGetTables, por ejemplo, debe devolvercatalog_name: utf8, db_schema_name: utf8, table_name: utf8 not null, table_type: utf8 not null, table_schema: bytes not null. Permitir que una configuración de sesión convirtiera esas columnasutf8enbinaryharía que ClickHouse dejara de cumplir la especificación para todos los controladores de Flight SQL, y además cambiaría el esquema por tabla que ClickHouse anuncia dentro detable_schema. - Un cliente de Flight obtiene el esquema y los datos en llamadas separadas (
GetFlightInfooGetSchema, y despuésDoGet). Cualquier opción capaz de cambiar el esquema abre la puerta a que el esquema anunciado y el stream entregado no coincidan si la sesión cambia entretanto.
JSON, Dynamic, QBit o AggregateFunction. No hay una correspondencia canónica a la que atenerse, así que ClickHouse debe elegir una representación, y output_format_arrow_unsupported_types te permite indicar cuál:
Una columna
AggregateFunction es el único tipo que sigue siendo una columna Binary de Arrow incluso en modo text: su forma de texto es el estado de agregación en bruto, que no es UTF-8 válido, y una columna Utf8 de Arrow debe contener UTF-8 válido. Usa finalizeAggregation si quieres obtener un valor legible.
Por la misma razón, ClickHouse sustituye cada secuencia UTF-8 no válida de un valor text por U+FFFD (�) antes de escribirlo en la columna Utf8. Un Dynamic que contiene un String serializa esos bytes literalmente, y pueden ser arbitrarios, de modo que, sin esto, la columna incumpliría la especificación de Arrow y podría ser rechazada por un cliente estricto. Solo cambian los valores que de por sí no son texto válido. Usa el modo binary cuando haya que preservar los bytes con exactitud.
output_format_arrow_string_as_string nunca se aplica a estas columnas, tampoco en FORMAT Arrow: solo rige las columnas String y FixedString reales. Por eso el tipo de Arrow de una columna clickhouse.opaque indica siempre qué codificación contiene: Utf8 para la forma de texto y Binary para la binaria.
Esta es la razón por la que un estado de agregación contenido en un Dynamic pierde información en modo text, aunque una columna AggregateFunction no. La columna se tipa a partir de Dynamic, que no dice nada sobre lo que contienen sus filas, y el esquema se fija antes de ver ningún valor, por lo que no se le puede asignar al estado una columna Binary propia. Usa el modo binary para conservarlo. Un Variant enumera sus alternativas, así que un AggregateFunction entre ellas sí obtiene su propio hijo Binary y no se ve afectado.
Por lo demás, una columna así es indistinguible de una Utf8/Binary genuina, así que se declara como un tipo de extensión de Arrow: los metadatos del campo contienen ARROW:extension:name = clickhouse.opaque y el nombre del tipo original de ClickHouse en ARROW:extension:metadata. Un cliente que no reconozca el nombre de la extensión ve el tipo de almacenamiento simple, tal como prescribe la especificación de Arrow. Las columnas anidadas se etiquetan en su propio campo, de modo que la etiqueta la lleva el hijo de un Array(JSON), y también la clave de un Map(JSON, ...), en lugar del contenedor en sí.
El antiguo valor booleano output_format_arrow_unsupported_types_as_binary sigue funcionando y equivale a throw cuando vale 0 y a binary cuando vale 1. Solo se tiene en cuenta mientras output_format_arrow_unsupported_types conserve su valor predeterminado.
Compatibilidad
La interfaz Arrow Flight es compatible con cualquier cliente o herramienta que admita el protocolo Arrow Flight o Arrow Flight SQL, entre ellos:- Python (
pyarrow) - Java (
org.apache.arrow.flight) - C++ (
arrow::flight) - Go (
apache/arrow/go) - controladores ADBC (Arrow Database Connectivity)
- DBeaver y otras herramientas compatibles con Flight SQL