Descripción general
- Usa
serdepara codificar y decodificar filas. - Admite atributos de
serde:skip_serializing,skip_deserializing,rename. - Usa el formato
RowBinarya través de HTTP.- Está previsto cambiar a
Nativesobre TCP.
- Está previsto cambiar a
- Admite TLS (mediante las features
native-tlsyrustls-tls). - Admite compresión y descompresión (LZ4).
- Proporciona APIs para consultar o insertar datos, ejecutar DDLs y realizar agrupación por lotes en el cliente.
- Proporciona mocks útiles para pruebas unitarias.
Instalación
Para usar este crate, añade lo siguiente a tuCargo.toml:
Características de Cargo
lz4(habilitada de forma predeterminada) — habilita las variantesCompression::Lz4yCompression::Lz4Hc(_). Si está habilitada,Compression::Lz4se usa de forma predeterminada para todas las consultas, excepto paraWATCH, que solo es aceptada por versiones de ClickHouse anteriores a v26.9.native-tls— admite URL con el esquemaHTTPSmediantehyper-tls, que enlaza con OpenSSL.rustls-tls— admite URL con el esquemaHTTPSmediantehyper-rustls, que no enlaza con OpenSSL.inserter— habilitaclient.inserter().test-util— agrega mocks. Consulta el ejemplo. Úsalo solo endev-dependencies.watch— habilita la funcionalidadclient.watch. Emite una consultaWATCH, que se eliminó en ClickHouse v26.9 junto conWINDOW VIEW, por lo que solo funciona con servidores anteriores.uuid— agregaserde::uuidpara trabajar con el crate uuid.time— agregaserde::timepara trabajar con el crate time.
Compatibilidad de versiones de ClickHouse
El client es compatible con las versiones LTS de ClickHouse y posteriores, así como con ClickHouse Cloud. ClickHouse server anterior a la v22.6 procesa RowBinary de forma incorrecta en algunos casos poco frecuentes. Puede usar la v0.11+ y habilitar la featurewa-37420 para solucionar este problema. Nota: esta feature no debe usarse con versiones más recientes de ClickHouse.
Ejemplos
Nuestro objetivo es abarcar varios escenarios de uso del client mediante los ejemplos del repositorio del client. La información general está disponible en el README de ejemplos. Si algo no está claro o falta en los ejemplos o en la documentación siguiente, no dude en contactarnos.Uso
El crate ch2rs resulta útil para generar un tipo de fila desde ClickHouse.
Crear una instancia de client
Conexión HTTPS o ClickHouse Cloud
HTTPS funciona con las features de Cargorustls-tls o native-tls.
Luego, cree el client de la forma habitual. En este ejemplo, se usan variables de entorno para almacenar los detalles de conexión:
- Ejemplo de HTTPS con ClickHouse Cloud en el repositorio del client. Esto también debería aplicarse a las conexiones HTTPS on-premise.
Selección de filas
- El marcador
?fieldsse reemplaza porno, name(campos deRow). - El marcador
?se reemplaza por los valores de las siguientes llamadas abind(). - Se pueden usar los prácticos métodos
fetch_one::<Row>()yfetch_all::<Row>()para obtener la primera fila o todas las filas, respectivamente. sql::Identifierse puede usar para vincular nombres de tablas.
query(...).with_option("wait_end_of_query", "1") para habilitar el búfer de respuesta en el servidor. Más detalles. La opción buffer_size también puede ser útil.
Insertar filas
- Si no se llama a
end(), elINSERTse cancela. - Las filas se envían progresivamente en flujo para distribuir la carga de red.
- ClickHouse inserta lotes de forma atómica solo si todas las filas caben en la misma partición y su número es inferior a
max_insert_block_size.
Async insert (agrupación por lotes del lado del servidor)
Puede usar las inserciones asíncronas de ClickHouse para evitar la agrupación por lotes en el cliente de los datos de entrada. Esto puede hacerse simplemente pasando la opciónasync_insert al método insert (o incluso a la propia instancia de Client, para que afecte a todas las llamadas a insert).
- Ejemplo de async insert en el repositorio del client.
Feature Inserter (agrupación por lotes en el cliente)
Requiere la featureinserter de Cargo.
Inserterfinaliza la inserción activa encommit()si se alcanza cualquiera de los umbrales (max_bytes,max_rows,period).- El intervalo entre la finalización de
INSERTactivas puede ajustarse mediantewith_period_biaspara evitar picos de carga causados por insertores en paralelo. Inserter::time_left()puede usarse para detectar cuándo termina el período actual. Llame aInserter::commit()de nuevo para comprobar los límites si su flujo emite elementos con poca frecuencia.- Los umbrales de tiempo se implementan usando el crate quanta para acelerar
inserter. No se usa sitest-utilestá habilitado (por tanto, el tiempo puede gestionarse contokio::time::advance()en pruebas personalizadas). - Todas las filas entre llamadas a
commit()se insertan en la misma sentenciaINSERT.
Ejecutar DDLs
Con una implementación de un solo nodo, basta con ejecutar los DDLs de esta forma:wait_end_of_query. Esto puede hacerse así:
Ajustes de ClickHouse
Puede aplicar varios ajustes de ClickHouse mediante el métodowith_option. Por ejemplo:
query, funciona de forma similar con los métodos insert e inserter; asimismo, se puede llamar al mismo método en la instancia Client para establecer la configuración global de todas las consultas.
Query ID
Con.with_option, puedes configurar la opción query_id para identificar las consultas en el registro de consultas de ClickHouse.
query, funciona de forma similar con los métodos insert e inserter.
Si configura
query_id manualmente, asegúrese de que sea único. Los UUIDs son una buena opción para ello.ID de sesión
Al igual quequery_id, puedes establecer session_id para ejecutar las sentencias en la misma sesión. session_id puede establecerse de forma global en el nivel de client, o en cada llamada a query, insert o inserter.
En las implementaciones en clúster, debido a la ausencia de “sesiones persistentes”, es necesario estar conectado a un nodo concreto del clúster para utilizar correctamente esta función, ya que, por ejemplo, un balanceador de carga round-robin no garantiza que las solicitudes posteriores se procesen en el mismo nodo de ClickHouse.
Encabezados HTTP personalizados
Si usas autenticación mediante proxy o necesitas enviar encabezados personalizados, puedes hacerlo así:client HTTP personalizado
Esto puede ser útil para ajustar la configuración del pool de conexiones HTTP subyacente.Tipos de datos
Véase también estos ejemplos adicionales:
(U)Int(8|16|32|64|128)se corresponde con los tipos(u|i)(8|16|32|64|128)equivalentes, y viceversa, o con newtypes basados en ellos.(U)Int256no se admite directamente, pero hay una solución alternativa.Float(32|64)se corresponde con los tiposf(32|64)equivalentes, y viceversa, o con newtypes basados en ellos.Decimal(32|64|128)se corresponde con los tiposi(32|64|128)equivalentes, y viceversa, o con newtypes basados en ellos. Es más práctico usarfixnumu otra implementación de números de punto fijo con signo.Booleanse corresponde conbool, y viceversa, o con newtypes basados en él.Stringse corresponde con cualquier tipo de cadena o bytes, y viceversa; por ejemplo,&str,&[u8],String,Vec<u8>oSmartString. Los newtypes también son compatibles. Para almacenar bytes, considere usarserde_bytes, ya que es más eficiente.
FixedString(N)se admite como un array de bytes, p. ej.,[u8; N].
Enum(8|16)se admite medianteserde_repr.
UUIDse mapea desde y haciauuid::Uuidmedianteserde::uuid. Requiere la featureuuid.
IPv6se corresponde constd::net::Ipv6Addr.IPv4se corresponde constd::net::Ipv4Addrmedianteserde::ipv4.
Datese puede convertir a/desdeu16o unnewtypebasado en este, y representa la cantidad de días transcurridos desde1970-01-01. Además,time::Datetambién es compatible usandoserde::time::date, para lo cual se requiere la featuretime.
Date32se mapea desde/haciai32o unnewtypeque lo envuelve, y representa una cantidad de días transcurridos desde1970-01-01. Además,time::Datees compatible medianteserde::time::date32, lo que requiere la funcionalidadtime.
DateTimese corresponde conu32o con unnewtypebasado en él, y representa un número de segundos transcurridos desde la época de Unix. Además,time::OffsetDateTimees compatible medianteserde::time::datetime, lo que requiere lafeaturetime.
DateTime64(_)se convierte a/desdei32o unnewtypebasado en este, y representa el tiempo transcurrido desde la época Unix. Además,time::OffsetDateTimees compatible mediante el uso deserde::time::datetime64::*, lo que requiere activar la featuretime.
Tuple(A, B, ...)se corresponde con(A, B, ...), y viceversa, o con unnewtypeque lo envuelve.Array(_)se corresponde con cualquierslice, y viceversa; por ejemplo,Vec<_>,&[_]. También se admiten tipos nuevos.Map(K, V)se comporta comoArray((K, V)).LowCardinality(_)se admite de forma transparente.Nullable(_)se corresponde conOption<_>, y viceversa. Para las funciones auxiliaresclickhouse::serde::*, agregue::option.
Nestedse admite si se proporcionan varios arrays con cambio de nombre.
- Se admiten los tipos
Geo.Pointse comporta como una tupla(f64, f64), y el resto de los tipos no son más que slices de puntos.
- Los tipos de datos
Variant,DynamicyJSON(nuevo) aún no son compatibles.
Simulación
El crate proporciona utilidades para simular el servidor de CH y probar consultas DDL,SELECT, INSERT y WATCH (WATCH solo es aceptada por versiones de ClickHouse anteriores a la v26.9). Esta funcionalidad puede habilitarse con la feature test-util. Úsela solo como dependencia de desarrollo.
Consulte el ejemplo.
Resolución de problemas
CANNOT_READ_ALL_DATA
La causa más común del errorCANNOT_READ_ALL_DATA es que la definición de la fila del lado de la aplicación no coincide con la de ClickHouse.
Considere la siguiente tabla:
EventLog está definido en la aplicación con tipos que no coinciden, por ejemplo:
struct EventLog:
Limitaciones conocidas
- Los tipos de datos
Variant,DynamicyJSON(nuevo) aún no se admiten. - El enlace de parámetros del lado del servidor aún no se admite; consulta este issue para seguir su evolución.