Cambios incompatibles con versiones anteriores
Cambios en consultas, funciones y sintaxis
- Para las vistas cuyo cuerpo es un
SELECTsimple sobre una única tablaDistributed, ahora toda la consulta externa se delega a los segmentos (nuevo ajusteoptimize_trivial_view_pushdown_to_distributed, habilitado de forma predeterminada). Esto cambia el comportamiento observable de dichas vistas:FINALySAMPLEindicados en la referencia a la vista ahora se propagan a la tabla local del segmento en lugar de ignorarse, yextremesno se devuelve en clústeres de un solo segmento. Establezcaoptimize_trivial_view_pushdown_to_distributed = 0para restaurar el comportamiento anterior. #101791 (simonmichal). - Las partes de parche de
UPDATEligero ahora usan un nuevo formato en disco v2, ordenado por (sorting_key..., _block_number, _block_offset) y aplicado con un nuevo algoritmo de fusión. El pico de memoria queda limitado por la secuencia más larga con la misma clave de ordenación, en lugar de por el parche completo, y las actualizaciones que atraviesan límites de fusión ya no recurren a aplicarse mediante Join en memoria. Las partes de parche con el formato antiguo siguen siendo legibles. Durante una actualización progresiva desde una versión anterior a la 26.8, mantengapatch_parts_version = 'v1'o utilice el ajustecompatibilityhasta que todas las réplicas se hayan actualizado. #103182 (CurtizJ). AggregatingMergeTreeahora rechaza, al crear la tabla, los esquemas en los que alguna columna no forma parte de la clave de ordenación ni es una medida de estado de agregación (AggregateFunction/SimpleAggregateFunction). Durante las fusiones en segundo plano, estas columnas se reducen silenciosamente a un valor arbitrario, lo que produce resultados incorrectos en las consultas que aplicanGROUP BYo filtran por ellas. Establezcaallow_dimensions_outside_sorting_key = 1para restaurar el comportamiento anterior. #108087 (alexey-milovidov).- ClickHouse ahora utiliza siempre el hash unificado de deduplicación de inserciones tanto en las inserciones síncronas como en las asíncronas; se eliminan los comportamientos heredados de deduplicación por inserción. El ajuste de servidor
insert_deduplication_versionse mantiene como salvaguarda para la migración: el servidor no se inicia si tiene asignado un valor heredado (old_separate_hashesocompatible_double_hashes). Para actualizar desde una versión que usaba un valor heredado, ejecute primero una versión que admitacompatible_double_hashes(que escribe tanto los hash heredados como los unificados). En las tablas replicadas, manténgala en ejecución durante al menosreplicated_deduplication_window_seconds(una hora de forma predeterminada; las ventanas predeterminadas conservan los hash unificados de todas las inserciones durante ese periodo, lo que se considera suficiente para un bucle de reintentos de inserción). En las tablas no replicadas connon_replicated_deduplication_window> 0, esa ventana se basa en un número de inserciones y no en el tiempo, por lo que debe ejecutarcompatible_double_hashesdurante al menos esa cantidad de inserciones. Después, elimine el ajuste (o establézcalo ennew_unified_hash) antes de actualizar a esta versión. #108361 (CheSema). - El ajuste
use_legacy_to_timeahora es0de forma predeterminada, por lo quetoTimeconvierte los valores al tipo de datosTimeen lugar de convertir una fecha con hora en una fecha fija. El comportamiento heredado sigue disponible mediante la funcióntoTimeWithFixedDateo estableciendouse_legacy_to_time = 1. #108729 (alexey-milovidov). - Los modelos Naive Bayes (utilizados por
naiveBayesClassifier) ahora se configuran como un diccionario con el layoutNAIVE_BAYES, que se construye durante la carga a partir de una tabla de recuentos de n-gramas preagregados por clase, en lugar de la configuración anterior del lado del servidor (un archivo de configuración XML que hacía referencia a archivos de modelo.binserializados), que ya no es compatible: los modelos existentes deben recrearse como diccionarios. Se añaden tres nuevas funciones junto anaiveBayesClassifier:naiveBayesClassifierWithProbdevuelve la clase predicha junto con su probabilidad,naiveBayesClassifierWithAllProbsdevuelve todas las clases con sus probabilidades ynaiveBayesNgramsdivide el texto en n-gramas del mismo modo que el diccionario, lo que permite construir los datos de entrenamiento a partir de texto etiquetado sin procesar. Además, se han aplicado varias optimizaciones de rendimiento: con un modelo de lenguaje de trigramas de puntos de código de 9.7 MiB, utiliza ~49× menos memoria (de 1.84 GiB a 38 MiB), se carga ~11× más rápido y clasifica ~11× más rápido. #108773 (nihalzp). - El valor predeterminado de la configuración
max_insert_threadsha cambiado de1(sin paralelismo) aauto, que equivale al número de núcleos de CPU disponibles para el servidor (y se reduce cuando hay presión de memoria, segúnmax_insert_threads_min_free_memory_per_thread). Esto paralelizaINSERT SELECTde forma predeterminada y también puede paralelizar la parte de escritura de unINSERTsimple apto cuando la ruta de escritura de destino admite distribuirse de forma segura. Esto puede cambiar el número de partes creadas y el orden de las filas insertadas. Para restaurar el comportamiento anterior, establezcamax_insert_threadsen1ocompatibilityen una versión inferior a26.8. #109000 (alexey-milovidov). #109006 (alexey-milovidov). - Al leer un
Tuplesimple en CSV, ahora se toma un campo por elemento en todas las posiciones, de modo que un\Nen el campo de un elemento de nivel superior corresponde a ese elemento y se le aplicainput_format_null_as_default. Anteriormente, un\Ninicial se interpretaba como que toda la columna era nula, por lo que la fila se sustituía por el valor predeterminado de la columna y luego fallaba el análisis de las celdas de los elementos restantes. Este cambio es incompatible con versiones anteriores en el caso de una fila que proporciona un único campo para todo unTuplesimple: ahora le faltan los elementos restantes y se rechaza; y, en el caso de unTuplede un solo elemento, donde el número de campos es el mismo en ambos casos, devuelve silenciosamente el valor predeterminado del elemento en lugar delDEFAULTde la columna. Establezcainput_format_csv_deserialize_separate_columns_into_tuple = 0para volver a leer dicho campo como la columna completa. #109744 (groeneai). - Se añadió la cláusula
VALID FOR <interval>aCREATE USERyALTER USERcomo forma abreviada deVALID UNTIL. La fecha límite de expiración se calcula como la hora actual más el intervalo indicado en el momento de ejecutar la consulta y se almacena con la formaVALID UNTIL. La columnavalid_untilde la tablasystem.usersahora es de tipoArray(DateTime64(0))en lugar deArray(DateTime), para que las fechas límite posteriores al año 2106 se representen con exactitud; las herramientas que leen esta columna deben admitir el nuevo tipo. #110171 (alexey-milovidov). EXPLAIN SYNTAXahora devuelve la consulta reformateada como un único registroString(con saltos de línea incrustados) en lugar de un registro por línea, de modo que su salida es una única fila recuperable que puede utilizarse directamente (por ejemplo,SELECT count() FROM (EXPLAIN SYNTAX ...)devuelve1). Este comportamiento se controla mediante la nueva opciónsingle_record, cuyo valor predeterminado es1; establezcasingle_record = 0para restaurar la salida tradicional de un registro por línea. Los demás tipos deEXPLAIN(PLAN/PIPELINE/AST) mantienen su salida en árbol línea por línea. #110479 (alexey-milovidov).- La función
hasColumnInTableya no acepta los argumentos opcionaleshostname,usernameypasswordpara comprobar una columna en un servidor remoto arbitrario; solo se mantiene la formahasColumnInTable(database, table, column). El modo remoto eliminado suponía un problema de seguridad: permitía a cualquier usuario iniciar conexiones salientes a hosts arbitrarios, exponía credenciales en los registros de consultas y no estaba restringido por ningún privilegio. #110881 (alexey-milovidov). - Los motores de base de datos
PostgreSQLyMaterializedPostgreSQLahora respetan la configuraciónremote_url_allow_hostsdel servidor, como ya hacían el motor de tablaPostgreSQL, la función de tablapostgresqly los diccionarios creados mediante DDL. La política se aplica enCREATE DATABASEy en losATTACH DATABASEejecutados por el usuario: siremote_url_allow_hostsestá configurado en su servidor, ahora se rechaza conUNACCEPTABLE_URLla creación o el adjuntado de una base de datosPostgreSQLoMaterializedPostgreSQLque apunte a un host fuera de la lista de permitidos. Las bases de datos existentes se siguen cargando al iniciar el servidor, de modo que una actualización no puede impedir que el servidor arranque. #111135 (alexey-milovidov). - Se eliminaron el lector y el escritor basados en la biblioteca Apache Arrow para los formatos
ArrowyArrowStream. La implementación nativa de ClickHouse, predeterminada desde la versión 26.7, es ahora la única. Los ajustesinput_format_arrow_use_native_readeryoutput_format_arrow_use_native_writerestán obsoletos: se siguen aceptando, pero no tienen ningún efecto, por lo que una consulta que los establecía en0para forzar la implementación de Apache Arrow ahora utiliza la nativa. #111996 (alexey-milovidov). - Las credenciales TLS de un origen MySQL (
ssl_ca,ssl_cert,ssl_key) ya no pueden especificarse como rutas de archivo desde SQL —en una colección con nombre creada conCREATE NAMED COLLECTION, como argumento de consulta o en una consultaCREATE DICTIONARY—, ya que el servidor abre esos archivos con sus propios privilegios. Las rutas siguen admitiéndose en el archivo de configuración del servidor. En los demás casos, pase el contenido del certificado o de la clave en los nuevos parámetrosssl_ca_pem,ssl_cert_pemyssl_key_pem, que se enmascaran en los registros y en las consultasSHOWal igual que las contraseñas. #112070 (alexey-milovidov). disable_insertion_and_mutationahora impide el consumo en segundo plano de las tablasKafka,RabbitMQyNATS, pero sigue permitiendo escrituras directas en el almacenamiento externo. Las tablasKafka2,NATSyRabbitMQafectadas por esta restricción no inicializan consumidores para unSELECTdirecto. El ajustemessage_queue_disable_insertion, introducido recientemente, ahora requiere reiniciar el servidor. #113660 (cwurm).- Un
PARTITION BYuORDER BYde ventana sobre una columnaAggregateFunctionahora se rechaza conILLEGAL_COLUMN, como ya ocurría con unORDER BYde nivel superior sobre ese tipo de columna. Anteriormente, al menos uno de los analizadores aceptaba este tipo de consultas, y elPARTITION BYde ventana particionaba de forma distinta segúnmax_threads. El rechazo también se aplica a un estado anidado enArray,Tuple,Map,VariantoSimpleAggregateFunction. No se ven afectados unSimpleAggregateFunctionsobre un tipo ordinario,QBit, niGROUP BYyDISTINCTsobre un estado. #113878 (groeneai). - Se corrigen las comprobaciones de acceso de los comandos
SYSTEM ... CACHE ON CLUSTER. Exigían el grupo de privilegiosSYSTEM DROP CACHEen lugar del privilegio propio de cada comando, lo que denegaba el acceso a quienes tenían un único privilegio granular de caché y, a la vez, permitía a quien tuviera el grupo ejecutarSYSTEM SYNC FILESYSTEM CACHE ON CLUSTERsin disponer deSYSTEM SYNC FILESYSTEM CACHE. #114042 (groeneai). - El motor de tabla
NATSacepta credenciales en línea mediante el nuevo ajustenats_credentials(con el mismo contenido que un archivo.creds) y ya no admitenats_credential_filedesde SQL: la ruta hace referencia a un archivo del sistema de archivos del servidor, que este abre con sus propios privilegios, por lo que solo puede especificarse en una colección con nombre definida en el archivo de configuración del servidor o comonats.credential_fileen la propia configuración del servidor. Una consulta puede sustituir esa ruta configurada pornats_credentialsen línea, salvo que el operador la haya fijado con<nats_credential_file overridable="false">. Las tablas creadas antes de esta restricción siguen funcionando tras una actualización. #114644 (alexey-milovidov).
Cambios en tipos de datos y formatos
- Se rechaza el formato de archivo de copia de seguridad
zip/zipxpara copias de seguridad guardadas en almacenamiento de objetos —destinos directosS3(...)/AzureBlobStorage(...)y destinosDisk(...)respaldados por S3 o Azure—, tanto paraBACKUPcomo paraRESTORE. Zip necesita realizar búsquedas aleatorias para leer su directorio central, algo muy lento en almacenamiento de objetos. Utilice en su lugar un formato basado en tar, comotar.gz. #101770 (Onyx2406). - Se amplió el rango admitido de
DateTime64de[1900-01-01, 2299-12-31]a[0000-01-01, 9999-12-31]. Los valores fuera del rango anterior ahora se calculan correctamente (mediante cctz) en lugar de ajustarse al límite. Con precision 8 o 9, el rango sigue siendo más reducido porque los ticks se almacenan comoInt64(con precisión de nanosegundos, el máximo sigue siendo2262-04-11). Compatibilidad con versiones anteriores: si antes utilizaba fechas y horas fuera de rango, pero dependía de las reglas de saturación tan específicas del rango anterior, tenga en cuenta que los resultados cambian ahora para ser más correctos. #107907 (alexey-milovidov). - Un número JSON sin comillas destinado a una columna
DateTime64/DateTimeenJSONEachRowy formatos similares ahora se interpreta como una marca de tiempo Unix (segundos desde la época) con precisión opcional inferior al segundo, de forma coherente con el formatoValues,CASTytoDateTime64. Anteriormente, un número con parte fraccionaria (p. ej.,1703363853.035) se rechazaba conCANNOT_PARSE_INPUT_ASSERTION_FAILED, y un entero sin más (p. ej.,1703363853) se leía como el valor escalado sin procesar de unDateTime64, lo que producía una marca de tiempo1970-.... Se trata de un cambio incompatible con versiones anteriores para los enteros sin comillas enviados a columnasDateTime64; las cadenas entre comillas y la salida JSON propia de ClickHouse (siempre entre comillas) no se ven afectadas. #108091 (alexey-milovidov). - El códec experimental
ALPahora realiza la aritmética de escalado deFloat32enFloat64, lo que elimina las excepciones con datos decimales y mejora notablemente las tasas de compresión. #111627 (rienath). - Se rechazan los valores de configuraciones de intervalo de tiempo (milisegundos/segundos) que desbordan un Int64 expresado en microsegundos #112757 (azat).
- Las métricas asíncronas ahora pueden tener el tipo de datos
Map, y las métricas por núcleo de CPU y por dispositivo se han convertido en métricas clave-valor únicas:OSUserTimeCPU0,OSUserTimeCPU1, … pasan a ser una única métricaOSUserTimeCPUcon un mapa que asocia el número de núcleo de CPU con su valor (y lo mismo ocurre con las demás métricasOS*TimeCPU*,CPUFrequencyMHz_*,Temperature*,EDAC*,Block*_*,Network(Receive|Send)*_*,Disk*_*,*BlobsQueueEstimateyAsyncLogging*QueueSize).system.asynchronous_metricstiene una nueva columnakey_values Map(LowCardinality(String), Float64)(la columnavalueesNaNpara dichas métricas),system.asynchronous_metric_loglas registra como una fila por clave mediante una nueva columnakey, el endpoint de Prometheus las exporta con una etiqueta (p. ej.,ClickHouseAsyncMetrics_BlockReadBytes{device="sda"}) y elMetricsTransmitterde Graphite las envía como<prefix>.<Metric>.<key>. Si su sistema de monitorización lee los nombres de métricas antiguos, establezcaasynchronous_metrics_key_values_modeenlegacy_namespara conservarlos, o enbothdurante la migración; esta configuración del servidor se aplica conSYSTEM RELOAD CONFIGsin necesidad de reiniciar. #115333 (alexey-milovidov). #116791 (alexey-milovidov). - Los discos de almacenamiento de objetos ahora usan de forma predeterminada transacciones nativas del almacenamiento de metadata, lo que mejora la consistencia de sus actualizaciones de metadata. #89658 (Michicosun).
Cambios en la configuración
- Se eliminaron las funciones
snowflakeToDateTime,snowflakeToDateTime64,dateTimeToSnowflakeydateTime64ToSnowflake, obsoletas desde hace tiempo. Se marcaron como obsoletas ya en la v24.6 en favor desnowflakeIDToDateTime,snowflakeIDToDateTime64,dateTimeToSnowflakeIDydateTime64ToSnowflakeID, que son las que deben usarse. El ajusteallow_deprecated_snowflake_conversion_functions(que permitía volver a habilitarlas) queda obsoleto y ya no tiene ningún efecto. #108711 (alexey-milovidov). - Se amplió el rango admitido de
Date32de[1900-01-01, 2299-12-31]a[0000-01-01, 9999-12-31], igual que el deDateTime64. El análisis y las conversiones ahora aceptan el rango ampliado en lugar de recortar silenciosamente los valores a los límites anteriores. Notas de compatibilidad con versiones anteriores: en la conversión numéricatoDate32(N), los valores en[120530, 2932896]ahora se interpretan como números de día (fechas de2300-01-01a9999-12-31) en lugar de como marcas temporales Unix de principios de 1970, conforme a la regla de que todo número que cabe en el rango de números de día se trata como número de día; los números inferiores al número de día de0000-01-01y las marcas de tiempo posteriores a9999-12-31se saturan en los nuevos límites. #111534 (alexey-milovidov).
Otros cambios incompatibles con versiones anteriores
arrayIntersectyarraySymmetricDifferenceya no tratan un valor repetido dentro de un mismo argumento como si apareciera en varios argumentos. Las consultas que dependan del comportamiento anterior pueden devolver ahora resultados diferentes:arrayIntersect([1], [2], [1, 1])devuelve[]en lugar de[1],arrayIntersect([1, 2], [2], [1, 1, 2])devuelve[2]en lugar de[1, 2], yarraySymmetricDifference([1], [2], [1, 1])devuelve[2, 1]en lugar de[2]. En el caso dearraySymmetricDifference, basta con dos argumentos:arraySymmetricDifference([1], [2, 2])devuelve[2, 1]en lugar de[1]. Ahora, un valor solo se contabiliza para un argumento si estaba presente en todos los argumentos anteriores, de modo que el resultado contiene exactamente los valores presentes en todos los argumentos. Como parte del mismo cambio,arrayIntersectconstruye su tabla hash a partir del argumento más pequeño en lugar de hacerlo a partir de todos ellos, lo que lo hace hasta 1,85 veces más rápido y reduce en un tercio el uso de memoria cuando los argumentos tienen tamaños muy distintos.arrayUnionno se ve afectado. #113021 (alexey-milovidov).- Se ha marcado como obsoleto el tipo de estadísticas de columna
minmax. #108680 (hanfei1991). - Se corrige la comprobación de acceso de
SYSTEM PREWARM PRIMARY INDEX CACHE ... ON CLUSTER, que exigía erróneamente el privilegioSYSTEM PREWARM MARK CACHEen lugar deSYSTEM PREWARM PRIMARY INDEX CACHE. #109198 (Algunenano). - Se ha corregido un problema por el que
SYSTEM STOP/START CLEANUPySYSTEM STOP/START VIRTUAL PARTS UPDATE ON CLUSTERexigíanSYSTEM PULLING REPLICATION LOGen lugar deSYSTEM CLEANUP/SYSTEM VIRTUAL PARTS UPDATE. #110289 (groeneai). - El glob
/(cualquier número de directorios) ahora también coincide con el propio directorio. Anteriormente,/no se trataba como un caso especial en los patrones glob, por lo quedata/**/file.txtno coincidía condata/file.txt(cero niveles de directorio). #97676 (alexey-milovidov).
Nuevas características
Funciones y tipos de datos
- Se añadieron las funciones
parseQueryToJSONyformatQueryFromJSONpara serializar y deserializar AST como JSON, así como un dialecto experimentalclickhouse_jsonque se habilita medianteenable_json_ast_dialect. #100412 (alexey-milovidov). #113480 (fm4v). - Se añadió la tabla del sistema
system.stemmers, que muestra todos los idiomas de stemmers disponibles que pueden especificarse en la funciónstem. #100611 (Ergus). - Se añadió compatibilidad con los operadores posfijos de SQL estándar
AT TIME ZONEyAT LOCALcomo azúcar sintáctico paratoTimeZone. La expresiónexpr AT TIME ZONE zoneahora equivale atoTimeZone(expr, zone), yexpr AT LOCALequivale atoTimeZone(expr, timeZone()). #106092 (lvzhipin03). - El motor de tabla
URLy la función de tablaurlahora redirigen al backend adecuado según el esquema de la URL:file://lo gestiona el motorFile;s3:///gs:///gcs:///oss://,S3;az:///azure:///abfss:///abfs://,AzureBlobStorage;hdfs://,HDFS; yhttp(s)://, el motorURL, como hasta ahora. La configuraciónurl_basese aplica antes de la redirección por esquema. Solo se redirigen los esquemas de S3 resueltos por losurl_scheme_mapperspredeterminados; otros esquemas de proveedores compatibles con S3 (cos,obs, …) no se redirigen y requieren usar directamente el motor o la funcións3. #106093 (alexey-milovidov). - Se añadió la función
dotProductTransposed(aliasscalarProductTransposed), que calcula el producto interno aproximado entre una columnaQBity un vector de referencia, y complementa las funciones ya existentesL2DistanceTransposedycosineDistanceTransposed. #108100 (alexey-milovidov). - Se añadió un parámetro opcional stride al tipo de datos
QBit(QBit(T, dimension, stride)) que almacena grupos de dimensiones en flujos independientes, de modo que una búsqueda vectorial pueda leer de forma eficiente solo las primeras dimensiones (por ejemplo, con embeddings Matryoshka). Las funciones de distancia transpuestas aceptan un cuarto argumento opcional,used_dims, para leer un número reducido de dimensiones. #108103 (alexey-milovidov). - Se añadió compatibilidad con el tipo de elemento
Int8en el tipo de datosQBit, lo que permite el almacenamiento y la búsqueda vectorial por distancia transpuesta (L2DistanceTransposed,cosineDistanceTransposed) sobre vectores cuantizados de enteros de 8 bits. #108105 (alexey-milovidov). - Nueva función
randomHadamardTransform(vector[, seed[, output_dims]]): una transformada de Hadamard aleatorizada y determinista de un vector de punto flotante, es decir, una rotación ortogonal que preserva la norma, útil para preprocesar embeddings antes de la cuantización y, si se trunca, como proyección aleatoria de Johnson–Lindenstrauss / Hadamard aleatorizada submuestreada. #108227 (alexey-milovidov). - Se implementó la función de agregación
mergedJSONPatchpara la agregación de tipo merge-patch al estilo de RFC 7396 sobre valores JSON, con compatibilidad con la fusión de estados y uso en AggregatingMergeTree. Los usuarios pueden agregar una columna JSON usando una marca de tiempo u otra columna de ordenación como clave de ordenación para obtener el estado más reciente. #108349 (larryluogit). - Se añadió la función
xxHash64Spark, que calcula valoresxxHash64compatibles con Spark para entradasStringyNULLusando la semilla42y devuelveInt64. #108436 (lalitium). - Se añadió la función
digits(n, offset[, length]), que devuelve el número contenido ennque comienza en el índiceoffset(1-indexed)y tienelengthdígitos. Si no se proporcionalength, la función devuelve el número desde offset hasta el final. #109012 (1000ms). - Se añadió la función aritmética
sqrpara calcular el cuadrado de un número. #109061 (lalitium). - Se añadieron las funciones de distancia transpuestas cuantizadas
cosineDistanceTransposedQuantized,L2DistanceTransposedQuantizedydotProductTransposedQuantized, que operan sobre unQBit(Int8)de códigos Lloyd-Max dequantizeBFloat16ToInt8y decuantizan sobre la marcha los códigos almacenados. Un vector de referencia de coma flotante actúa como consulta de precisión completa y se compara con precisiónFloat32(una consultaFloat64se convierte a una precisión menor); una referenciaArray(Int8)también se decuantiza, lo que da lugar a una distancia simétrica entre cuantizado y cuantizado. #109405 (alexey-milovidov). - Se añadió la nueva función
dictGetRoot, que devuelve el ancestro de nivel más alto (la raíz) de una clave en un diccionario jerárquico. Es un equivalente práctico dedictGetHierarchy(dict_name, key)[-1]. #109459 (alexey-milovidov). - Se añadió la función de tabla
mergeTreeCodecBlockCounts(database, table), que indica, para cada combinación de (parte, columna, subflujo) de una tablaMergeTree, cuántos bloques comprimidos utilizan cada códec. #109623 (rienath). - Se añadió la función
notHas, la negación dehaspara arrays, mapas y JSON. Cuando el pajar (haystack) es un array constante,optimize_rewrite_has_to_in(habilitado de forma predeterminada) reescribenotHas(constant_array, x)comox NOT IN constant_array, de modo que se ejecuta mediante una búsqueda en un conjunto y, al igual queNOT IN, puede aprovechar el índice de clave primaria para descartar datos. #109926 (nihalzp). - Se añadió el tipo de datos geoespacial
MultiPoint, almacenado comoArray(Point), y se incluyó en el tipoGeometry. #109951 (davidmenggx). - Las funciones
arrayElement(el operadorvec[n]) yarraySliceahora admiten el tipo de datosQBit:qbit[n]devuelve el n-ésimo elemento del vector con precisión completa, yarraySlice(qbit, offset, length)devuelve una proyección sobre un subconjunto de dimensiones. Ambas leen únicamente los planos de bits de los grupos de stride que necesitan, y los fragmentos alineados con los límites de los grupos de stride reutilizan los streams almacenados sin copiarlos. #109953 (Utkal059). - Se añadió el tokenizador
splitByRegexppara índices de texto y la funcióntokens. Divide la entrada en tokens usando una expresión regular como separador, por ejemplotokenizer = splitByRegexp('[^\p{L}\p{N}#+]+'), lo que permite conservar tokens con caracteres especiales comoC++oC#, que otros tokenizadores dividirían. #110002 (Ergus). - Se añadieron las funciones
geometryIntersectCartesianygeometryIntersectSpherical, que indican si dos geometrías se intersecan. A diferencia depolygonsIntersectCartesian/polygonsIntersectSpherical, aceptan cualquier tipo de dato geométrico (Point,LineString,MultiLineString,Ring,Polygon,MultiPolygon), incluido el tipo comúnGeometry, y los dos argumentos pueden ser de tipos distintos. #110062 (alexey-milovidov). - El lector nativo de ORC ahora admite el
uniontypede ORC y lo asigna al tipoVariantde ClickHouse (antes, estas columnas se rechazaban conUnsupported ORC type). #110078 (alexey-milovidov). - El formato de salida nativo de ORC ahora puede escribir el tipo
Variantde ClickHouse y lo asigna a ununiontypede ORC (antes fallaba conILLEGAL_COLUMN). #110085 (alexey-milovidov). - Se añaden formatos de estructura de tramas, que se seleccionan mediante el nuevo ajuste
framing_output_format: multiplexan las distintas partes de la respuesta de la consulta en un único flujo de respuesta HTTP (bloques de datos, totales y extremos, paquetes de progreso, eventos de perfil, registros del servidor y excepciones). Formatos de estructura de tramas implementados:None(predeterminado; todo funciona como antes),EventStream(eventos enviados por el servidor mediante HTTP),JSONEachPacketBase64yJSONEachPacketString(un objeto JSON por paquete con los datos codificados en base64 o como cadena). #110127 (alexey-milovidov). - Se añadieron la función de tabla
bigqueryy el motor de tablaBigQuerypara leer y escribir en tablas de Google BigQuery, incluidos los conjuntos de datos públicos. La estructura de la tabla se infiere a partir de su esquema en BigQuery. Para la autenticación se admite un token de acceso OAuth, una clave de cuenta de servicio en formato JSON y un cliente OAuth con un token de actualización. #110166 (alexey-milovidov). - Nueva función
aiRedact, que detecta y oculta información de identificación personal (PII) en textos mediante un proveedor de LLM. Especifique las categorías que se deben ocultar (p. ej.,['email', 'name']) o pase un array vacío para usar un conjunto predeterminado de categorías de PII. Los valores detectados se reemplazan por un token ([REDACTED]de forma predeterminada). #110464 (davidmenggx). - Se añade la función
aiFilter, que evalúa una condición en lenguaje natural sobre un texto mediante un LLM y devuelveUInt8para usarla enWHERE,PREWHEREyJOIN ... ON. #110594 (ylw510). - Se admiten conexiones TLS/SSL a PostgreSQL en el motor de tabla
PostgreSQL, la función de tablapostgresql, los motores de base de datosPostgreSQLyMaterializedPostgreSQL, y los diccionariosPostgreSQL:sslmode, además de los certificados y la clave, proporcionados como contenido literal (sslrootcert_pem,sslcert_pem,sslkey_pem; se enmascaran igual que las contraseñas) o como rutas (sslrootcert,sslcert,sslkey; solo se aceptan desde una colección con nombre definida en el archivo de configuración del servidor). #110615 (alexey-milovidov). - La función de tabla
postgresqly el motor de tablaPostgreSQLahora pueden usarse para conectarse a otro servidor ClickHouse a través del protocolo PostgreSQL (cuando se usa un nombre de tabla; la variantequery(...)aún no es compatible). Se añadieron las funciones de compatibilidad con PostgreSQLformat_typeycurrent_setting. #110760 (alexey-milovidov). - Nueva función
aiSimilarityque calcula la similitud semántica entre dos textos mediante un modelo de embeddings. Devuelve unNullable(Float32)en[-1, 1], donde1significa que los textos son idénticos, oNULLsi un operando esNULLo está vacío, o si falló el cálculo de su embedding. #110777 (davidmenggx). - Se añadieron los motores de base de datos
RemoteyRemoteSecure, que proporcionan acceso en tiempo real a las tablas de una base de datos en un servidor de ClickHouse remoto, al que reenvían las consultasSELECTeINSERT. Son el equivalente, entre ClickHouse y ClickHouse, de los motores de base de datosMySQLyPostgreSQL. #110975 (alexey-milovidov). - Compatibilidad con operadores de canalización en consultas SQL:
FROM t |> WHERE x > 1 |> AGGREGATE count() AS c GROUP BY y |> ORDER BY c DESC |> LIMIT 10, de forma similar a la sintaxis de canalización de GoogleSQL. Cualquier consultaSELECTpuede ir seguida de una cadena de operadores|>, y cada operador envuelve la consulta anterior en una subconsulta, por lo que el AST resultante es el mismo que el de la consulta equivalente con subconsultas anidadas. En una consulta que comienza con la cláusulaFROM, la cláusulaSELECTahora es opcional y, por defecto, equivale aSELECT *. #111151 (alexey-milovidov). - Se añadió la función de agregación
ginipara calcular el coeficiente de Gini de valores numéricos finitos y no negativos, incluidas las agregaciones agrupadas y distribuidas. #112280 (amirreza1307). #114643 (groeneai). - Compatibilidad con PNG animado en el formato de salida
PNG. Una columnatconvierte el resultado de una consulta en una animación; la escala de tiempo detse define medianteoutput_format_image_time_multiplier_secondsyoutput_format_image_time_divisor_seconds, youtput_format_image_streaming_animationpermite escribir los fotogramas a medida que la consulta los genera, en lugar de mantenerlos en un búfer en memoria. #112846 (alexey-milovidov). - Se añadió una columna
finish_timeasystem.mutationsque registra cuándo se completó una mutación. Para las mutaciones no finalizadas y aquellas cuyo momento de finalización se desconoce, el valor es cero. #113474 (nikitamikhaylov). - Se añade un nuevo tipo de esquema
bucketedparasystem.metric_log, que almacena todas las métricas en una única columnaMap(Enum16(...), Int64)mediante la serializaciónMappor buckets (128 buckets), además de una columnaALIASpor métrica para mantener la compatibilidad: la tabla consta de unas pocas columnas en lugar de miles, los valores cero no se almacenan y leer una sola métrica implica leer únicamente uno de los 128 buckets. Además, unMapcon clavesEnumahora puede indexarse mediante el nombre (como cadena) del valor del enum, p. ej.,map['name']. #115380 (alexey-milovidov). - Se añadió un tokenizador
chinesepara la funcióntokensy los índices de texto deMergeTree. Segmenta el texto chino en palabras mediante un diccionario y un modelo oculto de Markov (el algoritmo se basa en jieba), con las granularidadescoarse_grained(predeterminada) yfine_grained. #89945 (amosbird). - Se añade la función de agregación
groupFormat, que formatea las filas de cada grupo con un formato de salida especificado y devuelve el resultado como una cadena. #93201 (wandersofb). - Se añade el combinador de funciones de agregación
-Tuple, que aplica la función de agregación subyacente a cada elemento de una columnaTuplede forma independiente y devuelve unTuplecon los resultados, conservando los nombres de los elementos:sumTuple(t)parat = (a, b)devuelve(sum(a), sum(b)). Las funciones de agregación con varios argumentos reciben una tupla por argumento, emparejadas por posición:corrTuple((a1, a2), (b1, b2))devuelve(corr(a1, b1), corr(a2, b2)). A diferencia de-ForEachaplicado a arrays, los elementos pueden ser de tipos distintos, y se conservan el tipo de resultado y el nombre de cada elemento. #98190 (RinChanNOWWW).
Funcionalidades de SQL y de consultas
- Se añadió compatibilidad con cláusulas WHERE en las definiciones de proyecciones. Las proyecciones con WHERE solo materializan las filas que cumplen el predicado, y el optimizador puede usarlas (en función del coste) cuando el WHERE de la consulta implica el WHERE de la proyección. #102347 (SBALAVIGNESH123).
- Se añadió una forma de acceder a tablas y bases de datos mediante rutas URL en la interfaz HTTP (p. ej., `/database/table.format.gz?filter=a>0`), además de nuevas configuraciones (`http_allow_database_as_path`, `http_allow_table_as_file`, `http_allow_filters_as_path`, `http_allow_filters_as_unrecognized_url_parameters`, `select`, `order`, `sort`, `filter`, `page`, `compression`, `format`, `input_format`, `output_format`, `default_format`, `database`) que pueden combinarse entre sí y con el parámetro de URL `query` ya existente. #105249 (alexey-milovidov).
- Se añadieron los motores de tabla
RemoteyRemoteSecure, equivalentes persistentes de las funciones de tablaremoteyremoteSecure. Ahora, además deCREATE TABLE ... AS remote(...), también funcionaCREATE TABLE ... ENGINE = Remote('addresses', db, table, ...). #106189 (alexey-milovidov). - Se añadió
EXPLAIN ANALYZEpara examinar el rendimiento de las consultas: la consulta se ejecuta y las métricas reales de ejecución se muestran en el habitual formato de plan de consulta. #106586 (Fgrtue). #110668 (Fgrtue). - Se añadieron los comandos
SYSTEM STOP,SYSTEM START,SYSTEM PAUSE,SYSTEM CANCELySYSTEM REFRESH, independientes del motor, junto con sus variantes... ALL BACKGROUNDpara todo el servidor, que permiten controlar desde una única interfaz unificada la actividad en segundo plano de las tablasKafka,RabbitMQ,NATSyS3Queue/AzureQueue, así como de las vistas materializadas actualizables. En el caso de las vistas materializadas actualizables, actúan como alias de los comandosSYSTEM ... VIEWya existentes. Como parte de la compatibilidad con estos controles en NATS, las tablas JetStream ahora confirman los mensajes solo después de una inserción correcta (semántica «al menos una vez»; antes, los mensajes se confirmaban automáticamente al entregarse y podían perderse si fallaba la inserción). La nueva configuraciónnats_wait_for_flush_interval(por defectofalse, lo que mantiene el comportamiento anterior de baja latencia) permite mantener abierto un ciclo de consumo durante todo el intervalo de vaciado, en lugar de vaciar en cuanto se vacía la cola. La nueva configuraciónnats_commit_on_selecthace que unSELECTdirecto sobre una tabla JetStream consuma (confirme) los mensajes que lee. #107476 (NIKTONIKTO717). - Las funciones de tabla y los motores de tabla
mysql,postgresqlysqliteahora admiten una consulta del usuario (en lugar de un nombre de tabla) y la envían tal cual a la base de datos externa, escrita como subconsulta(SELECT ...)o comoquery('SELECT ...'). La estructura de la tabla resultante se infiere a partir del resultado de la consulta, y dicha tabla es de solo lectura. #107740 (alexey-milovidov). - Se introduce el motor de tabla
QueryRunner. Cada registro insertado en una tablaQueryRunnerrepresenta una consulta que el motor ejecuta. El motor puede utilizarse para la ejecución asíncrona de consultas, la ejecución por lotes de consultas generadas, el envío de consultas a clústeres remotos, pruebas de rendimiento, fuzzing y pruebas con tráfico en sombra. #107888 (mstetsyuk). - Se admite el modo de trama
GROUPSpara funciones de ventana (SQL:2011), p. ej.any(price) OVER (PARTITION BY symbol ORDER BY ts GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING). En una tramaGROUPS, los límites se cuentan en grupos de pares completos (conjuntos de filas con el mismo valor en la claveORDER BY), de modo queN PRECEDING/N FOLLOWINGsignificanNgrupos de pares antes/después del grupo de pares de la fila actual, en lugar de filas físicas (ROWS) o distancias entre valores deORDER BY(RANGE). #108653 (nihalzp). CREATE MATERIALIZED VIEW ... POPULATEsin más modificadores ahora es atómico a nivel local: la suscripción de la vista a las nuevas inserciones de la tabla de origen y la instantánea de los datos existentes se realizan conjuntamente bajo un breve bloqueo exclusivo sobre el origen, de modo que las filas insertadas a través del mismo servidor durante la carga inicial ya no se pierden ni se duplican (nueva configuraciónmaterialized_views_populate_atomically, habilitada de forma predeterminada). La garantía cubre solo la ruta de inserción local (las inserciones que llegan a otra réplica o a través de una ruta de escritura distribuida quedan fuera del corte) y requiere un origen capaz de proporcionar una instantánea fija (la familiaMergeTreeyMemory); los demás orígenes, así comoCREATE OR REPLACE/REPLACEy las vistas creadas en bases de datosReplicated, siguen usando la carga inicial no atómica anterior. Además,POPULATEahora puede usarse junto conTOpara rellenar la tabla de destino con los datos existentes. #108715 (alexey-milovidov).ALTER USER,ALTER ROLEyALTER SETTINGS PROFILEahora aceptanSET name = valuecomo alias deMODIFY SETTING name = value. Esta sintaxis modifica configuraciones individuales sin alterar el resto, a diferencia de la cláusulaSETTINGSsin modificadores, que reemplaza la lista completa de configuraciones. Así se reduce el riesgo de borrar por accidente las demás configuraciones de un usuario. #108722 (groeneai).- Se admite
ALTER TABLE ... MODIFY CONSTRAINT [IF EXISTS] name CHECK exprpara cambiar directamente la expresión de una restricción existente. #108768 (alexey-milovidov). - Se añadió el algoritmo IEJoin, basado en ordenación, para uniones cuya sección
ONcontiene dos comparaciones de desigualdad (<,<=,>,>=) entre las tablas unidas. Se habilita añadiendoie_joina la configuraciónjoin_algorithm. Los tipos admitidos sonALL INNER/LEFT/RIGHT/FULL JOINySEMI/ANTILEFT/RIGHT JOIN. Anteriormente, estas consultas se ejecutaban como unCROSS JOINcon un filtro (soloINNER), lo que resulta mucho más lento en tablas grandes. #109920 (vdimir). - Se añadió una nueva tabla del sistema,
system.user_query_log, que muestra a cada usuario sus propias entradas del registro de consultas sin necesidad de tener acceso a la tabla del registro de consultas. La idea y la implementación original son de Yue Ni (@niyue). #110156 (alexey-milovidov). - Nueva configuración
run_query_in_background. El servidor acepta la consulta, devuelve de inmediato un resultado vacío y la ejecuta hasta el final, independientemente de lo que ocurra con la conexión. El resultado se descarta. Puede hacer el seguimiento de la consulta mediante suquery_idensystem.processesysystem.query_log. Está pensada para consultas largas comoINSERT ... SELECT,CREATE TABLE … AS SELECToCREATE MATERIALIZED VIEW … POPULATE, que no deben interrumpirse si se pierde la conexión. #112816 (mstetsyuk). - Se admite ALTER TABLE … MODIFY PROJECTION para cambiar la configuración a nivel de proyección (p. ej., index_granularity) de una proyección existente sin necesidad de reconstruirla. La nueva configuración se aplica de forma diferida a medida que se producen las fusiones. #113343 (diegomestre2).
- El catálogo del motor de tablas S3 para lagos de datos ahora admite
INSERT, además de permitir consultar tablas existentes. #113505 (scanhex12). - El catálogo
Icebergahora admite Snowflake Horizon Catalog mediantecatalog_type = 'horizon', lo que permite leer y escribir en tablasIcebergadministradas por Snowflake. #114547 (melvynator). - Se agregó la configuración
skip_unavailable_shards_mode(también disponible como configuración del motorDistributed) para controlar qué excepciones de un segmento remoto se ignoran sin notificación cuandoskip_unavailable_shardsestá habilitado. Esto ofrece un control más preciso sobre el comportamiento de las consultas en entornos distribuidos. #79091 (byte-sourcerer).
Almacenamiento, lagos de datos y almacenamiento de objetos
- Se añadió compatibilidad con el formato de archivo Puffin (https://iceberg.apache.org/puffin-spec/). Ahora este formato puede utilizarse en funciones de tabla como
file,url,s3, etc. #103936 (scanhex12). - Se añadió el almacenamiento de partes de datos «packed» para tablas
MergeTree, que guarda todos los archivos de una parte en un único archivo empaquetado (data.packed) en lugar de un archivo por stream. Se controla mediante las configuracionesmin_bytes_for_full_part_storage,min_rows_for_full_part_storageymin_level_for_full_part_storage, y está deshabilitado de forma predeterminada. Nota de compatibilidad: una vez que una tabla escribe partes «packed», las versiones anteriores del servidor no pueden leerlas, por lo que habilitar este formato impide volver a una versión anterior del servidor. #108118 (Algunenano). - Se añadió la configuración
nats_credentialsal motor de tabla NATS, que permite especificar las credenciales de NATS directamente como una cadena (equivalente al contenido de un archivo.creds). #110733 (addshore).
Formatos de datos e ingestión
- Se añadió el formato de salida
HiveText, que escribe datos en el formato de textoLazySimpleSerDede Apache Hive. Los campos se separan con\x01; las filas, con el nuevo ajusteformat_hive_text_rows_delimiter(valor predeterminado:\n), y los valores anidados de tipoArray,MapyTupleutilizan la lista de separadores de Hive. La salida está pensada para elLazySimpleSerDepredeterminado de Hive y no es simétrica con la entradaHiveTextde ClickHouse en el caso de valores anidados o delimitadores de fila personalizados. #107582 (alexey-milovidov). - Se añadió el formato de salida
GeoJSONpara escribir documentos GeoJSONFeatureCollectioncon una entidad (feature) por fila. El nuevo ajusteformat_geojson_validate_geometry(habilitado de forma predeterminada) valida las geometrías GeoJSON tanto en lectura como en escritura; además, el formato de entradaGeoJSONahora infiereidcomoNullable(String), lo que permite distinguir los ID ausentes onullde las cadenas vacías. #108065 (nihalzp).
Configuración, acceso y observabilidad
- Se añadió una página integrada de búsqueda en la documentación, disponible en la ruta
/docsde la interfaz HTTP, que ofrece búsqueda instantánea sobre la tablasystem.documentationy renderiza la documentación de referencia (con resaltado de sintaxis, fórmulas matemáticas y enlaces cruzados). #108345 (alexey-milovidov). - Se añadió un tokenizador japonés para los índices de texto y las funciones tokens/hasAnyTokens/hasAllTokens, basado en el analizador morfológico MeCab. El diccionario se carga en tiempo de ejecución desde una ubicación definida en la configuración del servidor y se verifica con una suma de comprobación SHA-256 antes de usarse. #111420 (Ergus).
- Se añadió un nuevo ajuste de la caché del sistema de archivos,
system_cache_extensions, que controla qué archivos se almacenan en la caché del sistema cuandouse_split_cacheestá habilitado. #111575 (kirillgarbar). - Se añadió el ajuste
always_fetch_mutated_part, que permite a una réplica descargar partes mutadas desde otras réplicas en lugar de ejecutar las mutaciones localmente. #113020 (rorylshanks).
Otras nuevas características
- Se añade compatibilidad con
WITH TIESpara valores negativos deLIMIT. #100930 (nihalzp). - Se añaden las configuraciones de restauración
restore_table_data,restore_access_entitiesyrestore_functionspara controlar de forma granular qué se restaura. Estas pueden sobrescribirstructure_onlypara categorías concretas; por ejemplo,structure_only=true, restore_access_entities=truerestaura las definiciones de tablas y las entidades de acceso sin los datos de las tablas. #102402 (fm4v). - Ahora los diccionarios pueden configurarse individualmente para carga diferida con
dictionary_lazy_loaden la definición del diccionario, lo que sobrescribe la configuración global del servidordictionaries_lazy_load. Así, algunos diccionarios pueden cargarse de forma diferida y otros de forma inmediata. #108314 (mstetsyuk). - El operador de subíndice de arrays admite un array de enteros como índice:
arr[indexes]devuelve los elementos situados en todas las posiciones indicadas, lo que equivale aarrayMap(i -> arr[i], indexes). #108371 (ucasfl). - Se añaden las funciones
geoToUTM,UTMToGeo,geoToMGRSyMGRSToGeopara convertir entre coordenadas geográficas WGS84 y los sistemas de coordenadas UTM y MGRS. #108939 (alexey-milovidov). - Se añaden los comandos
SYSTEM UNLOAD DICTIONARYySYSTEM UNLOAD DICTIONARIESpara liberar la memoria de los diccionarios sin eliminar su definición. Los diccionarios se volverán a cargar de forma diferida en el siguiente acceso. #109639 (Manerone). - Se añade un nuevo tokenizador
icupara los índices de texto y las funcionestokens,hasAnyTokensyhasAllTokens, que ofrece segmentación de palabras Unicode adaptada a la configuración regional (incluida la segmentación basada en diccionarios para idiomas como el chino, el japonés y el tailandés). #109940 (Ergus). - Se añade un nuevo códec
ZXC: un códec LZ asimétrico con compresión lenta y descompresión muy rápida, cuya relación de compresión se sitúa entre la deLZ4y la deZSTD. #110620 (alexey-milovidov). - Se añade la configuración
s3_basepara que las URL relativas de las funciones de tablas3,s3Cluster,gcsyossy del motor de tablaS3puedan resolverse con respecto a una URL base de S3. Se añade el motor de base de datosURL, que resuelve los nombres de tabla como URL con respecto a una base opcional y los redirige al backend correspondiente. #111512 (alexey-milovidov). - Se habilita la expansión de comodines para
url()y el motorURLmediante la enumeración de páginas de índice HTTP (listados de directorios en HTML o texto plano) y la extracción de las URL coincidentes. Los comodines se comparan con el componente de ruta de la URL, con límites en el tamaño de la página de índice y en el número de directorios leídos. #95181 (niyue). - Se añade
AWS_MSK_IAMcomo valor admitido parakafka_sasl_mechanism, lo que permite a ClickHouse autenticarse en Amazon MSK mediante roles de IAM sin tener que gestionar credenciales SASL/SCRAM. #96100 (kalavt). - Se añade al índice de texto una etapa de posprocesamiento que transforma los tokens tras la tokenización. #98939 (Ergus).
Funcionalidades experimentales
Planificación y ejecución de consultas
- Se añadieron “controladores” para funciones definidas por el usuario de tipo executable. Un controlador declarado en
<user_defined_executable_function_drivers_config>puede utilizarse enCREATE FUNCTION name ARGUMENTS (...) RETURNS T ENGINE = DriverName(...) AS '...code...'para compilar o procesar de otro modo un fragmento de código del usuario al crear la función y generar una UDF executable lista para ejecutarse. La configuración resultante se almacena en<dynamic_user_defined_executable_functions_path>, y la consulta de origen se conserva comoATTACH FUNCTION, de modo que la función se mantiene tras reiniciar el servidor. Un controlador de prueba de concepto,c_function_body, compila y ejecuta cuerpos de funciones en C dentro de contenedores Docker aislados en modoexecutable_pool. #105131 (alexey-milovidov). - Las solicitudes a la Prometheus Query API dirigidas a
/api/v1/queryy/api/v1/query_rangeahora se registran ensystem.query_logcon las métricasread_rowsyread_bytes. #106611 (JTCunning). - Se admiten lecturas con plan de consulta distribuido para
SELECT ... FINALen tablas de la familia MergeTree cuandomake_distributed_planestá habilitado. #108148 (davenger). - Se añade la ejecución experimental de réplicas paralelas basadas en el plan para consultas sobre MergeTree. #108504 (devcrafter).
- Se añadió una función de tabla experimental,
eval, que evalúa una expresión constante para obtener una cadena de consulta y ejecuta la única consultaSELECTresultante. La funcionalidad está deshabilitada de forma predeterminada y puede habilitarse con la configuraciónallow_experimental_eval_table_function. Autor: Yue Ni #110132 (alexey-milovidov). - Réplicas paralelas basadas en el plan (
parallel_replicas_plan_based): la frontera entre lo local y lo remoto ahora la determina una optimización a nivel de plan sobre un plan de consulta normal, y las consultas sobre vistas con unUNIONse paralelizan sin necesidad deparallel_replicas_allow_view_over_mergetree. Las consultas que usanIN (subquery)ahora recurren a un plan local en lugar de fallar. #111063 (devcrafter). #112443 (devcrafter). - Se refuerza la seguridad de las funciones de IA experimentales: se rechazan de forma predeterminada los endpoints inseguros (
http) hacia hosts remotos (nueva configuraciónai_function_allow_insecure_endpoint), se limitan de forma predeterminada las llamadas salientes a la API por consulta (ai_function_max_api_calls_per_queryahora tiene el valor predeterminado1000) y se sanean las respuestas de error del proveedor que se escriben en los logs. #111286 (george-larionov). - Las réplicas paralelas basadas en el plan (
parallel_replicas_plan_based) ahora distribuyen los JOIN aptos (INNER,LEFT,RIGHT, incluidosSEMI/ANTI): la unión completa se ejecuta en un fragmento de plan distribuido, con uno de los lados coordinado entre réplicas y el otro difundido a todas ellas. #112268 (devcrafter). - Se informa del error que provocó la cancelación de una consulta distribuida (
make_distributed_plan = 1) en lugar de mostrar únicamenteQUERY_WAS_CANCELLED. Hasta ahora, el error real de una tarea de worker fallida solo podía verse en el log del servidor. #112590 (davenger). - Se admite la ejecución distribuida de planes de consulta con
IN (subquery)sin reescribirla como unJOIN. El conjunto se construye una sola vez en el iniciador y sus valores se envían junto con las tareas de los workers. Se elimina la activación forzada derewrite_in_to_join; la reescritura sigue disponible como configuración explícita. #113826 (davenger). - Una consulta con plan distribuido (
make_distributed_plan) ahora detiene sus etapas previas en cuanto se cumple unLIMIT, en lugar de calcular el resultado completo y descartarlo. #114806 (davenger). - Se corrige el error
Illegal type Decimal(18, 0) of argument of function toIntervalNanosecondque se producía cuando una consulta PromQL usabaoffsetdentro de un selector de rango, p. ej.,rate(m[2m] offset 5m). #114997 (nikitamikhaylov). - Se admite la agregación
GROUPING SETSen los planes distribuidos generados por el optimizador Cascades (make_distributed_plan = 1, enable_cascades_optimizer = 1). #115426 (davenger). - Las tablas
TimeSeriesahora pueden mantener una tabla de “muestras recientes”: cuando el nuevo ajuste del motorrecent_samples_ttl_secondses distinto de cero, el motor crea una copia con TTL de la tabla de muestras (particionada porrecent_samples_partition_by, por día de forma predeterminada) en la que se escribe en cada inserción, y las consultas PromQL cuyo rango de tiempo cabe en la ventana de TTL leen automáticamente de ella. Esto hace que las reglas de alerta y de registro, así como los dashboards de rango corto, sean varias veces más rápidos en tablas grandes. Esta preferencia puede desactivarse con el nuevo ajuste de consultatime_series_prefer_recent_samples_table. #115441 (nikitamikhaylov). - Los planes de consulta distribuidos (
make_distributed_plan) ahora detienen rápidamente las etapas previas inactivas una vez que se cumple unLIMIT: un sumidero de intercambio inactivo leeNoMoreDataNeededen cuanto llega, y una fuente de intercambio inactiva detecta que su salida está cerrada y propaga la detención hacia las etapas previas. Hasta ahora, dichas etapas seguían leyendo y calculando datos que nadie consumía. #115690 (davenger). - Las réplicas paralelas automáticas ahora pueden recopilar estadísticas en tiempo de ejecución y activar las réplicas paralelas para las consultas compatibles cuando
parallel_replicas_plan_basedestá habilitado. #115788 (devcrafter). - Se ha añadido Cascades, un optimizador experimental basado en costos para planes de consulta distribuidos, que se habilita con
enable_cascades_optimizer = 1junto conmake_distributed_plan = 1. En función del costo estimado, elige entre estrategias de join shuffle, broadcast, replicada y local; agregación en dos fases, shuffle y local; top-N distribuido en dos etapas; y lecturas paralelas y replicadas, e inserta operadores de intercambio cuando es necesario. #86353 (davenger).
Almacenamiento, lagos de datos e índices
- Se añadió una caché SLRU en memoria para los archivos de metadata de Paimon deserializados (listas de manifiestos y manifiestos). Cuando se habilita mediante el ajuste
use_paimon_metadata_files_cache, las consultas repetidas sobre la misma tabla Paimon ya no tienen que volver a descargar ni a analizar la metadata desde el almacenamiento de objetos. #104657 (Binnn-MX). - El
ReaderExecutorexperimental (use_reader_executor, desactivado de forma predeterminada) ahora puede mantener abierta una conexión con el origen remoto y reutilizarla en lecturas secuenciales, lo que reduce el número de solicitudes al almacenamiento de objetos durante los escaneos. #107735 (CheSema). - Se añadió una caché del sistema de archivos de tipo read-through a la ruta de lectura del
ReaderExecutorexperimental (use_reader_executor, desactivado de forma predeterminada). #110029 (CheSema). - Se añadió el ajuste experimental de
MergeTreeallow_experimental_adaptive_codec_selection. Cuando está habilitado, las fusiones y mutaciones eligen, para cada bloque, el códec que genera la salida más pequeña en las columnas que usan el códec predeterminado. #111834 (rienath). - Se añadió un nivel de caché de páginas en espacio de usuario a la ruta de lectura del
ReaderExecutorexperimental (use_reader_executor, desactivado de forma predeterminada). Ante un fallo de caché, el ejecutor ahora puebla la caché de páginas en espacio de usuario y atiende desde ella las lecturas posteriores, sin copias (zero-copy). #114890 (CheSema). - La compactación de archivos de manifiesto de
Icebergya está disponible medianteOPTIMIZE TABLE ... MANIFESTpara reducir el número de archivos de metadata. Está controlada por el ajusteallow_experimental_iceberg_compaction. #98178 (SmitaRKulkarni).
Funciones, formatos e IA
- Experimental: responder a
SELECT count(*) FROM t WHERE col <op> default(col)a partir de las estadísticas de dispersión por columna enserialization.json, sin escanear datos, cuando el predicado divide exactamente la columna en valores predeterminados y no predeterminados. #105890 (Algunenano). - Se añadió la familia experimental de códecs vectoriales
Quantize(...)y una reescritura opcional de búsqueda vectorial aproximada en dos etapas sobre flujos complementarios cuantizados. #108565 (shankar-iyer). - Se recupera el códec de compresión experimental
SZ3, con pérdida y error acotado, para columnasFloat32/Float64(y arrays de estos tipos). Requiereallow_experimental_codecs. #108788 (alexey-milovidov). - Se corrigió la lectura de datos comprimidos con el códec experimental
SZ3('ALGO_LORENZO_REG', ...), que antes fallaba conCORRUPTED_DATA, y se evitó el comportamiento no definido al comprimir valores de coma flotante no finitos (NaNe infinitos) con el códec experimentalSZ3. #110762 (alexey-milovidov). - PromQL: las funciones de fecha y hora (
hour(),minute(),month(),year(),day_of_week(),day_of_month(),day_of_year(),days_in_month()) ahora pueden llamarse sin argumentos, en cuyo caso usanvector(time())de forma predeterminada, como en Prometheus. #111869 (valerypetrov). - PromQL: se corrigieron las operaciones sobre vectores instantáneos sin etiquetas, p. ej.,
vector(1) + vector(2),topk(1, vector(1)),label_replace(vector(1), ...)y los operadores binarios conon(), que fallaban con un error de tipo. #111872 (valerypetrov). - PromQL: se implementó la función
derivy se corrigió un error por el que su función de agregación subyacente devolvía valores 1000 veces menores con marcas de tiempo con resolución de milisegundos. #112360 (valerypetrov). - Se aplica la optimización de lectura en orden a las consultas con
ORDER BYcuandoparallel_replicas_plan_basedestá habilitado: la ordenación ahora se envía a las réplicas y se fusiona en el initiator, de modo que cada réplica lee en el orden de la clave de ordenación. También se corrigeUnknown function __topKFilterparaORDER BYsobre una columna que no forma parte de la clave primaria cuando esta configuración está habilitada. #114315 (devcrafter). - Se corrigieron las lecturas de búsqueda vectorial tras recargar una parte de datos (por ejemplo, después de
ATTACHo de reiniciar el servidor): las partes ya no pierden sus subcolumnas del códecQuantized, por lo que las búsquedas leen las subcolumnas cuantizadas en lugar de recurrir a la columna de precisión completa. #114763 (shankar-iyer). - El motor de tabla experimental
TimeSeriesya no aplica el códecGorillaa las columnasvaluecreadas automáticamente en la tabla interna de muestras; ahora usanCODEC(ZSTD(1))de forma predeterminada. Las columnas declaradas explícitamente conservan los códecs que haya indicado el usuario. El valor predeterminado de la columnatimestampno cambia (CODEC(DoubleDelta, ZSTD(1))). #112110 (nikitamikhaylov). #114790 (nikitamikhaylov). - Se admiten
ROLLUP,CUBE,GROUPING SETSy la funcióngroupingen consultas ejecutadas conmake_distributed_plan = 1. #114950 (davenger). - Se añade una variante Real Doubles (RD) y un argumento opcional
ALP(AUTO|STD|RD)al códec experimental ALP. Ahora, ALP sin argumentos elige automáticamente entre el esquema STD existente y RD, en lugar de usar siempre STD. #99654 (nazarii-piontko).
Otras funcionalidades experimentales
- Se añade afinidad estática de partición a segmento para StorageKafka2 mediante las configuraciones kafka_partition_shard_num y kafka_shard_count, lo que permite que varios segmentos de ClickHouse consuman de forma determinista subconjuntos disjuntos de particiones de Kafka. #108886 (JingYanchao).
- Ahora puede autenticarse en OneLake con un token bearer obtenido previamente mediante la configuración
onelake_bearer_token, en lugar deonelake_client_idyonelake_client_secret. Así se evita compartir un secreto de cliente de larga duración. El token no se renueva, por lo que la base de datos debe volver a crearse cuando caduque. #109104 (asya-ch). - Se corrige
data_uncompressed_bytespara los índices de omisión empaquetados enskp_idx.packed(mediantepacked_skip_index_max_bytes): el tamaño sin comprimir que se notificaba era en realidad el tamaño comprimido, lo que además podía impedir que se activaradistributed_index_analysis. #109272 (Algunenano). - Se añadió compatibilidad con la compresión Zstandard al HTTP handler experimental de Prometheus remote-write v1. #110907 (JTCunning).
- PromQL: se implementaron las funciones
clamp,clamp_min,clamp_maxyround. #111870 (valerypetrov). - PromQL:
quantilecon un nivel de cuantil fuera de [0, 1] ahora devuelve -Inf/+Inf/NaN, igual que Prometheus, en lugar de lanzar un error, yhistogram_quantileahora ignora, también como Prometheus, las series de entrada cuya etiquetalefalta o no se puede analizar. #111871 (valerypetrov). - PromQL: se implementaron las funciones
changes()yresets(). #112352 (valerypetrov). - Ahora se recopilan correctamente las estadísticas de inserción y las consultas recibidas a través del endpoint de Prometheus remote-write. #112825 (JTCunning).
- PromQL: se conservan los valores finitos al aplicar el módulo con un divisor infinito. #113746 (fallintoplace).
- Se rechazan los saltos de línea literales en las cadenas PromQL ordinarias entre comillas. #114381 (fallintoplace).
- Un valor muy grande de
distributed_plan_workers_numya no hace que el servidor aborte con unstd::length_errorcuando están habilitadas las opciones experimentalesmake_distributed_planyenable_cascades_optimizer. Ahora ese número de nodos se rechaza conINVALID_SETTING_VALUE. #115398 (groeneai). - Se implementa el endpoint
/api/v1/seriesde la Prometheus HTTP API para las tablasTimeSeries: selectores de seriesmatch[](los valores repetidos se combinan como una unión), un rango de tiempostart/endopcional y un parámetrolimitopcional. #115676 (nikitamikhaylov).
Mejoras del rendimiento
Rendimiento de JOIN y de agregaciones
- Se habilita la caché de condiciones de consulta para las consultas que pasan por el filtrado dinámico TopK (
ORDER BY ... LIMIT n). La entrada de la QCC se particiona según los parámetros del plan TopK, de modo que una misma consulta reutiliza los resultados del filtro WHERE almacenados en caché, mientras que unLIMIT, una columna de ordenación o una dirección de ordenación distintos generan una entrada nueva. #104478 (alexey-milovidov). - Se traslada LIMIT a la agregación en orden para permitir una finalización anticipada cuando la clave de GROUP BY coincide con la clave de ORDER BY y con la clave de ordenación de la tabla, lo que reduce considerablemente el número de filas leídas. #104859 (thevar1able).
- Se habilita
allow_aggregate_partitions_independentlyde forma predeterminada. Cuando una clave deGROUP BYes compatible con la clave de partición, ClickHouse puede agregar cada partición de forma independiente y omitir el paso de fusión global. Unas heurísticas en tiempo de ejecución descartan automáticamente la optimización cuando la distribución de las particiones la haría desfavorable (muy pocas particiones, demasiadas particiones o tamaños de partición muy desequilibrados). #105128 (alexey-milovidov). - Se habilita
read_in_order_use_virtual_rowde forma predeterminada. Al leer en el orden de la clave primaria (p. ej.,ORDER BY primary_key LIMIT n) en una tabla con muchas partes, solo se leen las partes que realmente pueden contribuir al resultado (más una ventana de lectura anticipada de, como máximo,max_threadspartes que mantiene la lectura en paralelo), lo que reduce considerablemente el consumo máximo de memoria. #106215 (alexey-milovidov). - Se ha reducido el uso de memoria y mejorado el rendimiento de los
JOIN. El lado derecho de una unión hash utiliza ahora una referencia de fila compacta de 8 bytes basada en índices, de modo que las entradas de la tabla hash de las unionesALLson tan pequeñas como las de las unionesANYpara cualquier tipo de clave. En pruebas de rendimiento con consultas grandes de uniónparallel_hash—unionesINNERyANYde tablas de entre 100 y 300 millones de filas con clavesUInt64yString, tanto únicas como duplicadas—, la consulta mediana fue aproximadamente un 12 % más rápida y usó cerca de un 15 % menos de memoria máxima, sin que ninguna consulta se volviera más lenta. Las unionesINNERcon clavesUInt64fueron las más beneficiadas (mediana aproximadamente un 21 % más rápida y con un 38 % menos de memoria). #107189 (harikrishnan94). - Se ha añadido el algoritmo dpsub de enumeración del orden de uniones, que proporciona planes de unión óptimos con una menor sobrecarga de optimización que dpsize y admite uniones que no son internas. #107351 (fkastrati).
- Se evita convertir agregaciones de un solo nivel con bajo uso de memoria en agregaciones de dos niveles, asociando un rastreador de memoria al estado de agregación en lugar de usar la memoria de toda la consulta. #107490 (m-selmi).
- Se evita construir el AST completo de la consulta durante el análisis de consultas de agregación, ya que la clave de caché de estadísticas de tamaño de la tabla hash de agregación se calcula a partir del plan de consulta en lugar del AST. #107643 (novikd).
- Se permite pasar de la unión
hashusada en la primera ejecución de una consulta aparallel_hashen las ejecuciones posteriores, en función de las estadísticas de tiempo de ejecución recopiladas en la primera ejecución. #108125 (m-selmi). - Se utiliza el tamaño de la tabla hash obtenido de las estadísticas de unión en tiempo de ejecución para optimizar el tamaño de los filtros en tiempo de ejecución de JOIN en ejecuciones posteriores de la consulta. Puede controlarse mediante la nueva configuración
join_runtime_filter_size_from_hash_table_stats. #108313 (m-selmi). - Acelera y reduce el uso de memoria de las consultas
DISTINCTsobre tablasMergeTreeparticionadas al mantener las filas de cada partición dentro de un único stream, de modo que elDISTINCTpreliminar de cada stream trabaje sobre un conjunto disjunto de claves, en lugar de que el mismo conjunto de claves aparezca en variosDISTINCTpreliminares. Esto se aplica cuando la expresión de partición es una función determinista de las columnas delDISTINCT, y está condicionado por una heurística de costo basada en el número de particiones y su desequilibrio (que puede activarse o desactivarse mediante el settingforce_distinct_partitions_independently, deshabilitado de forma predeterminada). Esta misma propiedad de disyunción por partición se propaga a través de los pasosExpression,FilteryARRAY JOINhasta los consumidores finalesDISTINCT,LIMIT BYyGROUP BY, para que también puedan omitir su fusión. Se controla mediante los nuevos settingsallow_distinct_partitions_independently(habilitado de forma predeterminada) ymax_number_of_partitions_for_independent_distinct, que permite ajustar la heurística. #108326 (nihalzp). - Los filtros en tiempo de ejecución ahora se construyen sobre las claves de igualdad incluso cuando la cláusula
ONtambién contiene predicados de no igualdad, lo que reduce el número de filas que entran en la unión hash en uniones mixtas de igualdad y no igualdad.LEFT ANTI JOINno se ve afectado. #108579 (29antonioac). - Se reduce el umbral de precarga por software para las tablas hash de agregación y de unión de
4 * L2 cache sizeaL2 cache size, de modo que la precarga se habilite en cuanto la tabla hash deje de caber en la L2. Esto corrige una regresión enGROUP BYyJOINsobre tablas hash de tamaño medio (~1-8 MiB) en plataformas que reportan una L2 grande (p. ej., aarch64 con una L2 de 2 MiB). #108655 (groeneai). - Mejora del rendimiento de las funciones de ventana. Las consultas de ventana sobre tablas anchas que incluyen
SELECT *ahora consumen bastante menos memoria y se ejecutan más rápido. Las agregaciones de ventana, comoquantile*,uniq*ygroupArray, son más rápidas conOVER ()yOVER (ORDER BY ... RANGE ...). La funcióncume_disttambién es más rápida, y las ventanas que usanPARTITION BYuORDER BYahora rinden mejor en columnas con muchos valores repetidos. #108688 (nihalzp). - Las consultas de agregación sin funciones de agregación ahora usan métodos basados en
HashSeten lugar deHashMap(para los tipos de clave compatibles). Se han observado aceleraciones de hasta 1,8 veces. #108862 (nickitat). - Se reduce la sobrecarga causada por la contención de bloqueos en el algoritmo de unión
parallel_hash. #108938 (m-selmi). - Se añadió un nuevo valor de
join_algorithm,parallel_full_sorting_merge: para uniones de igualdad compatibles con hash, divide una full sorting merge join en segmentos según el hash de las claves de unión, lo que genera merge joins independientes por segmento que se ejecutan en todos los hilos. Conserva el bajo uso de memoria en streaming propio de una merge join y, al mismo tiempo, la paraleliza (en un benchmark, fue ~2,4 veces más rápida y usó ~3,3 veces menos memoria queparallel_hash). Las unionesASOFrecurren a un únicofull_sorting_merge; los tipos de clave incompatibles con hash (punto flotante,JSON,Object,Dynamic) omiten solo la reescritura de dispersión por hash y aún pueden segmentarse en el origen por rangos de clave primaria cuandoquery_plan_join_shard_by_pk_rangesestá habilitado. El resultado no está ordenado. #109005 (alexey-milovidov). - Las estadísticas de columnas ahora se materializan de forma predeterminada en
INSERTcuando el tamaño activo actual de la tabla más el tamaño del bloque escrito no supera el valor del nuevo ajustematerialize_statistics_on_insert_max_table_size(predeterminado: 25 GiB); la comprobación se realiza por cada bloque escrito, por lo que una primera carga masiva en una tabla vacía puede seguir materializando estadísticas para cada bloque escrito. Esto proporciona al optimizador de uniones basado en costes estimaciones precisas para tablas de dimensiones recién cargadas y evita órdenes de unión patológicos (por ejemplo, TPC-H Q5 y Q8 ya no agotan el tiempo de espera con un factor de escala de 40), mientras que las tablas de hechos grandes y consolidadas siguen materializando estadísticas durante las fusiones. #109454 (alexey-milovidov). - Se ha optimizado la función de agregación
uniqCombineden el caso de agregación sin clave. #109794 (CurtizJ). - Se han optimizado las funciones de agregación
uniqHLL12yuniqCombined. #109831 (CurtizJ). - Se paraleliza el procesamiento de filas no unidas en el algoritmo de unión
parallel_hashen dos casos más: cuando existe un filtro residual y cuando las claves de unión son pequeñas (mapa hash de un solo nivel). #110008 (m-selmi). - Se desplaza un filtro por debajo de una función de ventana cuando el predicado solo hace referencia a las columnas
PARTITION BYde la ventana. Un predicado de este tipo escrito después de la ventana (unWHEREexterno que envuelve una subconsulta con ventana, o un término de una conjunción enQUALIFY) ahora llega al almacenamiento y permite la poda por clave primaria o partición, así como el uso de índices de omisión y proyecciones. Por ejemplo,SELECT ... row_number() OVER (PARTITION BY key ORDER BY ts) AS rn ... QUALIFY rn = 1 AND key = 'x'ya no lee ni aplica la ventana a toda la tabla. #110114 (groeneai). - Con
join_use_nulls = 1, unWHEREque rechaza valores NULL y que hace referencia a columnas de ambos lados de una unión externa (p. ej.,WHERE l.k = 42 AND r.k = 42) ahora convierte la unión enINNER(oLEFT/RIGHT) y poda la clave primaria, igual que conjoin_use_nulls = 0. Anteriormente, la conversión se omitía en este caso y ambas tablas se leían por completo. #110121 (groeneai). - Se han optimizado las funciones
uniq,uniqExactyuniqHLL12en agregaciones sin clave. #110150 (CurtizJ). - Un
JOINcuya condiciónONes siempre falsa (p. ej.,ON 1 = 2,ON NULLo una condición que se reduce a falso, comoa.t = 'A' AND a.t = 'B') ya no lee el lado que no aporta resultados. Una nueva optimización del plan de consulta sustituye por una fuente vacía los lados de entrada que no pueden aportar ninguna fila. Se controla mediante el ajustequery_plan_short_circuit_constant_false_join(habilitado de forma predeterminada). #110234 (groeneai). - Se paraleliza la fusión final de las tablas hash de agregación de un solo nivel: el espacio de claves se divide en particiones hash disjuntas que los threads fusionan de forma independiente (ajuste
enable_parallel_single_level_merge, habilitado de forma predeterminada). Acelera las consultasGROUP BYcuyas tablas hash por thread no alcanzan el umbral de dos niveles, pero cuya fusión ocupaba la mayor parte del tiempo de ejecución. #110395 (nihalzp). - Las claves de agregación de un único
Stringahora usan una representación de tabla hash más compacta, lo que mejora las cargas de trabajo deGROUP BYcon uso intensivo de cadenas. La nueva configuraciónenable_packed_string_keys_in_aggregationestá habilitada de forma predeterminada; si se deshabilita, o si se establececompatibilitypor debajo de26.8, se restablece la ruta heredada deStringHashTable, que puede ser más rápida para claves de cardinalidad muy baja con una longitud superior a 11 bytes. #110573 (harikrishnan94). #112089 (harikrishnan94). - Se mejora el rendimiento de full sorting merge join entre 1,5 y 3 veces en escenarios dispersos. #111200 (vdimir).
- Se habilita
join_runtime_filter_from_fixed_hash_tablecuando los tipos de join key de sondeo y de construcción difieren (por ejemplo, una clave de sondeo Nullable con una clave de construcción no Nullable). #111244 (m-selmi). - Se mejora el rendimiento de las uniones
RIGHTyFULLcon el algoritmoparallel_hashcuando el lado derecho contiene join keysNULLo filas filtradas por la expresiónON, ya que se evita reconstruir los mapas de nulos. #111258 (m-selmi). - Nuevo algoritmo adaptativo para
GROUP BYen paralelo (controlado mediante la configuraciónenable_adaptive_aggregator, habilitada de forma predeterminada): cada hilo agrega en su propia tabla hash hasta que esta contieneadaptive_aggregator_freeze_thresholdclaves y, en ese momento, la congela. Así, las claves frecuentes siguen actualizando las pequeñas tablas residentes en caché sin necesidad de coordinación, mientras que las claves poco frecuentes se enrutan según su hash a colas pendientes por bucket y se agregan exactamente una vez, dentro de la fusión paralela por bucket. #111459 (nihalzp). - Se acelera el hashing por fila de los valores de columnas JSON/
Objectalmacenados en datos compartidos (que utilizan, por ejemplo,uniq/uniqExactsobre una columna JSON y las claves hash deGROUP BY/DISTINCT), ya que se evita reconstruirColumnDynamicpara cada valor. Los valores hash no cambian. #111501 (valerypetrov). - Se mejora el rendimiento de RIGHT y FULL hash JOIN con múltiples disyunciones
ORen la sección ON, así como de RIGHT/FULL JOIN con condiciones residuales (de desigualdad). #111590 (m-selmi). - La lectura en orden a través de un JOIN ahora también funciona cuando un hash join tiene configurado un umbral automático de volcado a disco (el valor predeterminado desde 26.5). Cuando se aplica esta optimización, la unión permanece en memoria para conservar el orden del lado izquierdo; establezca
query_plan_read_in_order_through_spilling_join = 0para restaurar el comportamiento anterior, en el que dichas uniones no se utilizan para la lectura en orden y pueden volcarse a disco libremente. Además, con este cambio, unORDER BY ... LIMITsobre unLEFT JOINleído en orden ya no indica la tabla completa como número de filas que prevé leer, por lo que deja de activarmax_rows_to_readconread_overflow_mode = 'throw'en lecturas que terminan anticipadamente. #111973 (alexey-milovidov). - Se vuelve a habilitar la optimización de claves consecutivas para la agregación de
TTL ... GROUP BYdurante las fusiones. El agregador se construía pasandomin_chunk_bytes_for_parallel_parsing(un umbral en bytes, 10 MiB de forma predeterminada) en la posición que corresponde amin_hit_rate_to_use_consecutive_keys_optimization(una tasa de aciertos en[0, 1], 0,5 de forma predeterminada), por lo que la optimización quedaba deshabilitada permanentemente en esa ruta. Los resultados no se ven afectados. #112314 (groeneai). - La replicación diferida de columnas para
ARRAY JOINya no se pierde cuando se serializa un plan de consulta. Conserialize_query_plan = 1, el nodo que ejecutaba un fragmento de plan remoto ignorabaenable_lazy_columns_replicationy siempre materializaba todas las copias replicadas, aunque esta configuración está habilitada de forma predeterminada. #112330 (groeneai). - Una igualdad en
WHEREahora se fusiona con la condición deJOINcuando sus operandos tienen tipos distintos pero comparten un supertipo común, comoInt32yNullable(Int32). Esto permite convertir una unión CROSS en una unión INNER. #112630 (m-selmi). - Se corrigió la reasignación cuadrática al replicar un
Arraycuyos elementos contienen valoresJSONen datos compartidos, por ejemplo, unArray(JSON)constante pasado a una función de agregación. En estas consultas, la cantidad de bytes copiados crecía de forma cuadrática con el número de filas. #112897 (groeneai). - Se restaura la poda de partes y gránulos cuando los límites de un predicado de rango sobre una clave primaria o de partición de MergeTree se proporcionan mediante una cláusula
JOIN ONcontra un lado constante de una sola fila, por ejemplo,SELECT count() FROM t JOIN bounds ON t.d >= bounds.lo AND t.d <= bounds.hi. Desde la versión 25.2, una consulta de este tipo leía todas las partes, y la configuraciónquery_plan_use_logical_join_step, que antes permitía restaurar la poda, quedó obsoleta en la 26.5, por lo que no había forma de recuperarla. #112957 (groeneai). - Se corrigió la complejidad cúbica de la planificación de consultas para un JOIN con una tabla
Mergesobre muchas tablas con estructuras diferentes. Anteriormente, estas consultas podían pasar minutos en la fase de planificación sin responder amax_execution_timeni aKILL QUERY. #113140 (alexey-milovidov). - Se corrigió una regresión de rendimiento por la que una agregación sin claves
GROUP BYserializaba en cada ejecución todo el subárbol de su plan de entrada, incluido el contenido completo de los literales resultantes del plegado de constantes, para calcular una clave de caché del tamaño de la tabla hash que nunca llega a utilizar. Una consulta comoSELECT quantileMerge(arrayJoin(arrayMap(x -> state, range(5000000))))dedicaba unos 63 ms por ejecución a la optimización del plan de consulta; ahora dedica 0,15 ms. #113333 (groeneai). - Los operadores de agregación de PromQL
topk,bottomkylimitkse evalúan ahora con un plan de streaming cuyo estado de selección esO(time_steps * k), en lugar de reunir todas las series en una sola fila con una memoria intermedia deO(time_steps * series^2). Las consultas sobre métricas de alta cardinalidad que antes fallaban conMEMORY_LIMIT_EXCEEDEDahora se ejecutan con memoria acotada, y la evaluación se paraleliza en lugar de ejecutarse en un solo hilo. #113656 (nikitamikhaylov). - Se sustituyó el mapa hash por bucket de las funciones de agregación
timeSeries*ToGridpor un array plano y ordenado de muestras: la ingesta de muestras pasa a ser una inserción al final en O(1) para entradas ordenadas (el caso más habitual con diferencia) y desaparece la copia y ordenación por bucket durante la finalización. #113681 (nikitamikhaylov). - Las subexpresiones de PromQL compartidas por varios pasos del plan (el operando de
topk/bottomk/limitky el lado izquierdo deor) se evalúan ahora una sola vez en lugar de dos: el SQL generado a partir de PromQL materializa las subconsultas compartidas. Esto elimina un escaneo duplicado de la tabla de muestras;topksobreratees aproximadamente el doble de rápido en frío, y las consultas de reglas de kubernetes-mixin mejoran entre un 10 y un 29 %. #113772 (nikitamikhaylov). - La caché de condiciones de consulta ahora está habilitada de forma predeterminada para las consultas que usan la optimización
ORDER BY <column> LIMIT n(TopK). Establezcause_query_condition_cache_for_top_k = 0para desactivarla. #111492 #114539 (alexey-milovidov). - Se paraleliza la conversión de un nivel a dos niveles de los estados de agregación por thread antes de la fusión. Esto corrige una regresión de 2-3x en consultas
GROUP BYcortas con estados de agregación pesados (p. ej.,COUNT(DISTINCT ...), ClickBench Q10/Q11) en máquinas con un número muy elevado de núcleos, introducida en las builds de desarrollo de la 26.7 al hacer precisa la contabilización de memoria de la agregación. #114691 (alexey-milovidov). - Se aceleran las funciones de ventana sobre tablas
MergeTreeparticionadas: cada partición se lee mediante su propio stream y las ventanas se evalúan por partición, lo que evita la dispersión por hash que normalmente redistribuye todas las filas entre threads antes de ordenar la ventana. Esto se aplica cuando la expresión de partición de la tabla es una función determinista de las columnasPARTITION BYde la ventana, y está sujeto a la misma heurística de coste queGROUP BY/DISTINCTpor partición (suficientes particiones en relación conmax_threadsy ninguna partición dominante). Se controla mediante los nuevos ajustesallow_window_partitions_independently(habilitado de forma predeterminada),force_window_partitions_independentlyymax_number_of_partitions_for_independent_window. #114783 (nihalzp). - Se aceleran las funciones de agregación
timeSeries*ToGrid: el cálculo del bucket de cada muestra ya no utiliza la división Int128, y las muestras consecutivas en el mismo bucket se saltan la búsqueda en el mapa hash. #114889 (nikitamikhaylov). - Las funciones de agregación
timeSeries*ToGridprocesan ahora las muestras en secuencias de muestras consecutivas que caen en un mismo bucket de la cuadrícula, lo que acelera entre 1,2 y 2 veces la etapa de ingesta de muestras detimeSeriesRateToGridy funciones relacionadas sobre datos de series temporales ordenados. #115041 (nikitamikhaylov). - Una agregación sin claves
GROUP BYya no reparte su salida de una sola fila entremax_threadsstreams, por lo que las consultas cuyo plan continúa tras dicha agregación obtienen un pipeline mucho más pequeño (menos procesadores que crear, planificar y perfilar) sin perder paralelismo. #115170 (nikitamikhaylov). - Evaluación más rápida de las consultas instantáneas de PromQL: las funciones de agregación
timeSeries*ToGridusan la ruta vectorizada de clasificación de muestras para cuadrículas de un solo punto, ytimeSeriesIdToGrouprellena directamente su columna de resultado. #115267 (nikitamikhaylov). - Un
JOINcuya secciónONcontiene varias igualdades combinadas conORya no materializa las columnas de clave del lado derecho que la consulta no selecciona. #115465 (nickitat). - Se acelera la construcción de la tabla hash de una unión
ANY,SEMIoANTIcuando el lado derecho repite muchas veces las mismas claves de unión: la unión ya no vuelve a leer el ajustejoin_any_take_last_rowdesde memoria para cada fila del lado derecho. #115820 (nickitat). - Se acelera
GROUP BYsin funciones de agregación sobre clavesString,FixedStringyLowCardinality: la consulta ya no reescribe un marcador de posición no utilizado en la tabla hash para cada fila, sino solo para las filas que añaden una clave nueva. #115834 (nickitat). - Se redujeron el uso de memoria y el tiempo de optimización del plan de consulta en agregaciones con clave sobre literales grandes resultantes del plegado de constantes. La clave de caché de estadísticas de la tabla hash de agregación ahora se calcula mediante hash a medida que se serializa, en lugar de acumularse primero en memoria, de modo que un plan que contiene un literal grande ya no conserva una copia de este durante la optimización. Con un literal de 80 MB, el pico de memoria disminuye en unos 250 MB y el tiempo de optimización se reduce aproximadamente 2,5 veces. La clave calculada no cambia. #115847 (groeneai).
- Se optimizan las consultas
GROUP BY ... ORDER BY ... LIMITyGROUP BY ... LIMITmediante un heap acotado durante la agregación, que permite descartar los grupos que no pueden aparecer en el resultado. Esto reduce significativamente el uso de memoria y el tiempo de ejecución en agrupaciones de alta cardinalidad. Se controla mediante la configuraciónenable_group_by_top_k_optimization. Basado en la implementación inicial de Dmitriy Terenichev #96630 (thevar1able).
Optimización y ejecución de consultas
- La lectura en orden con réplicas paralelas ahora utiliza la misma lógica que la lectura local para dividir la tabla en
max_threadspartes, lo que mejora el paralelismo. #101434 (nickitat). - Se añade al lector de Parquet la poda espacial de GeoParquet a nivel de grupo de filas y de página. La poda a nivel de grupo de filas omite grupos de filas completos cuyo cuadro delimitador no se solapa con la geometría de la consulta. La poda a nivel de página utiliza el índice de columna
covering.bboxpara omitir páginas irrelevantes dentro de los grupos de filas. Además, se generaliza el pushdown de predicados espaciales medianteIFunctionBase::isSpatialPredicate()y se añade unGeoFilterque evalúa predicados espaciales durante la lectura de filas de Parquet. #104435 (bacek). - Se añadió el setting
use_constant_folding_in_index_analysis(deshabilitado de forma predeterminada). Cuando está habilitado, el análisis de clave primaria,MinMaxe índices de omisión deMergeTreeincorpora las constantes a nivel de partición en el predicado del filtro por separado para cada parte, lo que mejora la poda en filtros cuyas ramas dependen de valores de partición, p. ej.,(a = 1 AND b >= 1) OR (a = 2 AND b > 10)conPARTITION BY a. #104582 (Michicosun). - Se aplica el posicionamiento exacto de filas en consultas de búsqueda vectorial con
vector_search_with_rescoringantes de la evaluación exacta de distancias en el pipeline de la consulta. #105591 (skuznetsov). - Se añadió una optimización del plan de consulta que desplaza las funciones que reducen el volumen de datos (
length,lengthUTF8,empty,notEmpty) por debajo de los pasosSortingyFilter, sustituyendo el argumento amplioString/FixedStringpor el resultado de tamaño fijo, de modo que ni se almacena en búfer durante una ordenación ni se copia en un filtro. Se controla mediante el nuevo settingquery_plan_push_down_volume_reducing_functions, habilitado de forma predeterminada. #106199 (fastio). - Se acelera la carga de la caché del sistema de archivos durante el arranque al codificar el tamaño de cada archivo de caché en su nombre (
<offset>_<size>), lo que evita una llamadastatpor archivo. Se sigue admitiendo la carga de archivos de caché escritos por versiones anteriores. #107415 (alexey-milovidov). - Se mejoró el rendimiento de las consultas de búsqueda de texto combinadas con un filtro de clave primaria. #108114 (CurtizJ).
- Se mejora el rendimiento de la función
pointInPolygoncon un polígono constante. La caché de polígonos preprocesados ahora usa como clave los argumentos constantes sin procesar, de modo que un polígono constante se analiza una sola vez (ante un fallo de caché) en lugar de volver a analizarse en cada bloque de entrada. #108184 (groeneai). - Se evita mantener los contadores de selectividad de
system.predicate_statistics_logen la ruta de lectura de MergeTree cuando la funcionalidad está deshabilitada (predicate_statistics_sample_rate = 0, el valor predeterminado). Esto elimina una actualización atómica por gránulo y un popcountO(rows)del filtro en cada lectura, lo que corrige una regresión de rendimiento especialmente visible en aarch64. #108190 (groeneai). - Se añade el setting
merge_use_batch_sorting_queueMergeTreepara usar opcionalmente la cola de ordenación por batch en las fusiones ordinarias deMergeTree, lo que reduce el tiempo de CPU y el tiempo real en cargas de trabajo de fusión en las que la fusión ordenada supone un coste significativo. #108468 (rorylshanks). - Se acelera la planificación de consultas con el analizador para expresiones que hacen referencia al mismo alias
WITHo repiten la misma subexpresión muchas veces (por ejemplo, cadenasif/multiIfprofundamente anidadas), ya que las subexpresiones compartidas no se reconstruyen al construir el DAG de acciones. #108523 (novikd). - Se aceleró el análisis de consultas que contienen muchas cadenas
ANDde comparaciones o cadenas muy largas: la optimizaciónoptimize_and_compare_chainahora está limitada por un presupuesto de trabajo (nueva configuraciónoptimize_and_compare_chain_max_hash_work) en lugar de calcular el hash de una gran parte del árbol de la consulta, y la resolución de lambdas ya no recalcula los hashes del cuerpo de la lambda para su protección contra la recursión. #108757 (alexey-milovidov). - Los posprocesamientos que solo filtran (
if(..., '', token)) ahora construyen el gránulo a partir de los tokens sin procesar y descartan los vacíos durante la construcción, con lo que se evitan la materialización por ocurrencia y la ejecución deActionsDAGpropias de la ruta general. #109049 (ahmadov). - Se eliminó un cuello de botella monohilo en
ShuffleSendStepdel plan de consulta distribuida: ahora cada stream de origen reparte sus filas por bucket de destino de forma independiente, en lugar de canalizar todo el fragmento a través de un únicoScatterByPartitionTransform. #109206 (davenger). - Se redujo la sobrecarga de CPU en la evaluación de expresiones para consultas con un gran número de columnas (p. ej., búsqueda vectorial sobre una columna
QBitcon un paso pequeño, donde cada vector se expande en cientos de subcolumnas de planos de bits que se pasan todas a una única llamada*DistanceTransposed). #109380 (alexey-milovidov). - Se desplaza un filtro por debajo de
LIMIT BYcuando el predicado hace referencia únicamente a las columnas clave deLIMIT BYy la cláusula conserva al menos una fila por grupo no vacío (LIMIT n BYconn >= 1yOFFSET 0). Así, estos predicados (escritos como unWHEREexterno que envuelve una subconsulta conLIMIT BY) llegan al almacenamiento y pueden aprovechar la poda por clave primaria, los índices de omisión y las proyecciones, en lugar de leer toda la tabla y aplicar primero el top-N por grupo, sin cambiar la semántica de excepciones deOFFSET,LIMIT 0 BYni las formas negativas deLIMIT BY. #110116 (groeneai). - Se evita una asignación en el heap por cada comprobación de hiperrectángulo en el análisis del índice de clave primaria, lo que acelera el filtrado de marcas entre un 5 y un 26 % según la forma de la consulta. #110153 (raimannma).
- El push-down de filtros en Parquet (poda de grupos de filas e índices de columna) ahora admite conversiones entre variantes de
DateTime64, variantes deDecimalyFloat32/Float64. #110457 (al13n321). - Se optimizó la construcción de índices de omisión de texto y basados en filtro Bloom con el tokenizador sparseGrams #110541 (UnamedRus).
- Se combina el coste de E/S con la selectividad al ordenar las condiciones de PREWHERE. Esto corrige una regresión de rendimiento en la ejecución de PREWHERE que se producía en algunos casos desde https://github.com/ClickHouse/ClickHouse/pull/101275. Parte de https://github.com/ClickHouse/ClickHouse/issues/110462 #110695 (Avogar).
- Se reduce el cálculo de hashes de los tokens definidos en el filtro
IN/NOT INdel posprocesamiento. #111690 (ahmadov). - Las funciones mapContainsKeyLike, mapContainsValueLike, mapExtractKeyLike y mapExtractValueLike con un patrón no constante consumen menos memoria y tiempo cuando enable_lazy_columns_replication está habilitado. El patrón ya no se copia de forma anticipada por cada entrada del mapa en el momento de la captura; la copia se aplaza hasta la ejecución de la lambda interna y se libera antes, de modo que en el pico de uso existe una copia expandida menos del patrón. #111749 (diegomestre2).
- Se habilitaron de forma predeterminada (y se promovieron a beta) dos funcionalidades en disco: 1)
packed_skip_index_max_bytes = '1M': los subflujos de índices de omisión de hasta 1 MiB ahora se escriben en un único archivoskp_idx.packedpor parte, lo que reduce el número de objetos y de solicitudes de escritura en el almacenamiento de objetos. Compatibilidad: solo se ven afectadas las partes escritas a partir de ahora, que siguen siendo totalmente legibles en versiones anteriores; las versiones previas a la 26.6 simplemente no utilizan los índices empaquetados para la poda (se tratan como no materializados). Establezcapacked_skip_index_max_bytes = 0para mantener la disposición independiente de un archivo por índice. 2)compute_exact_num_defaults_for_sparse_columnsjunto conoptimize_trivial_count_with_sparsity_filter: los contadores exactosnum_defaultspor columna se persisten y se utilizan para responder aSELECT count() FROM t WHERE <pred>sin escanear datos cuando el predicado divide las filas entre valores predeterminados y no predeterminados. Compatibilidad: las versiones anteriores ignoran el indicadorexact_num_defaultsdeserialization.json, por lo que las partes siguen siendo totalmente legibles tras volver a una versión anterior; la reescritura del conteo solo se aplica a las partes que contienen contadores exactos, de modo que los resultados siguen siendo correctos en tablas con partes mixtas. #111816 (Algunenano). - La optimización de condiciones transitivas ahora utiliza su filtro adicional únicamente para el análisis de índices cuando no puede aplicar el filtro completo. Consulte la configuración
optimize_and_compare_chain. #112076 (yariks5s). - La API de consultas de Prometheus (
/api/v1/query,/api/v1/query_range) del motor experimental TimeSeries ahora ejecuta las consultas en paralelo en lugar de en un único hilo. #112108 (nikitamikhaylov). randomHadamardTransformaplicado a un vector constante ahora se evalúa una sola vez en lugar de una vez por fila. Esto acelera las consultas de búsqueda vectorial que rotan el vector de consulta conrandomHadamardTransformantes de compararlo con una columnaQBit. #112921 (alexey-milovidov).- Se restablece el uso compartido de conjuntos entre las tareas por parte de una misma mutación que filtra con
IN (subquery)sobre una columna de clave primaria.enable_sharing_sets_for_mutationsestá activado de forma predeterminada, pero el conjunto construido para el análisis de la clave primaria había dejado de participar en la caché compartida, por lo que una tabla con N partes materializaba el mismo conjunto N veces. #112941 (groeneai). - En los planes de consulta distribuidos (
make_distributed_plan),ORDER BY ... LIMIT kahora utiliza materialización diferida en cada réplica: las columnas anchas se leen solo para las k primeras filas locales de esa réplica en lugar de para cada fila candidata. #113111 (shankar-iyer). - Se acelera la planificación de consultas cuando se utilizan estadísticas de columna
uniq_v2. El número estimado de valores distintos ahora se almacena en caché en lugar de recalcularse en cada solicitud, algo que la planificación emite muchas veces por consulta. #113357 (groeneai). - La aplicación anticipada de filtros (filter pushdown) ahora funciona con subcolumnas
Tupleen archivos Parquet y ORC. Un predicado comoWHERE tup.1 = 555555sobrefile(),s3()ourl()ahora poda grupos de filas e intervalos del índice de filas utilizando las estadísticas propias del elemento de la tupla en lugar de leer el archivo completo. #113383 (groeneai). - Se mejora el rendimiento de las consultas PromQL sobre el motor TimeSeries: el SQL interno del selector ahora lee directamente las columnas de clave primaria de la tabla de muestras (sin conversiones de tipo superfluas) y comprueba el rango de marcas de tiempo antes que el conjunto de identificadores de series, lo que hace que las consultas en frío con uso intensivo de selectores sean entre un 30 % y un 44 % más rápidas. #113768 (nikitamikhaylov).
- Los selectores de PromQL que coinciden con todas las series de una métrica ahora filtran la tabla de muestras de una tabla
TimeSeriescon un rango continuo de clave primaria sobreiddurante el análisis de índices, en lugar de usar una condiciónid IN <set>de gran tamaño, cuando la estructura del id es una tupla de dos componentes con el generador de id canónico. Esto elimina el principal coste monohilo del análisis de índices en consultas PromQL con muchos selectores: hasta un −45 % de latencia en frío en los patrones de consulta de dashboards y reglas, y un −11 % en la media geométrica en frío sobre el conjunto completo de pruebas en una tabla de 62 000 millones de muestras. #114131 (nikitamikhaylov). - Los endpoints
/api/v1/queryy/api/v1/query_rangede la Prometheus HTTP API ahora evalúan una sola vez las subconsultas PromQL compartidas por varios pasos del plan, como ya hacían las funciones de tablaprometheusQueryyprometheusQueryRange. Anteriormente, las solicitudes realizadas conenable_analyzer = 0, o por un usuario cuyo perfil lo establecía, volvían a escanear la subconsulta compartida una vez por cada paso que la referenciaba. #114261 (groeneai). - Se corrigió una regresión de la versión 26.7: en una tabla
MergeTreeordenada portoUnixTimestamp(u otra conversión a entero) de una columnaDateTime64, un filtro de rango simple sobre esa columna ya no utilizaba la clave primaria y leía todos los gránulos de las partes coincidentes. Además, un filtro comotoInt64(ts) >= csobre una tabla ordenada directamente por la columnaDateTime64ahora utiliza la clave primaria. #114413 (alexey-milovidov). - Se acelera la ejecución de
INsobre columnas agrupadas (por ejemplo, ordenadas por la clave primaria) reutilizando el resultado de la fila anterior cuando las filas consecutivas son iguales. #114853 (nikitamikhaylov). - Se corrigió el coste cuadrático en tiempo que se producía cuando las funciones
h3kRing,h3ToChildren,h3PolygonToCellsyh3PolygonToCellsWithContainmentconstruían su resultado sobre muchas filas. Una consulta sobre 196 000 filas tardaba 838 segundos copiando memoria en una ejecución de pruebas de estrés de CI; ahora tarda unos 5 segundos. #115773 (groeneai). - Se optimizan las búsquedas inversas en diccionarios. Un predicado de igualdad constante como
WHERE dictGet(dict, attr, key_expr) = valueahora se pliega como constante directamente en un filtro de clave (key_expr = const,key_expr IN [...]oWHERE 0) en lugar de reescribirse como una subconsultaIN (SELECT ... FROM dictionary(...)), y la ruta constante dedictGetKeysahora se ejecuta en paralelo. #91164 (nihalzp). - Se añade una nueva configuración,
merge_tree_generic_exclusion_search_max_steps, que limita el número de pasos que el algoritmo de búsqueda de exclusión genérica dedica a analizar el índice de clave primaria de cada parte de datos. El presupuesto se invierte primero en los rangos de clave restantes más grandes, de modo que incluso un presupuesto pequeño descarta la mayor parte de los datos; los rangos que no se han analizado por completo se leen enteros, por lo que los resultados de la consulta siguen siendo correctos, aunque pueden leerse más gránulos. El límite se aplica de forma aproximada: puede superarse como máximo enmerge_tree_coarse_index_granularitypasos, más un paso por cada rango en que la parte ya esté dividida (por ejemplo, por la caché de condiciones de consulta). El valor predeterminado, 0, significa pasos ilimitados. #92779 (EmeraldShift). - Las consultas con
ORDER BYyLIMITsobreVIEWs definidas sobre tablas distribuidas ahora utilizan la optimización de fusión de flujos ordenados. ElORDER BY/LIMITexterno se traslada a la consulta interna de una vista simple, de modo que cada shard ordena sus datos localmente y el coordinador fusiona flujos ya ordenados, en lugar de realizar una ordenación completa en el coordinador. #94102 (matanper).
Rendimiento del almacenamiento, la E/S y los lagos de datos
- Usa los límites del índice minmax de partición para podar más gránulos durante el análisis de la clave primaria en tablas
MergeTree, cuando una columna de la clave primaria es también una columna de entrada de la clave de partición. Por ejemplo, en una tablaMergeTreeconORDER BY (id, event_time)yPARTITION BY toYYYYMM(event_time), ClickHouse usará el índice minmax de partición sobreevent_timedurante el análisis del índice de clave primaria para tomar decisiones de poda de gránulos mejor fundamentadas. Se controla mediante la nueva configuraciónuse_partition_minmax_for_primary_key_pruning(habilitada de forma predeterminada). #103480 (UnamedRus). - Acelera los operadores que recorren un stream ordenado en busca de secuencias de valores de clave iguales:
DISTINCTen orden,LIMIT BYen orden,LIMIT BYnegativo en orden y los joinsfull_sorting_mergeypartial_merge. #106502 (nihalzp). - El lector Parquet v3 ahora puede omitir grupos de filas completos mediante la página de diccionario (además de las estadísticas min/max y los filtros de Bloom) en condiciones de igualdad e
IN, cuando un fragmento de columna está completamente codificado por diccionario. Se controla mediante la nueva configuracióninput_format_parquet_dictionary_filter_push_down. #106952 (alexey-milovidov). - Usa libdeflate para la compresión y descompresión gzip/zlib/deflate, lo que las hace más rápidas (compresión ~1,15× con una mejor tasa de compresión, descompresión ~1,4–1,5×) para datos
.gz/HTTP/url/s3y para el códec GZIP de Parquet. #108074 (alexey-milovidov). - Acelera las funciones
trimLeft/trimRight/trimBothcon espacios en blanco predeterminados (y sus aliasltrim/rtrim/trim): las filas consecutivas que no necesitan recorte se copian en un único lote, y el escaneo de espacios por fila solo se ejecuta en las filas que realmente tienen un espacio inicial o final. #108177 (groeneai). - Acelera la lectura de tablas Iceberg precargando el siguiente archivo de manifiesto mientras se analiza el actual, de modo que la E/S se solapa con el trabajo de CPU. #108543 (asya-ch).
- Las consultas de búsqueda vectorial que usan reevaluación ahora limitan el cálculo exacto de distancias a las filas candidatas del índice vectorial, en lugar de reevaluar por fuerza bruta las filas vecinas del mismo gránulo
MergeTree. #108846 (skuznetsov). - Se añadió la configuración
merge_tree_min_bytes_per_read_streampara reducir el exceso de streams de lectura y la sobrecarga del pipeline en escaneosMergeTreelocales ordinarios, no ordenados y de columnas estrechas, en servidores con muchos núcleos. #109035 (jiebinn). - Acelera la serialización y las fusiones de columnas
JSONcuyos datos compartidos contienen muchas rutas dispersas. Al aplanar los datos compartidos en columnas por ruta,flattenAndBucketSharedDataPathsya no escanea todas las columnas de ruta acumuladas en cada fila ni inserta valores predeterminados celda a celda: se elimina el escaneo por fila sobre todas las rutas y los huecos se rellenan en bloque. #109341 (groeneai). - El protocolo nativo ahora envía las columnas
Stringcomo un stream independiente de desplazamientos de bytes acumulativos (la misma disposición que usaArraypara sus desplazamientos), seguido de los datos concatenados, en lugar de un prefijo de longitud varint por valor, siempre que ambos extremos usen la revisión de protocolo 54489 o posterior. Así, un cliente puede leer columnasStringcon una preasignación exacta del búfer y una única copia masiva, aproximadamente 4 veces más rápido que con la disposición por valor. Los clientes y servidores antiguos no se ven afectados, ya que la disposición se negocia mediante la revisión del protocolo. La misma disposición está disponible en los formatosNativeyBuffersmediante las nuevas configuracionesoutput_format_native_write_string_with_size_stream/input_format_native_read_string_with_size_stream(desactivadas de forma predeterminada para que los formatos sigan siendo portables). #110320 (vahid-sohrabloo). - Las consultas con
FINALque leen en el orden de la clave primaria (ORDER BYsobre un prefijo de la clave de ordenación) con unLIMITpequeño ya no usansplit_intersecting_parts_ranges_into_layers_final. #110431 (KochetovNicolai). - Materialización diferida (materialización tardía) al leer archivos Parquet desde almacenamiento de objetos, incluidas las tablas Iceberg: en las consultas
ORDER BY ... LIMIT n, las columnas que no se necesitan para ordenar ni filtrar solo se leen para lasnfilas que quedan tras aplicar elLIMIT. Con un archivo Parquet de 200 MB en S3,SELECT k, s ... ORDER BY k DESC LIMIT 10lee 3,3 MB en lugar de 171 MB (51 veces menos IO y 8 veces más rápido). Se controla mediante la nueva configuraciónquery_plan_optimize_lazy_materialization_for_object_storage(habilitada de forma predeterminada; también requierequery_plan_optimize_lazy_materialization). #110970 (alexey-milovidov). - Las consultas sobre tablas Iceberg con muchos archivos de eliminación ahora se inician más rápido. ClickHouse lee y decodifica los archivos de manifiesto de eliminación de forma concurrente en lugar de uno por uno, de modo que sus lecturas del almacenamiento se solapan. La nueva configuración
iceberg_delete_manifest_decode_concurrency(valor predeterminado:4) controla cuántos se decodifican simultáneamente. #112679 (asya-ch). - Se añade la serialización opcional en Parquet de UInt128/UInt256/Int128/Int256 como DECIMAL para permitir la poda de grupos de filas y de páginas. #113347 (bobrik).
- Se corrigió la multiplicación de solicitudes de lectura en discos remotos cuando un paso de la cadena de lectores lee rangos de marcas fragmentados, por ejemplo, rangos filtrados por índices primarios o de omisión. #113584 (CurtizJ).
- Se omite la comprobación redundante de ordenación al escribir partes de
MergeTreecuyas claves de ordenación son todas constantes. #113899 (perfloop-agent). - La materialización diferida para las consultas
ORDER BY ... LIMIT nahora también se aplica a archivos Parquet locales leídos con la función de tablafiley el motor de tablaFile: las columnas que no se necesitan para ordenar ni filtrar solo se leen para lasnfilas que quedan tras aplicar elLIMIT. La segunda lectura de un archivo seleccionado falla de forma segura con el nuevo errorFILE_CHANGED_DURING_READsi el archivo se modificó entre las dos pasadas. Se controla mediante la nueva configuraciónquery_plan_optimize_lazy_materialization_for_file(habilitada de forma predeterminada). También corrige un fallo de la materialización diferida para almacenamiento de objetos con el errorNot found column or subcolumn ... in blockcuando se difiere una subcolumna solicitada (p. ej., de una columnaJSON). #114262 (alexey-milovidov). - Se acelera la construcción del Set para
IN (subquery)en tablasMergeTreeparticionadas al mantener las filas de cada partición dentro de un único flujo y deduplicar cada flujo de forma independiente, de modo que la única transformada de llenado del Set —que antes calculaba el hash de cada fila en serie— solo recibe filas únicas. Esto se aplica cuando la expresión de partición es una función determinista de las columnas de salida de la subconsulta. La optimización no se aplica cuando la partición más grande contiene más del doble de filas que la partición promedio; la nueva configuraciónforce_creating_set_partitions_independently(deshabilitada de forma predeterminada) permite omitir esta comprobación. Se controla mediante la nueva configuraciónallow_creating_set_partitions_independently(habilitada de forma predeterminada). #114645 (nihalzp). - Las tablas de registro del sistema
MergeTreeno replicadas y rotadas que no tienen TTL se marcan ahora comotable_readonlypara evitar operaciones en segundo plano innecesarias. La configuracióntable_readonlyMergeTreeahora también suprime todo el trabajo en segundo plano en una tablaMergeTreesimple —fusiones regulares, de TTL (DELETE/MOVE/recompresión) y de recompresión, mutaciones en segundo plano y movimientos de partes en segundo plano— y rechaza los comandos de partición que modifican datos (ATTACH/MOVE/DROP/DROP DETACHED/FETCH/REPLACE PARTITIONyMOVE PARTITION ... TO TABLEhacia la tabla), además de las inserciones, mutaciones yOPTIMIZEque ya rechazaba. En consecuencia, una tablatable_readonlycon TTL deja de recuperar el espacio de sus datos expirados mientras la configuración esté habilitada. #95079 (matt-metivier).
Eficiencia de memoria y recursos
- Se reduce el uso de memoria de
UNLOCK SNAPSHOTal dejar de cargar la metadata de cada parte de datos que la ruta de desbloqueo no utiliza, lo que evita errores por falta de memoria en instantáneas con un número muy elevado de partes. #111849 (jkartseva). - Se reducen las asignaciones de memoria al leer la metadata de copias de seguridad: ahora cada entrada de archivo se mueve a los mapas en memoria en lugar de copiarse. #111718 (jkartseva).
Rendimiento de funciones, tipos y formatos
- Dar formato de texto a valores
Decimales mucho más rápido: hasta 190 veces para unDecimal256con una escala grande y alrededor de 1,6 veces para unDecimal64. En procesadores con AVX-512 IFMA, convertir enteros de 64 bits a texto es aproximadamente 1,4 veces más rápido. También se corrigió el redondeo detoDecimalString, que descartaba el acarreo procedente de la parte fraccionaria:toDecimalString(toDecimal64('9.995', 3), 2)devolvía9.00y ahora devuelve10.00. #112457 (thevar1able). - Se mejoró el rendimiento del algoritmo de unión
partial_mergesobre clavesFixedStringal comparar secuencias de valores de una sola vez, en lugar de realizar una llamada de comparación por cada valor. #105737 (4ertus2). HashJoinahora admite de forma nativa claves LowCardinality de cadena no anulables de una sola columna. #107264 (nickitat).- Se mejoró el rendimiento de
replaceAllyreplaceRegexpAllcuando tanto el patrón como el reemplazo son un único carácter (por ejemplo,replaceRegexpAll(s, ' ', '_')). Estos reemplazos ya no alteran la disposición de los valores String, por lo que ahora la columna se copia una sola vez y los bytes coincidentes se reescriben in situ, en lugar de ejecutar un bucle de búsqueda por cada coincidencia. #108178 (groeneai). - Se aceleró el análisis de la representación canónica de fecha y hora
YYYY-MM-DD hh:mm:ssen el modo best-effort (date_time_input_format = 'best_effort',cast_string_to_date_time_mode = 'best_effort'), que es el predeterminado. Con esto se recupera el rendimiento perdido por una regresión en el análisis, introducida al cambiar esos valores predeterminados debasicabest_effort. #108187 (groeneai). - Los literales de array y tupla profundamente anidados se analizan ahora en tiempo lineal en lugar de cuadrático. #108892 (alexey-milovidov).
- La función
toStartOfInterval(aliastime_bucket,date_bin) es hasta 5 veces más rápida para intervalosSECOND,MINUTEyHOUR. #109729 (raimannma). - Las funciones
arraySortyarrayReverseSortson varias veces más rápidas con arrays numéricos (incluidosDecimalyDateTime64) cuando se invocan sin una lambda. #109832 (raimannma). - Se aceleraron
addDays,addWeeks,subtractDaysysubtractWeekscon valoresDateTimeyDateTime64en zonas horarias de desplazamiento fijo (como UTC) mediante una ruta rápida basada en aritmética. #109836 (raimannma). - Se vectorizó la descompresión del códec
Delta. La decodificación ahora es entre 1,5 y 5 veces más rápida para tipos de datos de 8/16/32 bits, lo que acelera hasta un 20 % los escaneos de columnas comprimidas conDelta. #110189 (raimannma). - Se aceleraron las funciones de búsqueda de cadenas (
like,position,match,countSubstrings,hasToken, etc.) sobre columnasEnumcon una aguja constante: ahora se buscan solo los nombres distintos del enum y los resultados se asignan de vuelta a cada fila, en lugar de buscar en todas las filas. #110325 (alexey-milovidov). - Se ha mejorado hasta 1.5x el rendimiento de las funciones de búsqueda de subcadenas (
position,countSubstrings,multiSearch*,replaceAll/replaceOne, y sus variantes que no distinguen entre mayúsculas y minúsculas y UTF-8) con un needle no constante, gracias al uso de buscadores de cadenas basados en SIMD en la ruta por fila en lugar de una alternativa ingenua. #110580 (Algunenano). - Se ha mejorado el rendimiento de la combinación de bloques (squashing) y la fusión de columnas
DynamicyObjectcon muchas variantes dinámicas o rutas JSON. #110583 (cv4g). estimateCompressionRatioes más rápido con el códecNONE#111107 (rienath).- Se han acelerado la ordenación y otras operaciones basadas en comparaciones sobre columnas
JSONcuyas rutas se almacenan en datos compartidos. Antes, cada comparación de valores materializaba una columnaDynamictemporal y ejecutaba una deserialización binaria completa de ambos operandos, lo que hacía queORDER BYsobre dichas columnas fuera extremadamente lento. #111894 (groeneai). - La división de enteros de 256 bits (
Int256,UInt256yDecimal256) ahora calcula el cociente de 64 en 64 bits (un limb cada vez), mediante un bucle de divisiones 128 / 64 cuando el divisor cabe en 64 bits y el Algoritmo D de Knuth en caso contrario, en lugar de hacerlo bit a bit con división larga por desplazamiento y resta. Esto afecta aintDiv,modulo, la aritmética deDecimal256y la conversión de estos tipos a texto. #112477 (thevar1able). - La lectura de una columna
Nesteddesde un tipo codificado en binario (Native,RowBinaryconinput_format_binary_decode_types_in_binary_format) ya no convierte el tipo de nuevo en un nombre de tipo para volver a analizarlo. Además, un nombre de tipoTupleanidado mal formado ahora se notifica como error de sintaxis, en lugar de tardar un tiempo exponencial en función de su profundidad de anidamiento y fallar conTOO_SLOW_PARSING. #112560 (alexey-milovidov). - Se han acelerado las consultas PromQL sobre tablas TimeSeries:
timeSeriesIdToGroupahora reutiliza el grupo de la fila anterior cuando filas consecutivas tienen el mismo id de serie, lo que evita la serialización del id y la búsqueda en el hash para cada fila. #113580 (nikitamikhaylov).
Otras mejoras del rendimiento
- Se implementaron un lector y un escritor nativos para los formatos
ArrowyArrowStreamque no utilizan la biblioteca Apache Arrow, lo que evita copias y conversiones de datos adicionales. Ahora son la opción predeterminada (configuracionesinput_format_arrow_use_native_readeryoutput_format_arrow_use_native_writer) y son más rápidos tanto en lectura como en escritura. #106522 (alexey-milovidov). - Se optimizan los predicados
nullIf(key, sentinel) = constpara construir rangos de claves y permitir la poda mediante la clave primaria, las particiones y los índices de omisión. #107308 (adityaksolves). - El rendimiento de `INTERSECT ALL` y `EXCEPT ALL` (el modo predeterminado de `INTERSECT` y `EXCEPT`) se multiplica varias veces al indexar el multiconjunto por el valor de la fila en lugar de calcular el hash de cada fila con SipHash. #107649 (Algunenano).
- Se aceleran las funciones
match,extract,extractAll,replaceRegexpOneyreplaceRegexpAllcon expresiones regulares simples al compilarlas a código nativo con LLVM. Se controla mediante la nueva configuracióncompile_regular_expressions(habilitada de forma predeterminada); los patrones que quedan fuera del subconjunto admitido recurren de forma transparente al motor RE2. #108004 (alexey-milovidov). - Se aceleró la descompresión ZSTD en AArch64 (ARM) para columnas con offsets de coincidencia pequeños, como las columnas de enteros de ancho fijo, mediante la vectorización con NEON de las copias solapadas de offset corto. Por ejemplo, la descompresión de una columna
UInt64es hasta ~2.3 veces más rápida en AWS Graviton 4. #108049 (alexey-milovidov). - Se mejoró la velocidad de descompresión LZ4 para columnas de tamaño fijo y baja cardinalidad. #108175 (nickitat).
- Se mejoró el rendimiento de
levenshteinDistance(yeditDistance) con cadenas de longitud media en ARM al evitar asignaciones de memoria en el heap por cada fila en la ruta de código de Myers por bloques. #108185 (groeneai). - Se acelera el análisis de números de coma flotante a partir de texto con
precise_float_parsing = 1, que pasa a ser igual de rápido o más que el analizador predeterminado en casi todas las entradas. Además, se actualiza la biblioteca incluidafast_floata la v8.2.10. #108205 (Algunenano). - Las funciones de codificación y decodificación Base64 ahora utilizan
simdutf, lo que mejora su rendimiento. #108333 (thevar1able). - Se optimiza
DISTINCTpara claves costosas de alta cardinalidad. #108366 (nihalzp). - Se mejoró el rendimiento de las funciones matemáticas al habilitar optimizaciones del compilador que no preservan
errno. #108628 (nickitat). - Se acelera
estimateCompressionRatiopara columnas codificadas conT64al calcular el tamaño comprimido de forma analítica en lugar de comprimir los datos. #109054 (rienath). - Los JOIN ahora pueden usar el índice de clave primaria o el índice de omisión de la tabla del lado izquierdo para podar gránulos #109085 (shankar-iyer).
- Se mejora el rendimiento de las funciones geo de H3 (
h3ToGeoBoundary,h3ToGeo,h3CellAreaM2/h3CellAreaRads2,geoToH3) al calcular conjuntamente pares de seno/coseno y eliminar llamadas trigonométricas redundantes en las transformadas de coordenadas. Los resultados no cambian (son idénticos bit a bit). #109399 (alexey-milovidov). - Se mejora hasta 7 veces el rendimiento de las comparaciones (
<,>,<=,>=) de tipos de enteros anchos (Int128,UInt128,Int256,UInt256y los tipos basados en ellos, comoDecimal128), así como el de la conversión de enteros con signo aInt256(hasta 7 veces con datos de signo mixto), al eliminar las bifurcaciones del código de comparación y de extensión de signo. #109474 (raimannma). - Las funciones con un único argumento
Nullableno constante ahora comparten con el resultado el null map del argumento, en lugar de asignar y fusionar uno nuevo. #110151 (raimannma). - Se mejora en aproximadamente 1,3-1,5x el rendimiento de las funciones
arrayMinyarrayMaxsobre arrays numéricos, gracias a una reducción vectorizada en lugar de un bucle de comparación por elemento. #110163 (raimannma). - Se mejora el rendimiento de
DISTINCTcuando el stream de entrada está ordenado por un prefijo de las columnas deDISTINCT, por ejemplo,SELECT DISTINCT a, b FROM table ORDER BY a. Estas consultas se ejecutan hasta 2,4 veces más rápido. #110170 (nihalzp). - Rutas de procesamiento por lotes vectorizadas para
groupBitOr/groupBitAnd/groupBitXory la familia de varianza (varPop,varSamp,stddevPop,stddevSamp,skewPop,skewSamp,kurtPop,kurtSamp,covarPop,covarSamp,corr): hasta 4x más rápidas con el combinador-Ifen condiciones impredecibles, y hasta 3x más rápidas para la familia de varianza sin él. #110461 (raimannma). - Se optimiza el análisis del índice de texto. #110530 (CurtizJ).
- Se acelera el análisis de valores
UUIDa partir de texto (p. ej.,JSONExtractenLowCardinality(UUID),toUUID,CAST AS UUID) al validar y convertir los dígitos hexadecimales en una sola pasada en lugar de dos. #110625 (groeneai). - Se acelera la descompresión ZSTD en x86_64 para columnas con desplazamientos de coincidencia pequeños, como las columnas de enteros de ancho fijo, mediante la vectorización de copias superpuestas de desplazamiento corto con SSSE3
pshufb(el equivalente en x86_64 de la optimización NEON para AArch64 de #108049). #110909 (thevar1able). - Se acelera hasta 3x
groupUniqArraypara tipos numéricos gracias al uso de hashing CRC32 (como enuniqExact) y a la inserción por fila en línea (inlining). #110917 (raimannma). - Se mejora la eficiencia de las estadísticas de columna minmax y básicas para columnas de coma flotante. #111221 (cv4g).
- Devuelve los resultados de las consultas
COUNT()directamente a partir de la metadata de cardinalidad del índice de texto. #111494 (ahmadov). - Acelera
minymaxen tipos de 128 y 256 bits (Int128,UInt128,Int256,UInt256,Decimal128,Decimal256): hasta 1,8 veces más rápido con enteros anchos y hasta 3,4 veces más rápido con decimales anchos. #111965 (raimannma). - Corrige una regresión de rendimiento en la ingesta de
system.query_log. La construcción de las columnas de tipo mapaSettingsyasynchronous_read_countersera unas 6 veces más lenta que antes, lo que podía hacer queSYSTEM FLUSH LOGS query_logsuperara su tiempo de espera de 180 segundos en servidores que registran muchas consultas con numerosas configuraciones modificadas. #112210 (groeneai). - Añade una caché opcional para los tokens que no existen en los índices de texto. #112742 (rorylshanks).
- El registro asíncrono ahora utiliza una cola acotada sin bloqueos: los threads que escriben mensajes de log nunca se bloquean en un mutex ni despiertan a los threads de registro. #112803 (alexey-milovidov).
- Utiliza el índice de clave primaria para
pointInPolygoncuando el argumento de punto es una columna clave completa de tipoPoint(u otraTuplede dos elementos numéricos), p. ej.,pointInPolygon(coord, [...])en una tabla ordenada porcoord. Antes solo se analizaba la formapointInPolygon((x, y), [...])con dos columnas clave escalares. #112956 (alexey-milovidov). text_index_posting_list_apply_modeahora tienelazycomo valor predeterminado, de modo que las consultas sobre índice de texto decodifican las listas de postings bajo demanda, con granularidad de bloque empaquetado y mediante un cursor, en lugar de materializarlas por adelantado en mapas de bits en los índices de texto que tienen configuradoposting_list_codec. #113521 (CurtizJ).- Acelera las transformaciones vectorizadas de etiquetas de TimeSeries al sustituir la reasignación basada en hash por indexación directa cuando los ID de grupos de etiquetas ocupan un rango compacto. #114244 (fallintoplace).
- Mejora el rendimiento de las fusiones de índices de texto. #114525 (CurtizJ).
- Utiliza máscaras de presencia compactas para los operadores de conjunto de PromQL. #115224 (fallintoplace).
- Al adjuntar las tablas del sistema, ya no se copia dos veces la metadata de cada tabla, incluida su descripción completa de columnas, solo para establecer el comentario de la tabla. #115490 (thevar1able).
- Acelera las comprobaciones de series duplicadas en vectores de condición de PromQL compuestos íntegramente por ceros. #115822 (fallintoplace).
- Acelera
toUTCTimestamp/to_utc_timestampyfromUTCTimestamp/from_utc_timestampcon argumentosDateTime64y recupera el caudal que tenían antes de las correcciones previas de desbordamiento. Los resultados no cambian. #115838 (groeneai). - Se redujo el coste fijo de inicialización de la generación de datos aleatorios (
rand,rand64,randomString,randomFixedString,generateUUIDv4,generateUUIDv7) en x86-64. La mejora es apreciable cuando los bloques son pequeños; los valores generados no cambian. #116158 (Algunenano). - Ahora se puede habilitar el plegado temprano con evaluación en cortocircuito para los operadores integrados
andyordurante el análisis mediante el ajusteenable_function_early_short_circuit. Esto permite omitir la ejecución de subconsultas escalarescount()de una sola fila que son código muerto, sin renunciar a la inferencia de tipos habitual ni a la validación semántica. #83505 (fhw12345). - Se utiliza una única llamada de IO al búfer para vectores trivialmente serializables #89842 (Ergus).
- Se habilita
optimize_or_like_chainde forma predeterminada. #94517 (alexey-milovidov). - Se mejora el rendimiento al recuperar el registro de un único usuario de system.users cuando el servidor tiene muchos usuarios. #96699 (alistairjevans).
Mejoras
Mejoras en consultas y SQL
- Las CTE materializadas referenciadas desde varias ramas de una consulta
UNIONahora se materializan una sola vez y se comparten entre todas las ramas. Anteriormente, cada rama recibía su propia copia de la CTE, que se expandía en línea y se evaluaba por separado. #102107 (novikd). - Se omite el filtro en tiempo de ejecución de JOIN cuando se estima que el lado de sondeo es pequeño. La nueva configuración
join_runtime_filter_min_probe_rows(valor predeterminado:1000) controla el umbral. #104860 (vdimir). EXPLAIN [PLAN] actions=1, compact=1, pretty=1pasa a ser el comportamiento predeterminado. #105036 (Fgrtue).- Se ha reducido la latencia de cancelación en las formas positivas de LIMIT BY (LimitByTransform, LimitBySortedStreamTransform): KILL QUERY y Ctrl+C ahora interrumpen el procesamiento en el transcurso de un único bloque, en lugar de esperar a que finalice todo el paso. #106070 (rvasin).
- Las consultas JOIN ahora son compatibles con las réplicas paralelas automáticas. #106073 (nickitat).
- Se añade una nueva métrica asíncrona UntrackedMemory (visible en
system.asynchronous_metrics) que informa de la memoria ya asignada por los threads, pero aún no contabilizada en el contador global de seguimiento de memoria. Cada thread acumula localmente pequeñas asignaciones y las notifica en bloque. Esto ayuda a explicar las discrepancias entreMemoryTrackingy el uso real de memoria del proceso. Los mensajes de errorMEMORY_LIMIT_EXCEEDEDahora también incluyen la cantidad de memoria no contabilizada, lo que facilita entender por qué una consulta o el servidor alcanzó su límite de memoria. #106386 (mstetsyuk). - Cuando un
INSERTfalla porque la tabla de destinoTOde una vista materializada rechaza la escritura mientras se construye el pipeline de inserción (por ejemplo, si el destino es unaViewo no admite transacciones), el mensaje de error ahora indica el nombre de la vista materializada y de su tabla de destino, en lugar de mostrar únicamente el error de almacenamiento sin más contexto. #107234 (groeneai). ALTER TABLE ... MODIFY COLUMN <col> Tuple(...)sobre unTuplecon nombre ahora solo modifica la metadata cuando únicamente se añaden subcampos, por lo que es tan rápido como unADD COLUMNde nivel superior. Se habilita medianteSET allow_metadata_only_named_tuple_alter = 1. #107305 (amosbird).- Se ha añadido la configuración
materialized_postgresql_use_extended_date_and_time_types, definible en el momento de la creación, para el motor de base de datosMaterializedPostgreSQL. De forma predeterminada (habilitada), las columnasdate/timestampde PostgreSQL se infieren comoDate32/DateTime64; si se establece en0al ejecutarCREATE DATABASE, se infieren los tipos de menor rangoDate/DateTime. Esta configuración no se aplica al motor de tablaMaterializedPostgreSQL. #107428 (alexey-milovidov). EXPLAIN PLANahora marca como aproximadas (~~...) las filas de resultado estimadas de una unión cuando la estimación procede de una sugerencia o de un mecanismo de respaldo aleatorizado en lugar de las estadísticas de la tabla, lo que ayuda a identificar planes que carecen de estadísticas fiables para el reordenamiento de JOIN. #107666 (vdimir).INSERTen una tablaMergeTreeahora respeta la cancelación de la consulta ymax_execution_timeal escribir muchas partes, en lugar de poder seguir ejecutándose mucho tiempo después de haberse terminado. #107929 (al13n321).arrayFoldahora respeta la cancelación de consultas ymax_execution_time. Anteriormente, un fold sobre un array muy largo (por ejemplo,arrayFold(acc, x -> arrayPushFront(acc, x), range(number), emptyArrayUInt64())) ejecutaba todo el fold dentro de una única llamada a función y no podía interrumpirse, por lo queKILL QUERYy los límites de tiempo se ignoraban hasta que el fold terminaba. #108192 (groeneai).- Se añaden
ProfileEventspara cada fase previa a la ejecución de la consulta:QueryParseMicroseconds,QueryAnalysisMicroseconds,QueryPlanBuildMicrosecondsyQueryPipelineBuildMicroseconds. Permiten ver en qué se invierte el tiempo antes de ejecutar la consulta (análisis sintáctico, análisis, construcción del plan de consulta y construcción de la canalización) y están disponibles ensystem.query_logysystem.events. #108282 (jrdi). - Las operaciones
ALTER TABLEque generarían metadatos de tabla que superanmax_query_sizeahora se rechazan de antemano, lo que evita que componentes como la distribución de DDL o la recuperación de réplicas no puedan cargar las tablas. #108283 (lockie). - Se añadió
ConstantJoinpara uniones cartesianas y uniones con predicados constantes planificadas por el analizador, de modo que estas consultas ya no fallan por una configuraciónjoin_algorithmincompatible cuando se usa el analizador. #108289 (antaljanosbenjamin). - Se añadió a
system.documentationuna columnasourcecon la ruta del archivo fuente donde se define la documentación de cada entidad. La tabla ahora también documenta los códecs de compresión, los eventos de perfil, las métricas actuales, las métricas asíncronas y las propias tablas del sistema (con sus columnas), y la documentación de la configuración incluye ahora su tipo y su valor predeterminado. #108346 (alexey-milovidov). - Si se usa WHERE con filtros sobre
tableydatabase,system.iceberg_historymostrará solo las bases de datos coincidentes. Esto puede ahorrar tiempo si hay muchas bases de datos remotas no relacionadas en el servidor. #108492 (Diskein). - Los parámetros de consulta (sustituciones
{name:Type}) ahora pueden usarse como valores de configuración, tanto en la cláusulaSETTINGSde una consulta (comoSELECToINSERT) como en consultasSETindependientes; p. ej.,SELECT ... SETTINGS max_threads = {threads:UInt64}ySET max_threads = {threads:UInt64}. #108760 (alexey-milovidov). - Permite calcular el beneficio combinado de los índices de omisión en EXPLAIN WHATIF. Muestra la proporción de datos, que corresponde a la intersección del rendimiento de todos los índices hipotéticos aplicables existentes. #108934 (yariks5s).
- Una consulta con una única CTE ahora se formatea con los mismos saltos de línea y la misma sangría que una consulta con varias CTE. Anteriormente,
WITH a AS (...)mantenía la CTE en la misma línea queWITH, mientras que con dos o más CTEWITHquedaba en su propia línea y cada CTE, sangrada. #109092 (groeneai). - Se admite la Query Condition Cache para archivos Parquet locales leídos mediante el motor de tabla
File(antes solo se admitía para almacenamiento de objetos y data lakes). #109247 (alexey-milovidov). - La Query Condition Cache para archivos Parquet remotos (en almacenamiento de objetos) ahora usa como clave el ETag además de la ruta, de modo que sobrescribir un objeto en el mismo lugar ya no devuelve resultados obsoletos de la caché. #109310 (alexey-milovidov).
- Una referencia no calificada a una clave de
INNER JOINque se iguala en la condiciónON(p. ej.,SELECT id FROM a INNER JOIN b ON a.id = b.id) ya no se notifica como identificador ambiguo, ya que se garantiza que ambos lados contienen el mismo valor. #109366 (alexey-milovidov). - Las funciones de distancia transpuestas sobre
QBit(L2DistanceTransposed,cosineDistanceTransposed,dotProductTransposedy sus equivalentes cuantizadasL2DistanceTransposedQuantized,cosineDistanceTransposedQuantized,dotProductTransposedQuantized) ahora aceptan un vector de referencia más largo que el número de dimensiones en las que se busca e ignoran los elementos finales sobrantes. Esto permite reutilizar un vector de consulta de tamaño completo para una búsqueda de dimensión reducida (Matryoshka) sin tener que recortarlo primero. #109388 (alexey-milovidov). - Se añadió una comprobación de coherencia que garantiza que una consulta distribuida siempre incluya una versión de cliente conocida; si no es así, se lanza un error lógico en lugar de reenviar silenciosamente una versión cero a los shards remotos. Las consultas iniciadas por el servidor (vaciados en segundo plano, consumidores de streaming, recargas de diccionarios, vaciados de inserciones asíncronas) ahora informan de la propia versión del servidor como versión del iniciador. #109408 (alexey-milovidov).
- Este parche corrige el uso de nombres de columna calificados en la cláusula WHERE de las mutaciones sobre los motores de tabla de la familia MergeTree. #109491 (Michicosun).
- Se admiten funciones de ventana sin particionar (
OVER (ORDER BY ...)) en planes de consulta distribuidos (make_distributed_plan). Anteriormente, cualquier consulta con una función de ventana fallaba porqueWindowStepno podía serializarse para su ejecución remota; por ahora, las ventanas conPARTITION BYsiguen rechazándose. #109802 (VighneshPath). - Ahora es posible modificar algunas configuraciones de autenticación del catálogo one-lake con
ALTER DATABASE ... MODIFY SETTING = 'xxx'. #110019 (alesapin). - Una subconsulta en el lado derecho de
INcuya única columna es un array con un nivel de anidamiento más que el argumento izquierdo ahora se interpreta como el conjunto de los elementos del array (como un literal de array o una función que devuelve un array), en lugar de fallar con un confuso error de incompatibilidad de tipos. Por ejemplo,x IN (SELECT groupArray(x) FROM ...)ahora funciona. #110169 (alexey-milovidov). - Las consultas aceleradas mediante el filtrado dinámico TopK (
ORDER BY ... LIMIT k) ahora aprovechan mejor la caché de condiciones de consulta: la caché se rellena incluso cuando se aplica la materialización diferida, y estas consultas pueden reutilizar entradas escritas previamente por una consulta ordinaria con el mismo predicadoWHERE. #110507 (shankar-iyer). SHOW CREATE TABLE(ySHOW CREATE VIEW/SHOW CREATE DICTIONARY) ahora sugiere una tabla con un nombre similar en el mensaje de error cuando la tabla solicitada no existe, igual que hacen las consultasSELECT. #110633 (alexey-milovidov).- Se añade el modificador STREAM BOUNDED, que lee solo la primera instantánea de una consulta de streaming y luego finaliza en lugar de suscribirse a las actualizaciones. #110653 (SmitaRKulkarni).
- Se corrigió la caché de resultados de consultas para las consultas PromQL. El dialecto
promqlomitía la comprobación de funciones no deterministas y podía devolver resultados obsoletos anclados ennow(); la API HTTP de Prometheus (/api/v1/query,/api/v1/query_range) nunca almacenaba entradas en la caché. #110887 (nikitamikhaylov). EXPLAIN ANALYZEahora muestra el número de filas de cada lado del join, las tasas de coincidencia, el factor de expansión (fanout) y el estado específico de cada algoritmo, como la memoria de la tabla hash y el volcado a disco. Usematches = 1para recopilar las métricas de coincidencia que requieren contabilidad adicional. #110892 (Fgrtue).- Se corrigió un error de heap-use-after-free en el ejecutor del pipeline que podía provocar la caída del servidor cuando una consulta eliminaba procesadores en tiempo de ejecución (por ejemplo,
FINALcon lecturas diferidas u ordenación externa). El error lo detectó el AST fuzzer. #111017 (groeneai). - Se corrigió un use-after-free (fallo de segmentación) que se producía cuando una consulta con una instantánea de almacenamiento compartido (configuración
enable_shared_storage_snapshot_in_query) eliminaba partes de datos de la instantánea; por ejemplo, una subconsulta en streaming que leía la misma tablaMergeTreeque otra parte de la consulta leía de forma concurrente. #111192 (alexey-milovidov). - Se admiten planes de consulta distribuidos (
make_distributed_plan) para consultas cuyo origen, de forma demostrable, no produce filas en el momento de la planificación, como una lectura de una tablaMergeTreevacía. Anteriormente, estas consultas fallaban conSUPPORT_IS_DISABLED. #111941 (groeneai). - Se corrigió un problema por el que la caché de condiciones de consulta no se rellenaba para los gránulos descartados por cualquier conjunción que no fuera la última en una cláusula
WHEREcon varias condicionesAND. #112083 (shankar-iyer). - Se redujo el pico de memoria al escribir columnas JSON con serialización de datos compartidos por buckets (map_with_buckets y advanced), ya que ahora los datos compartidos se dividen en buckets de uno en uno durante la escritura en lugar de materializar todos los buckets simultáneamente. Esto beneficia sobre todo a las columnas Array(JSON): en JSON escalar, los datos compartidos se dividen por gránulo (limitado por index_granularity_bytes), por lo que el ahorro es pequeño; en cambio, un solo gránulo de Array(JSON) puede contener muchas filas anidadas y, por tanto, una gran cantidad de datos compartidos, y en ese caso dividirlos de bucket en bucket reduce considerablemente el pico de memoria #112172 (Avogar).
- La planificación de reservas de memoria (experimental) ya no desaloja una asignación cuando una liberación de memoria pendiente dejaría libre el espacio necesario para un aumento de reserva que supera el límite: la decisión de desalojo ahora espera a que se apliquen las reducciones en curso, lo que evita terminar consultas innecesariamente en situaciones de presión de memoria. #112299 (serxa).
SYSTEM DROP FILESYSTEM CACHEahora elimina en paralelo las claves de metadatos de la caché, lo que agiliza la limpieza de cachés del sistema de archivos de gran tamaño. La nueva configuracióndrop_cache_threadsde la caché de archivos controla el número de workers de eliminación y su valor predeterminado es 16; con un valor de 1, la eliminación se realiza en el thread de la consulta. #112532 (kssenii).- Los modificadores de una declaración de columna (
COMMENT,CODEC,STATISTICS,TTL,COLLATE,PRIMARY KEYySETTINGSpor columna) ahora pueden escribirse en cualquier orden enCREATE TABLE, y cada uno de ellos como máximo una vez. Antes solo se aceptaba un orden fijo y, por ejemplo,x UInt64 CODEC(ZSTD) COMMENT 'text'producía un error de sintaxis. EnALTER TABLE ... ADD COLUMN/MODIFY COLUMN, los modificadores compatibles (COMMENT,CODEC,STATISTICS,TTLySETTINGSpor columna) también pueden escribirse en cualquier orden; losSETTINGSpor columna enADD COLUMNy unSTATISTICSdeclarado enADD COLUMN/MODIFY COLUMNahora se aplican en lugar de descartarse silenciosamente, yCOLLATEyPRIMARY KEYen estos comandosALTERahora lanzan una excepción en lugar de ignorarse sin aviso. #112788 (alexey-milovidov). - Una consulta sobre una tabla
Merge(o la función de tablamerge) que coincide con muchas tablas ahora responde aKILL QUERYy amax_execution_timemientras se construyen los planes de consulta de cada tabla, en lugar de hacerlo solo cuando ha terminado la planificación de todas las tablas hijas. #113415 (alexey-milovidov). - Un
SELECTsobre una tablaMergeque superamax_execution_timecontimeout_overflow_mode = 'break'ahora deja de construir planes de consulta para las tablas coincidentes restantes, en lugar de ejecutar el análisis completo de la consulta para cada tabla coincidente antes de detenerse. La consulta sigue finalizando sin error, tal como establece la documentación de ese modo. #113642 (groeneai). - Cuando el tipo declarado de una columna y sus datos no coinciden durante una lectura de
MergeTree(procedencia de tipos mixta, p. ej., tras unALTER TABLE ... MODIFY COLUMNcuya mutación aún no ha finalizado), el servidor ahora devuelve una excepción clara que indica la columna y ambas estructuras, en lugar de realizar una conversión sin comprobar: antes, los builds de depuración y con sanitizadores abortaban con un escuetoBad cast from type A to Bsin indicar ninguna columna, y los builds de release recorrían silenciosamente memoria con una estructura distinta. #114087 (alexey-milovidov). - Se ha habilitado
ie_joinde forma predeterminada: el valor predeterminado dejoin_algorithmes ahoradirect,parallel_hash,hash,ie_join. UnJOINcuya secciónONcontiene solo condiciones de desigualdad (dos comparaciones<,<=,>,>=entre expresiones de las tablas unidas) se ejecuta ahora con el algoritmo IEJoin basado en ordenación en lugar de con unCROSS JOINy un filtro, y se admiten unionesLEFT/RIGHT/FULL/SEMI/ANTIcon dichas condiciones. Comoie_joines el último de la lista, solo se utiliza cuando no es posible aplicar los demás algoritmos. #114327 (vdimir). - Se propaga el contexto de traza de OpenTelemetry a las fibras utilizadas para el establecimiento asíncrono de conexiones y la ejecución remota de consultas (hedged requests,
async_socket_for_remote,async_query_sending_for_remote). Los spans de las consultas remotas en una consulta distribuida ahora cuelgan correctamente del spanConnection::sendQuerydel iniciador, en lugar de adjuntarse directamente al contexto de traza proporcionado por el cliente, y cada ejecución de tarea asíncrona genera su propio span. #114813 (diegomestre2). DROP DATABASEahora elimina las tablas en orden topológico inverso según las dependencias tanto de carga como referenciales (antes solo según las de carga), de modo que un fallo a mitad deDROP DATABASEno puede dejar una tabla cuyas dependencias ya se hayan eliminado. #114952 (alexey-milovidov).- Se admiten operadores de coincidencia de expresiones regulares al estilo de PostgreSQL:
~(un alias de la funciónmatch),~*(coincidencia sin distinguir entre mayúsculas y minúsculas),!~y!~*(negaciones). Los comandos\d,\dty\dvdepsqlahora funcionan al conectarse a ClickHouse mediante el protocolo de compatibilidad con PostgreSQL, y una consulta fallida ya no cierra la conexión. #115066 (alexey-milovidov). EXPLAIN WHATIFahora indica por qué se omitió la estimación empírica en una nueva líneaempirical_reason, que se muestra cuandoempirical_statusesunsupported. #115140 (yariks5s).- Cuando ningún algoritmo de unión habilitado por el ajuste
join_algorithmpuede ejecutar unJOIN, el mensaje de error ahora indica los algoritmos que se intentaron, así como la rigurosidad y el tipo del JOIN que falló, en lugar de limitarse a informar de que ninguno funcionó. #115226 (elkinal). - Las consultas de búsqueda vectorial ahora pueden usar el índice de similitud vectorial cuando el vector de referencia es un literal de array de enteros, p. ej.,
ORDER BY L2Distance(vec, [1, 2]). Anteriormente, estas consultas recurrían de forma silenciosa a un escaneo por fuerza bruta. #115255 (rschu1ze). BACKUPya no deja un archivo de bloqueo en su destino cuando el intento que lo creó falla antes de escribir nada, ya sea al reclamar el destino o al abrir un archivo comprimido. Ninguna copia de seguridad posterior podía coincidir con dicho bloqueo, por lo que todos los reintentos hacia el mismo destino fallaban hasta que el archivo se eliminaba manualmente. Las copias de seguridad a destinosS3yAzuretambién crean el bloqueo de forma exclusiva, y un bloqueo que pertenece a otra copia de seguridad se notifica como una copia de seguridad concurrente, en lugar de con el error que hubiera devuelto el almacenamiento. #115387 (jkartseva).- Una traza iniciada por muestreo (
opentelemetry_start_trace_probability) ahora se escribe de vuelta en la información de cliente de la consulta, de modo que las consultas secundarias remotas y distribuidas, así como las entradas DDL, se incorporan a la misma traza en lugar de iniciar trazas independientes. #115619 (diegomestre2). - Se corrigió
CREATE TABLEpara tablas Iceberg respaldadas por Amazon S3 Tables, que gestiona por sí mismo las ubicaciones de las tablas. #115652 (scanhex12). - La agregación adaptativa de
GROUP BY(enable_adaptive_aggregator) ahora mide si compensa diferir las claves poco frecuentes y vuelve al algoritmo ordinario cuando sus claves o argumentos de agregación son demasiado anchos para que copiarlos resulte rentable, de modo que las agregaciones sobre columnas de cadenas pesadas (p. ej.,min(URL)por usuario) se ejecutan con la velocidad y el consumo de memoria del algoritmo ordinario. Se añadeadaptive_aggregator_freeze_threshold_bytespara limitar en bytes la tabla congelada de cada hilo (la tabla se congela al alcanzarse el primero de los dos umbrales: este o el de número de claves). #115755 (nihalzp). - Se añade el ajuste
query_plan_aggregation_bucket_top_k(habilitado por defecto) para activar o desactivar la optimización del plan que materializa solo losnmejores grupos de cada bucket de dos niveles cuando una agregación final alimenta unORDER BYsobre sus salidas conLIMIT n. La optimización ahora también se muestra en la salida deEXPLAIN. #116124 (nihalzp). - Se mejora la compatibilidad de las consultas
DESCRIBEcon las vistas parametrizadas. Se admiten vistas parametrizadas en expresiones escalares en el nuevo analizador. #68978 (novikd). - Las consultas como
SELECT * FROM t WHERE idahora utilizarán la omisión de datos mediante índices en la columnaid. #89603 (adityachopra29). - Se añadió la configuración
query_plan_merge_expression_into_joinpara permitir la fusión de pasos Expression en pasos JOIN durante la optimización de reordenamiento de JOIN. Esto permite reordenar JOIN a través de subconsultas que encapsulan uniones (p. ej., cuando un JOIN se encuentra dentro de una subconsulta con columnas calculadas), lo que mejora la optimización de árboles de uniones complejos. #98533 (vdimir). - Se añadió a la tabla
system.grantsuna columnais_wildcardque indica si un privilegio utiliza coincidencia de prefijo con comodín (p. ej.,GRANT SELECT ON db*.*). Anteriormente, ensystem.grantsno era posible distinguir entre los privilegios con comodín y los exactos sobre un mismo nombre. #98577 (il9ue).
Funciones y tipos de datos
- Se añadió una nueva configuración
allow_lossy_numeric_supertype(deshabilitada de forma predeterminada). Cuando está habilitada,if,multiIf,coalesce,ifNull,arrayymapaplicados a argumentos numéricos que no tienen un tipo común sin pérdida (por ejemplo, unDecimaly unFloat64, o unInt64y unFloat64) se resuelven al supertipo numéricoFloat64en lugar de a unVariant, de modo que el resultado puede usarse con funciones de agregación comosum,avg,minymax. Ahora, los mensajes de error correspondientes de las funciones de agregación mencionan el nombre de esta configuración. #107236 (groeneai). - El cuantificador de array
SOME/ALL(expr OP SOME(array)/expr OP ALL(array)) ahora también admite los predicados de comparación con palabra claveIS DISTINCT FROMeIS NOT DISTINCT FROM, así como los predicados de búsqueda de cadenasLIKE,ILIKE,NOT LIKE,NOT ILIKEyREGEXP, que se reescriben comoarrayExists/arrayAll. #107454 (alexey-milovidov). - Se añadió la configuración
input_format_json_max_object_sizepara limitar el tamaño de los objetos JSON durante el análisis. #107669 (Avogar). - Se corrigió una fuga de memoria que se producía al fallar la apertura de una base de datos SQLite (por ejemplo, cuando a la función de tabla
sqliteo al motor de base de datosSQLitese les proporciona una ruta que no se puede abrir). #107807 (alexey-milovidov). - Se admite la función
lengthpara el tipo de datosQBit. Devuelve la dimensión del vector como una constante. #108071 (alexey-milovidov). - Se admite
CASTde unQBita unArray, lo que reconstruye el vector original. Es la operación inversa de la conversión ya existente deArrayaQBit. #108072 (alexey-milovidov). - El motor de base de datos, el motor de tabla y la función de tabla
MySQLahora asignan los tipos de columna espaciales de MySQL (LINESTRING,POLYGON,MULTILINESTRING,MULTIPOLYGONy el genéricoGEOMETRY) a los tipos geométricos correspondientes de ClickHouse en lugar de aString. Este comportamiento se controla mediante el nuevo indicadorgeometryde la configuraciónmysql_datatypes_support_level, habilitado de forma predeterminada.POINTse sigue convirtiendo siempre aPoint. La columna genéricaGEOMETRYse asigna al tipo generalGeometry; al leer un valor cuyo subtipo no tiene equivalente en ClickHouse (MULTIPOINT,GEOMETRYCOLLECTION), se genera una excepción en el momento de la lectura. #108944 (alexey-milovidov). - Ahora se usa de forma predeterminada el algoritmo preciso (el valor representable más cercano) para analizar números de punto flotante, y la configuración
precise_float_parsingse aplica a los formatos de entrada (CSV, TSV, JSON, VALUES, …) y a los literales numéricos, no solo atoFloat*/CAST. Establezcaprecise_float_parsing = 0para recuperar el comportamiento anterior, más rápido en algunos casos pero menos preciso. #109086 (Algunenano). - Se admite
reinterpretde unArrayde elementos de tamaño fijo comoString, la operación inversa delreinterpretya existente de unString/FixedStringcomoArray. #109383 (alexey-milovidov). - Se permite
CASTentre tiposQBitque difieren en el tipo de elemento y/o en el stride, siempre que la dimensión se mantenga (por ejemplo,CAST(x AS QBit(Float64, N))desde unQBit(Float32, N)). Los cambios que solo afectan al stride no implican pérdida; los cambios de tipo de elemento siguen la semántica de conversión deArraycorrespondiente (por ejemplo, al pasar deFloat32aBFloat16puede perderse precisión, yaccurateCast/accurateCastOrNullrechazan las filas que no se pueden representar con exactitud). #109387 (alexey-milovidov). - Las funciones
quantizeBFloat16ToInt8ydequantizeInt8ToBFloat16ahora también aceptan argumentosArrayyQBit, además de las sobrecargas escalares existentes, y aplican el códec Lloyd-Max a todo el vector (devolviendoArray/QBitdel tipo de elemento correspondiente). #109398 (alexey-milovidov). - El especificador de formato de estilo MySQL
%fenparseDateTime/parseDateTime64(y sus variantesOrZero/OrNull) ahora acepta entre 1 y 6 dígitos fraccionarios, que se interpretan como microsegundos alineados a la izquierda, igual que enSTR_TO_DATEde MySQL, en lugar de exigir exactamente 6. También se corrigieron tablasPrettyCompactdesalineadas en los ejemplos de la documentación de funciones integradas. #109421 (alexey-milovidov). - La subestadística
NullCountde las estadísticasbasicpasa a llamarseDefaultCount: en lugar de contar las filasNULLde una columnaNullable,buildahora cuenta las filas iguales al valor predeterminado intrínseco del tipo de la columna medianteIColumn::getNumberOfDefaultRows. #109977 (hanfei1991). - Se redujo el tamaño del binario en ~10,5 MB al ejecutar las operaciones de comparación y aritméticas sobre pares de tipos mixtos poco usados (
Decimalfrente a enteros de distinto ancho, y pares que involucranInt128/UInt128/Int256/UInt256) mediante una conversión a un tipo común, en lugar de usar un kernel compilado dedicado para cada combinación de tipos. Los pares del mismo tipo, los pares de uso habitual y las operaciones limitadas por memoriaplus/minus/multiplyconservan sus kernels dedicados; los resultados, los tipos de resultado y los casos excepcionales no cambian. #110131 (alexey-milovidov). - La lectura desde un motor de tabla
SQLiteo desde la función de tablasqliteya no ocupa por completo un núcleo de CPU en espera activa cuando la base de datos SQLite está bloqueada por otra conexión. Ahora la lectura permanece inactiva mientras espera a que se libere el bloqueo y se puede seguir cancelando. #110248 (groeneai). - Los valores de tiempo transcurrido, tasa y proporción en los mensajes de log y de excepción se redondean ahora a tres dígitos, de modo que números como
1.345844286 sec.ya no se muestran con precisión completa. #110277 (alexey-milovidov). - Se corrigieron las lecturas de
MergeTreede columnasStringcon un stream de tamaños independiente tras omitir filas iniciales, que podían devolver datos erróneos o leer fuera de los límites de la caché de substreams. También se corrigió la posible obtención de datos erróneos cuando lecturas concurrentes o repetidas acceden a un subobjetoJSONalmacenado con serialización de datos compartidos de tipo map. #110471 (alexey-milovidov). - Se admite la cláusula
SETTINGSen el motor de tablaPostgreSQLy en la función de tablapostgresql(por ejemplo,SETTINGS postgresql_connection_pool_size = 50), lo que equipara sus funcionalidades a las del motorMySQL. #110614 (alexey-milovidov). - Las funciones
bitmaskToArrayybitmaskToListahora admiten argumentos(U)Int128y(U)Int256. Con argumentos de enteros grandes, la funciónbitPositionsToArrayahora se ejecuta en un tiempo proporcional al número de bits activos, en lugar de a la posición del bit activo más alto. #110743 (raimannma). - Se corrigió el manejo de valores de ancho fijo con signo que contienen números negativos en el códec GCD. Anteriormente, el divisor se calculaba directamente a partir de los valores con signo, lo que podía impedir encontrar el divisor común y reducir significativamente la eficiencia de compresión en columnas de tipo entero y decimal con signo. Ahora, para los tipos con signo, el divisor se calcula a partir de las magnitudes, y se mantiene el comportamiento existente para los tipos sin signo y para la descompresión. #113798 (kshcherbatov).
- Las funciones de ventana con
PARTITION BYahora funcionan conmake_distributed_plan. Cuando la forma del plan lo permite, la ventana se ejecuta en paralelo en varios buckets, cada uno de los cuales recibe particiones completas. #114111 (VighneshPath). - Ahora se utiliza una función hash de 64 bits en los métodos de agregación externa de ancho fijo con valores nullable (lo que evita colisiones masivas en agregaciones de cardinalidad muy alta). #114210 (nickitat).
x IN (subquery)sobre una columnaLowCardinalityahora devuelveLowCardinality(UInt8), el mismo tipo quex IN (literal list). Anteriormente, ambas formas devolvían tipos distintos, y los planes distribuidos con unINde este tipo requerían un caso especial en la comprobación de tipos del plan. #114229 (davenger).- Ahora se pueden analizar enteros que superan el rango de 64 bits en el tipo de datos
JSON,JSONExtracteisValidJSON. Estos valores se leen en tipos de enteros anchos, comoInt128/UInt256, en lugar de provocar el rechazo de todo el documento. #114379 (Avogar). - Se añadió
keywordcomo alias del tokenizadorarraydel índice de texto para mejorar la compatibilidad con OpenSearch, Elasticsearch, SolR y Lucene. #115507 (rschu1ze). - Las funciones
toDateOrNull,toDateTimeOrNullytoDateTime64OrNullahora aceptan argumentos de todos los tipos enteros nativos (que se interpretan igual que entoDate,toDateTimeytoDateTime64, con un argumento opcional de zona horaria) y devuelvenNULLpara valores fuera del rango del tipo de resultado. Por ejemplo,toDateTimeOrNull(1583851242, 'Asia/Shanghai')devuelve2020-03-10 22:40:42ytoDateTimeOrNull(4294967296)devuelveNULL. #79791 (jitendra1411).
Almacenamiento, lagos de datos y almacenamiento de objetos
- Se añadieron métricas opcionales de Prometheus para la actividad de desalojo de la caché del sistema de archivos (
filesystem_cache_evictions_total,filesystem_cache_evicted_bytes_total,filesystem_cache_evicted_segment_hits,filesystem_cache_evicted_segment_size_bytesy sus variantes por usuario etiquetadas conuser_id), expuestas por caché mediantesystem.dimensional_metrics,system.histogram_metricsy el endpoint de Prometheus. Se controlan con las opciones de configuración de disco de la cachéexpose_prometheus_eviction_metricsyexpose_prometheus_eviction_metrics_per_user(ambas desactivadas de forma predeterminada), que pueden activarse o desactivarse en tiempo de ejecución medianteSYSTEM RELOAD CONFIG. #105020 (sacheendra). - El motor
Aliasahora admite la lectura con réplicas paralelas cuando la tabla de destino usa un motor de la familiaMergeTree. #107830 (nauu). - Se limita a max_inflight_parts_for_one_file el número de partes preparadas simultáneamente en la copia de lectura y escritura de Azure Blob Storage (que utilizan las copias de seguridad cuando la copia nativa no está disponible), lo que evita un uso excesivo de memoria al copiar muchos archivos grandes en paralelo. #108232 (SmitaRKulkarni).
- Se admite la columna virtual
_etagpara el almacenamiento HDFS #108255 (zhangyifan27). - Se añadieron las columnas
settingsyengine_settingsasystem.backupsysystem.backup_log.settingsmuestra las opciones de configuración específicas de copia de seguridad/restauración solicitadas para una operación (p. ej.,allow_s3_native_copy,deduplicate_files,structure_only), yengine_settingsmuestra las opciones de configuración que realmente utiliza el lector/escritor del motor de copia de seguridad (p. ej., las opciones de solicitudes de S3, comoallow_native_copy, que pueden diferir de las solicitadas tras combinarse con la configuración del endpoint). Así es posible ver con qué opciones de configuración se ejecutó realmente una operaciónBACKUP/RESTORE. #108334 (jkartseva). - Se añadieron
system.s3_queue_metadataysystem.azure_queue_metadatapara inspeccionar el estado en Keeper de las tablasS3QueueyAzureQueueregistradas, incluidos los recuentos de archivos procesados, en procesamiento y fallidos. #108522 (kssenii). - Se redujo entre 2 y 2,5 veces el uso de memoria de la caché de encabezados del índice de texto. Ahora caben más encabezados de partes de datos en la caché (opción
text_index_header_cache_size), lo que reduce las lecturas de disco en las consultas de búsqueda de texto. #109332 (CurtizJ). - Se añadieron columnas de compatibilidad con MySQL a las vistas de
INFORMATION_SCHEMA:SCHEMATA.DEFAULT_COLLATION_NAMEyDEFAULT_ENCRYPTION;TABLES.ENGINEy otras columnas de MySQL relacionadas; yCOLUMNS.COLUMN_KEY,PRIVILEGES,GENERATION_EXPRESSION,SRS_ID. Esto permite que los clientes compatibles con MySQL ejecuten sus consultas de introspección del catálogo sin toparse conUNKNOWN_IDENTIFIER. #109351 (alexey-milovidov). - Se redujo el uso de memoria de las tablas
MergeTreecon muchas partes de datos al compartir entre las partes de una tabla la metadata por parte derivada del esquema (lista de columnas, descripciones de columnas, serializaciones y subflujos de columnas), en lugar de copiarla en cada parte. El efecto es mayor en tablas anchas con muchas partes pequeñas. #109816 (Algunenano). - Se añadió una nueva configuración
use_projection_index_in_read_pools(deshabilitada de forma predeterminada). Cuando está habilitada, los rangos de marcas que un índice de proyección filtra por completo se descartan dentro de los grupos de lectura deMergeTreeantes de crear tareas de lectura para ellos, en lugar de omitirse gránulo a gránulo durante la lectura. Así se evita crear tareas de lectura y configurar lectores para datos que no se van a leer, y el tamaño de las tareas de lectura se sigue midiendo en marcas restantes. #110291 (KochetovNicolai). - Se redujo el nivel de detalle de los diagnósticos de búsqueda binaria en la clave primaria por parte en
MergeTree, que pasan del registro de nivel trace al de nivel test. #110324 (alexey-milovidov). - Se corrigieron reconexiones espurias de conexiones HTTP keep-alive agrupadas sobre TLS (HTTPS, S3). La comprobación de conexiones obsoletas usaba
pollsobre el socket, que informa erróneamente como cerrada una conexión segura activa con un registro TLS posterior al handshake pendiente de leer (un ticket de sesión oKeyUpdate); ahora usa unMSG_PEEKno bloqueante en sockets sin cifrar ySSL_peek/SSL_has_pendingen sockets TLS, lo que además detecta correctamente un cierre TLS ordenado y un registro TLS que solo ha llegado en parte. #110402 (alexey-milovidov). - Los catálogos de OneLake ahora pueden usar tokens de actualización de OAuth para renovar los tokens de acceso. #110413 (alesapin).
- Se añadió el ProfileEvent
DuplicationDataHashComputations, que cuenta los cálculos de hash de datos por columna realizados al deduplicar bloques insertados con INSERT en tablas*MergeTree. #111173 (valerypetrov). - El SST del índice UNIQUE KEY ahora se escribe directamente en la parte a través de la abstracción de almacenamiento, en lugar de almacenarse provisionalmente en un archivo temporal local. #111189 (JingYanchao).
- Se admiten escrituras concurrentes en tablas Iceberg en un disco local:
LocalObjectStorageahora implementa escrituras condicionales, por lo que la operación compare-and-swap que publica una nueva instantánea medianteversion-hint.textfunciona también en ese caso y los escritores concurrentes ya no pueden perder las actualizaciones de los demás. #112556 (alexey-milovidov). - La caché de regiones de buckets del client de
S3ahora también funciona con los catálogos de data lake; antes, cada solicitud a estos volvía a resolver la región. #113330 (scanhex12). - Los fallos de red del lado del cliente de Azure (conexión restablecida/rechazada, errores de DNS y TLS) ahora se reintentan como errores de transporte en lugar de devolverse como un
500sintético, igual que en el client de S3. #115269 (arsenmuk).
Formatos e ingestión
- Se permite la compresión snappy en la interfaz HTTP (
Accept-Encoding: snappy) y se añade el settingsnappy_modepara elegir entre el formato de bloque snappy de Hadoop o el formato de estructura de tramas de snappy para la E/S snappy genérica defile/url. #100752 (alexey-milovidov). - Se añadió el setting
input_format_csv_missing_nullable_as_empty_string(deshabilitado de forma predeterminada). Cuando está habilitado, un valor ausente deNullable(String)en la entrada CSV se lee como unStringvacío en lugar deNULL, independientemente del valor deinput_format_csv_empty_as_default. #107577 (alexey-milovidov). - Al procesar mensajes protobuf con
input_format_protobuf_oneof_presence, ya no se exige una coincidencia exacta de las etiquetas, lo que permite realizar cambios de esquema. #109174 (ilejn). - Se eliminó el lector ORC heredado basado en Apache Arrow. El formato de entrada ORC ahora utiliza siempre el decodificador nativo de ClickHouse (que antes era el predeterminado). El setting
input_format_orc_use_fast_decoderqueda obsoleto (se sigue aceptando, pero no tiene ningún efecto). #110074 (alexey-milovidov). - El motor Hive ahora lee la metadata de los archivos ORC (índices min/max, recuentos de filas) con el lector ORC nativo de ClickHouse en lugar del adaptador ORC de Apache Arrow. #110086 (alexey-milovidov).
Seguridad, acceso y observabilidad
- Se agregó una nueva columna
skipping_indices_typesa la tablasystem.tables, que contiene los distintos tipos de índices de omisión de datos definidos en cada tabla. #106388 (CurtizJ). - El valor automático de
max_threadsy de configuraciones similares ahora se muestra ensystem.settingscomoauto(8)en lugar de'auto(8)'; las comillas simples que lo rodeaban eran un artefacto heredado que llevaba mucho tiempo incrustado en el valor. Se mantiene la compatibilidad entre versiones: la forma heredada entre comillas se sigue aceptando al analizar las configuraciones recibidas de servidores más antiguos. #108657 (alexey-milovidov). - Cuando el valor predeterminado de una configuración está vacío, ahora se muestra como cadena vacía en
system.documentation, en lugar de como comillas invertidas vacías. #108708 (alexey-milovidov). - La documentación de una configuración en
system.documentation(la que muestran la página integrada/docsy el comandohelp) ahora incluye el historial de cambios de su valor predeterminado: la versión en la que se introdujo la configuración y cada cambio posterior de su valor predeterminado, con el valor anterior, el nuevo valor y el motivo del cambio. #112177 (alexey-milovidov). - Ahora es posible consultar la documentación de todas las sentencias SQL (p. ej., nombre, sintaxis, descripción y ejemplos) en la tabla del sistema
system.statements. #115341 (rschu1ze).
Configuración
- Se añadió una nueva configuración de servidor
memory_worker_rss_speculative_reserve_ratio(por defecto1.0, o0en builds con sanitizador) que hace que el rastreador de memoria global reserve de forma especulativaratio * min(resident - previous_resident, resident - tracked)por encima del RSS observado en cada ciclo deMemoryWorker. Esto sesga el rastreador al alza cuando el RSS crece más rápido de lo que el rastreador lo contabiliza entre muestras, de modo que las asignaciones recibenMEMORY_LIMIT_EXCEEDEDantes y es menos probable que el OOM-killer del kernel actúe primero. Establezca el ratio en0para desactivar la reserva especulativa. Los builds con sanitizador usan0por defecto porque en ellos la diferenciaresident - trackedse debe principalmente a la memoria sombra del sanitizador. #104976 (alexey-milovidov). - El modo de aplicación diferida de listas de publicación del índice de texto deja de ser experimental y puede seleccionarse con
text_index_posting_list_apply_mode = 'lazy'sin necesidad deallow_experimental_text_index_lazy_apply. La configuración del umbral de densidad pasa a llamarsetext_index_lazy_intersection_density_thresholden lugar detext_index_density_threshold. #108814 (CurtizJ). - La configuración
merge_selector_enable_heuristic_to_lower_max_parts_to_merge_at_onceahora está habilitada por defecto: el selector de fusiones reduce automáticamente el número máximo de partes que se fusionan a la vez en función del grado de ocupación de la partición. #110726 (Michicosun). - Los comandos de limpieza de PostgreSQL
RESET,UNLISTENyDISCARDse aceptan como operaciones sin efecto en el protocolo de comunicación de PostgreSQL, en lugar de rechazarse con un error de sintaxis. Esto mejora la compatibilidad con controladores como Skunk, que envíanRESET ALLyUNLISTEN *al establecer y limpiar la conexión. #110780 (alexey-milovidov). - Las funciones de texto de IA (
aiGenerate,aiClassify,aiExtract,aiTranslate) ahora rechazan las respuestas del proveedor truncadas o incompletas por cualquier otro motivo (p. ej., cuando el modelo alcanza el límitemax_tokens) en lugar de devolver silenciosamente una salida parcial. El comportamiento se rige por la configuraciónai_function_throw_on_error. #111830 (george-larionov). - Se mejoran
L2DistanceTransposedQuantized,cosineDistanceTransposedQuantizedydotProductTransposedQuantizedcon precisión reducida, reconstruyendo los códigosp < 8QBit(Int8)mediante centroides de prefijo de media condicional gaussiana. Con precisión completa (p = 8), los resultados siguen siendo idénticos bit a bit; las distancias aproximadas con precisión reducida pueden cambiar, y las mejoras en recall y latencia dependen de la carga de trabajo. #111867 (skuznetsov). - La configuración
write_snapshot_versionahora se puede recargar en caliente. #112150 (alesapin). - Se añadió observabilidad para las pilas de las fibras, que se usan para la comunicación asíncrona con réplicas remotas: los eventos de perfil
FiberStackAllocs,FiberStackAllocBytes,FiberStackAllocNanosecondsyFiberStackFreeNanoseconds, y las métricasFiberStacksyFiberStackBytes. #114541 (alexey-milovidov). - El protocolo Prometheus remote-write ahora admite inserciones asíncronas: los datos de varias solicitudes remote-write concurrentes se agrupan en lotes antes de formar partes, según la configuración
async_insert(habilitada por defecto; añadaasync_insert=0a la URL del handler para mantener el comportamiento síncrono). Una solicitud solo se confirma después de que los datos se hayan volcado en todas las tablas internas de la tablaTimeSeriesde destino. #115688 (nikitamikhaylov).
Otras mejoras
- Se añadieron dos ajustes,
shrink_over_allocated_columns_min_waste_ratioyshrink_over_allocated_columns_min_waste_bytes, que hacen que los INSERT reduzcan las columnas sobreasignadas (cuya memoria reservada supera la memoria utilizada debido al crecimiento en potencias de dos de las columnas de longitud variable) para ajustarlas a su tamaño real antes de la materialización y la escritura de partes, lo que reduce el pico de uso de memoria. Deshabilitado de forma predeterminada.. #112161 (Avogar). - Se omite por completo el paso de lectura de datos en las fusiones
TTLDroppara evitar un uso excesivo de memoria, especialmente en las asignaciones de los búferes de lectura/precarga. #105859 (Avogar). - Se añadió compatibilidad con
BFloat16endotProducty se mejoró el rendimiento del producto escalar mediante el procesamiento por lotes en la ruta SIMD. #106569 (nickitat). - Ahora
max_named_collection_num_to_throw,max_table_num_to_throw,max_replicated_table_num_to_throw,max_view_num_to_throw,max_dictionary_num_to_throwymax_database_num_to_throwse pueden modificar sin reiniciar el servidor. #106821 (UberDever). - La escritura en tablas
DeltaLake, controlada porallow_experimental_delta_lake_writes, pasó a fase Beta. #107034 (kssenii). - Se añadió el tipo de estadísticas de columna
uniq_v2, una alternativa ligera auniqbasada en el sketchuniqCombined64. #107863 (hanfei1991). - Se añadieron los ProfileEvents
DistributedPlanRemoteTasks,DistributedPlanLocalExecutionyDistributedPlanHostsUsedpara supervisar la ejecución de make_distributed_plan. #107985 (shankar-iyer). - Las solicitudes a catálogos REST de data lakes, como OneLake, ahora incluyen un encabezado
User-Agentde ClickHouse. #108117 (scanhex12). MVTEncodeGeomahora ajusta la geometría a la cuadrícula de píxeles enteros antes del recorte y recorta los polígonos conwagyu, de modo que la salida recortada es válida (los anillos que se intersecan a sí mismos se reparan) y queda alineada con los bordes, igual queST_AsMVTGeomde PostGIS. #108248 (saarthak2002).- Se habilitaron globalmente las tres cachés del índice de texto; anteriormente, solo estaban habilitadas dentro de las consultas. Además, el tamaño de la caché de listas de postings ahora es cero (lo que, en la práctica, vuelve a deshabilitarla), ya que las listas de postings son grandes y almacenarlas en caché resulta demasiado costoso. #108274 (rschu1ze).
- El endpoint de Prometheus (para configuraciones solo de métricas) y la recopilación de métricas asíncronas se inician antes de cargar las tablas, para que las métricas puedan observarse durante la fase de carga de metadatos, que puede prolongarse. #108402 (cwurm).
- Compatibilidad con BFloat16 en las funciones matemáticas binarias #108442 (zhangyifan27).
- Las funciones de distancia vectorial transpuestas
L2DistanceTransposed,cosineDistanceTransposedydotProductTransposedahora aplican la optimización de lectura parcial de planos de bits a las columnasNullable(QBit), de modo que solo leen los planos de bits solicitados en lugar de la columna completa. #109358 (alexey-milovidov). - Se admiten
arraySum,arrayAvgyarrayProductpara arrays deBFloat16. #109420 (alexey-milovidov). - Las funciones
L1Normalize,L2Normalize,LinfNormalizeyLpNormalize(y sus alias) ahora funcionan con arrays, no solo con tuplas, de forma coherente conL2Normy las funciones de distancia. #110052 (alexey-milovidov). - Ya no se hace ping a las conexiones del grupo antes de cada uso. Esto elimina el viaje de ida y vuelta
Ping-Pongque se añadía a cada conexión reutilizada y reduce la latencia de las consultas distribuidas y declickhouse-benchmark. Las conexiones obsoletas del grupo se detectan mediante un sondeo con tiempo de espera cero (una comprobación no bloqueante que no añade ningún viaje de ida y vuelta) y se recuperan mediante una reconexión. #110068 (alexey-milovidov). - Las partes de listas grandes para el análisis distribuido de índices se envían como escalares (lo que evita posibles fallos debidos a max_ast_elements/max_query_size y elimina la sobrecarga de analizar el AST) #110419 (azat).
- Al hacer clic en el logotipo de la nube en el Playground, ahora se abre el sitio web de ClickHouse en una pestaña nueva para no perder el progreso mientras se ejecutan las consultas. #110422 (williamhatcher).
- Se cambia el valor predeterminado de
auto_statistics_typesdebasic, uniqabasic, uniq_v2#110878 (hanfei1991). - Cuando salta una aserción de reentrada de
RWLockImpl::getLock()(RWLock is already locked in exclusive mode/Cannot acquire exclusive lock while RWLock is already locked), el mensaje de error ahora indica los demásquery_idque tienen actualmente el bloqueo y cuántos bloqueos mantiene ya elquery_idsolicitante, para facilitar el diagnóstico de este tipo de errores de orden de bloqueo. #110971 (groeneai). randomHadamardTransformahora calcula una transformada exacta que preserva la longitud para cualquier longitud de vector cuyo mayor factor impar sea como máximo 64 (por ejemplo,3584 = 512 * 7, habitual en modelos de embeddings), lo que amplía las familias anteriores2^N,2^k * {12, 20}y2^k * 9. Una transformada completa de una longitud que no puede representarse de forma exacta ahora genera una excepción en lugar de rellenar silenciosamente con ceros hasta un vector más largo; paseoutput_dimspara calcular una proyección truncada de longitud arbitraria. #111006 (alexey-milovidov).- Se devuelve el código HTTP
403 Forbidden(en lugar de500 Internal Server Error) para las excepcionesACCESS_DENIEDa través de la interfaz HTTP. #111043 (Schum-io). UTMToGeoahora acepta como cuarto argumento la letra de banda de latitud MGRS devuelta porgeoToUTM(además del indicador entero de hemisferio), de modo que un resultado degeoToUTMpuede convertirse de ida y vuelta directamente conUTMToGeo. #111521 (alexey-milovidov).MaterializedPostgreSQLahora conserva los valoresTOASTde PostgreSQL que no se han modificado durante las actualizaciones, en lugar de reemplazarlos por valores predeterminados. #111552 (OrpheusAgent).- Se añadieron las configuraciones
text_index_max_processed_tokens_before_flushytext_index_max_memory_usage_before_flushpara controlar cuándo los constructores de índices de texto realizan el vaciado de los segmentos temporales. #111573 (rorylshanks). - Se añade el modificador STREAM UNORDERED: omite la ordenación por orden de confirmación de cada instantánea #111794 (SmitaRKulkarni).
- Ahora
make_distributed_plan=1deshabilita las funcionalidades que aún no son compatibles. #112463 (alesapin). - Ya no se escriben secuencias de escape ANSI con INTO OUTFILE cuando stdout es un tty #113252 (azat).
- Se renombró
allow_experimental_delta_kernel_rsaallow_delta_kernel_rs. El nombre anterior se mantiene como alias. #113476 (kssenii). - Se añaden las configuraciones
enable_alp_codec,enable_sz3_codec,enable_zxc_codecyenable_quantized_codecpara habilitar por separado cada códec de compresión experimental. #113824 (rienath). - Se notifica el desbordamiento de pila en lugar de terminar silenciosamente: los handlers de señales fatales ahora se ejecutan en la pila de señales alternativa, de modo que
SIGSEGV,SIGABRT,SIGILL,SIGBUS,SIGSYS,SIGFPEySIGTRAPgeneran un stack trace incluso cuando el thread que provocó el fallo ha agotado su pila. #113927 (groeneai). - Se admite el parámetro lookback_delta de la Prometheus HTTP API para consultas instantáneas y de rango. #113971 (fallintoplace).
- Las tablas QueryRunner ahora inician hilos de trabajo bajo demanda y los liberan cuando quedan inactivos, en lugar de ocupar threads durante toda la duración de la tabla. #114522 (mstetsyuk).
- Con este cambio, al usar índices WHATIF, la línea base servida por proyección devuelve
not_applicablepara cada candidato en lugar de provocar el fallo de la sentencia. #114846 (yariks5s). - Se optimizan las cadenas AND con varias condiciones de comparación sobre la misma expresión: se detectan contradicciones (p. ej.,
a < 3 AND a > 5→false) y se eliminan condiciones redundantes (p. ej.,a = 3 AND a < 5→a = 3). #99736 (wudidapaopao).
Correcciones de errores
Correcciones de MergeTree, replicación y almacenamiento
- Se corrigió una condición de carrera entre
ALTER TABLE ... RENAME COLUMNy unOPTIMIZE TABLE ... FINALconcurrente (o cualquier fusión en segundo plano) enMergeTreeque podía reemplazar silenciosamente los datos de la columna renombrada por valores predeterminados. La ventana de carrera entre la publicación de los nuevos metadatos en memoria y el registro de la mutación de renombrado encurrent_mutations_by_versionahora se cierra manteniendocurrently_processing_in_background_mutexdurante ambas operaciones. #104822 (groeneai). - Se corrigieron resultados de consulta incorrectos al usar GROUP BY con ORDER BY y
arrayJoinen la proyección. #101775 (Onyx2406). - Las configuraciones no válidas del tamaño de carga en Azure (por ejemplo,
azure_min_upload_part_size = 0oazure_max_blocks_in_multipart_upload = 0) ahora se rechazan de forma anticipada con un error claro, en lugar de provocar una excepción interna (second_size > 0) en un punto profundo de la ruta de escritura. Esto se aplica tanto a los ajustes de consulta como a la configuración de disco de Azure. #103394 (statxc). - Se lanza
BAD_ARGUMENTSen lugar deLOGICAL_ERRORcuando se ejecutaALTER TABLE ... MOVE/REPLACE/ATTACH PARTITIONentre dos tablasMergeTreecon configuraciones de granularidad incompatibles (una adaptativa y otra no adaptativa). #103881 (groeneai). - Se corrige un
LOGICAL_ERROR“Expected one block from input stream” lanzado porKILL QUERY/KILL MUTATION/KILL PART_MOVE_TO_SHARD/KILL TRANSACTIONcuando su cláusulaWHEREcontiene una subconsulta por fila, o cuandomax_block_sizees tan pequeño que elSELECTinterno sobre la tablasystem.*correspondiente emite más de un bloque. #104927 (groeneai). - Se corrige una fuga en las vistas materializadas actualizables (
MATERIALIZED VIEW ... REFRESH ...) por la que la tabla interna temporal que la tarea de actualización retira medianteEXCHANGE TABLESno podía eliminarse si superaba elmax_table_size_to_dropdel servidor. Cada actualización posterior creaba una nueva tabla interna temporal sin conseguir limpiar las anteriores, de modo que el directorio de datos de la vista crecía hasta agotar el disco. La eliminación interna que realiza la tarea de actualización ahora omitemax_table_size_to_dropymax_partition_size_to_drop; estas salvaguardas siguen aplicándose cuando el usuario ejecutaDROP TABLEsobre la propia vista. #105106 (groeneai). - Se corrige un error inesperado
DATA_TYPE_CANNOT_BE_USED_IN_KEYen consultasALTERque no pueden modificar la clave de ordenación (configuraciones, comentarios, códecs, adición de una columna que no forma parte de la clave, etc.) en tablasMergeTreeque tienen unSimpleAggregateFunction(u otro tipo permitido solo conallow_suspicious_primary_key = 1) en la clave de ordenación. #105111 (groeneai). OPTIMIZE ... DRY RUNinterrumpido por un tiempo de espera de consulta (max_execution_timecontimeout_overflow_mode = 'break') ahora devuelveTIMEOUT_EXCEEDEDen lugar de un error lógico relacionado conrows_sources(que abortaba el servidor en compilaciones de depuración y con sanitizadores). #107114 (groeneai).- Se corrigió
NOT_FOUND_COLUMN_IN_BLOCKal leer archivos con particionamiento Hive usandouse_hive_partitioning=1y una cláusulaWHERE/PREWHEREque filtra una columna real (no virtual) cuando también se selecciona una columna de partición Hive. #107505 (groeneai). - Se corrigen resultados de consulta incorrectos debidos a una poda errónea de clave primaria y de partición cuando se aplica
toStartOfDay,toStartOfISOYear,toDaysSinceYearZero,toRelativeSecondNum,toRelativeMinuteNum,toRelativeHourNum,toRelativeWeekNum,toRelativeDayNum,toMonthNumSinceEpochotoYearNumSinceEpocha una columna claveDate32que contiene fechas fuera del rango que la función puede representar (en particular, fechas anteriores a1970-01-01). Estas funciones se declaran monótonas ante el índice primario, pero hasta ahora se desbordaban con dichos argumentos, por lo que el índice podía podar gránulos que en realidad contenían filas coincidentes. Ahora se saturan en los límites de su tipo de resultado y se mantienen monótonas en todo el rango deDate32, de modo que la poda es correcta. #108018 (nihalzp). - Se corrige que
CREATE TABLE dst AS src SETTINGS ...(y variantes similares conORDER BY/PARTITION BYpero sin unENGINEexplícito) descartara silenciosamente el motor, las cláusulas de almacenamiento (como elTTLde la tabla y las claves) y la configuración de la tabla de origen. Ahora el motor y las cláusulas de almacenamiento no sobrescritas se heredan de la tabla de origen, y la configuración especificada se combina con la de la tabla de origen, prevaleciendo sobre ella. #108085 (alexey-milovidov). - Se corrige que
INSERTen tablasMergeTreefallara confilesystem error: in rename: Permission denieden sistemas de archivos respaldados por Windows (WSL, CIFS/SMB, montajes bind de Docker Desktop), debido a que el escritor de partes dejaba descriptores de archivo abiertos durante el renombrado del directorio de la parte. #108089 (alexey-milovidov). - Se corrige un bloqueo permanente en una tabla MergeTree adjuntada con un índice de omisión heredado
hypothesis(un tipo de índice eliminado que solo se conserva por compatibilidad conATTACH). Hasta ahora, unDELETEligero,OPTIMIZE, unINSERTsimple o unSELECTfiltrado sobre dicha tabla fallaba conILLEGAL_INDEX(“Index of type ‘hypothesis’ is no longer supported”), y la mutaciónDELETEse reintentaba indefinidamente. Ahora el índice obsoleto se trata como inerte: se conserva intacto durante la fusión/mutación, se omite en la inserción y en la planificación de consultas, y todavía puede eliminarse conALTER TABLE ... DROP INDEX. #108217 (groeneai). - Se corrige el error
NOT_FOUND_COLUMN_IN_BLOCK(p. ej.,Column _part not found) al seleccionar columnas virtuales de una tablaMergeTreecon réplicas paralelas, incluso medianteSELECT *conasterisk_include_virtual_columns = 1. #108451 (groeneai). - Se corrige que
ATTACH PARTITION ... FROMrechazara tablas cuyas claves primarias son equivalentes pero están declaradas de forma distinta (una conPRIMARY KEYexplícito y la otra implícita a partir deORDER BY). #108590 (jordiori). join_any_take_last_rowahora se respeta en todas las rutas de unión basadas en hash compatibles, incluidas las uniones que usan volcado automático a disco. #108936 (antaljanosbenjamin).- Se corrige el error
NOT_FOUND_COLUMN_IN_BLOCKcuandoquery_plan_optimize_lazy_finalestá habilitado junto con un filtroWHEREtrasladado parcialmente aPREWHERE(medianteoptimize_move_to_prewhere_if_final). La optimización de FINAL diferido ya no solicita al almacenamiento las columnas de predicado calculadas en prewhere. #109073 (groeneai). - Se corrigió que
ALTER TABLE ... ADD PROJECTIONsobre una columnaALIASa nivel de tabla dejara la tabla inutilizable (elINSERTposterior fallaba conUNKNOWN_IDENTIFIER, “Missing columns”) cuando la sesión teníaoptimize_respect_aliases = 0. #109091 (groeneai). - Se corrigió una aserción de puntero nulo (
px != 0enTreeRewriter::analyzeSelect, que abortaba el servidor en compilaciones de depuración y con sanitizadores) al ejecutarORDER BY ALL(oGROUP BY ALL) sobre una tabla con motorMergeunida mediante JOIN a otra tabla con el analizador antiguo (allow_experimental_analyzer = 0). #109139 (groeneai). - Se corrigió un resultado incorrecto en subconsultas
EXISTScorrelacionadas y subconsultas escalares cuando la correlación solo aparece en la proyección de la subconsulta junto con una cláusulaWHEREno correlacionada (la subconsulta podía evaluarse como falso /NULLpara todas las filas). Corrige https://github.com/ClickHouse/ClickHouse/issues/105760. #109186 (novikd). - Se corrigió un error por el cual la fusión de una tabla
MergeTreecon proyecciones, con el ajusteenable_block_number_columnoenable_block_offset_columnhabilitado, generaba partes de proyección con una columna espuria_block_number/_block_offset. Como resultado, la parte de proyección fusionada dejaba de coincidir con la definición de la proyección y con las partes de proyección generadas por inserción, por lo queCHECK TABLEyOPTIMIZE ... DRY RUNla notificaban como corrupta (CORRUPTED_DATA). #109284 (groeneai). - Se corrigió el error
UNKNOWN_IDENTIFIERal ejecutarALTER TABLE ... RENAME/ADD/MODIFY COLUMNen una tabla MergeTree que tiene un índice min-max implícito sobre las columnas virtuales persistentes_block_numbero_block_offset(habilitado medianteadd_minmax_index_for_block_number_column/add_minmax_index_for_block_offset_column). #109428 (groeneai). - Se corrigió que se eliminaran índices de omisión de una parte de datos (o que
CHECK TABLEfallara conUNEXPECTED_FILE_IN_DATA_PART) tras una mutación que reescribe la parte completa, comoALTER TABLE ... DROP COLUMNde una columnaMATERIALIZED, en una parteWide. #109616 (groeneai). - Se corrigieron índices de omisión (
text,bloom_filter, etc.) y proyecciones obsoletos tras materializar actualizaciones ligeras conALTER TABLE ... APPLY PATCHES. Anteriormente, los archivos de índices y proyecciones que dependen de una columna actualizada mediante parche no se modificaban, por lo que las consultas que los utilizaban podían devolver resultados incorrectos (p. ej.,hasTokenomitía una fila actualizada, o una proyección devolvía agregados obsoletos una vez eliminada la parte de parche ya aplicada). #109709 (groeneai). - Se corrigió que una mutación que hace referencia a la columna virtual
_sample_factorfallara a mitad de ejecución conUnexpected const virtual column: _sample_factor, dejando la mutación bloqueada. Ahora una mutación la lee como1, el mismo valor que devuelve una consulta sinSAMPLE. #109813 (groeneai). - Se corrigieron dos errores que se producían cuando una consulta con
GROUP BY GROUPING SETS(o una subconsulta escalar o de mutación que la contuviera) se ejecutaba conforce_aggregation_in_order = 1:Trying to get name of not a column: ExpressionListcon el analizador antiguo (enable_analyzer = 0), yMemory bound merging of aggregated results is not supported for grouping sets.en una consulta distribuida conenable_memory_bound_merging_of_aggregation_results = 1con el analizador. #109862 (groeneai). - Se corrigen tres problemas con
use_constant_folding_in_index_analysis: un error lógicoInvalid partition key sizeque podía abortar unSELECTque usaba una proyección normal cuando la tabla establecepart_minmax_index_columns = 'with_block_number_offset'; resultados incorrectos (filas descartadas de forma silenciosa) al filtrar por una clave de partición basada en módulo, comoPARTITION BY id % 200; y un fallo (carrera de datos) al consultar un índicetextcon un tokenizadorsparseGramsmediante un predicadoLIKEsobre muchas particiones conmax_threads > 1. #109896 (groeneai). - Se corrigen resultados incorrectos cuando se construye un índice de omisión
minmaxsobre una columnaLowCardinality(Nullable(...)): los predicadosWHERE/PREWHERE/HAVING ... IS NULLdelegados al almacenamiento descartaban todos los gránulos y devolvían 0 filas aunque la columna contuviera valores NULL. #110061 (groeneai). - Se corrigió la lentitud de las consultas
ORDER BY ... LIMITsobre tablasDistributedcuandoprefer_localhost_replicaselecciona una réplica local. #110136 (EmeraldShift). - Se corrigió una excepción (
UNION mode UNION_DEFAULT must be normalized) que se producía cuando una mutaciónDELETEoALTER UPDATEusaba una operación de conjuntos (UNION/UNION ALL/UNION DISTINCT/EXCEPT/INTERSECT) dentro de una subconsulta en su condiciónWHEREo en una asignaciónUPDATE. #110196 (alexey-milovidov). - Se corrigió el apagado lento del servidor y la falta de respuesta de
KILL MUTATIONcuando una mutación conx IN (subquery)estaba construyendo el conjunto de la subconsulta durante el análisis de la clave primaria; ahora la construcción del conjunto se cancela de inmediato. #110198 (alexey-milovidov). - Se corrigió una condición de carrera entre
KILL TRANSACTIONyALTER TABLE ... UPDATE/DELETEejecutado dentro de una transacción: un rollback producido entre el registro de la mutación en la transacción y su registro en la tabla dejaba una entrada de mutación huérfana, lo que provocaba un error lógico (Cannot find transaction ... that has started mutation ...) en los trabajos en segundo plano y bloqueaba todas las mutaciones posteriores de las partes afectadas hasta reiniciar el servidor. #110226 (tiandiwonder). - Se corrigió un problema por el que
system.tablespara una base de datosDataLakeCatalog(Iceberg/Glue) abortaba toda la consulta, o descartaba tablas de forma silenciosa, cuando no se podía resolver el metadata de una sola tabla. Ahora dicha tabla sigue apareciendo por nombre, con valores predeterminados/NULL en las columnas que requieren el objeto de almacenamiento abierto (engine,total_rows, etc.), independientemente dedatabase_datalake_require_metadata_access. El acceso directo a la tabla dañada sigue notificando el error. #110242 (groeneai). - La estimación de cardinalidad para el orden de join ahora combina las estadísticas de columnas de las partes que quedan tras la poda por partición/PK, en lugar de las de todas las partes activas. Anteriormente, una consulta podada a una partición pequeña se planificaba con estadísticas de toda la tabla (se observó una sobreestimación de filas de 2500x que invertía el lado de construcción del hash join) y, paradójicamente, desactivar las estadísticas producía un plan mejor. También se corrigió que el FINAL diferido se desactivara de forma silenciosa para relaciones MergeTree bajo un JOIN, porque el resultado memoizado del análisis de índices del optimizador de orden de join se confundía con una proyección aplicada. #110283 (skuznetsov-clickhouse).
ALTER TABLE ... MOVE/REPLACE PARTITIONentre dos tablas MergeTree con granularidad incompatible (una adaptativa y otra no) ahora lanzaBAD_ARGUMENTSen lugar deLOGICAL_ERROR. Es una situación que el usuario puede provocar, por lo que no debe manifestarse como un error interno (que aborta el servidor en builds de depuración/sanitizer). #110535 (groeneai).- Se corrige un problema por el que
TTL ... DELETE WHERE <cond>nunca eliminaba las filas que empezaban a cumplir<cond>como consecuencia de unALTER TABLE ... UPDATEsobre una columna referenciada en elWHERE. Ahora la mutación recalcula el TTL de la fila, de modo que las filas expiradas que pasan a cumplir la condición se eliminan en lugar de conservarse sin aviso. #110648 (groeneai). - Se corrigió un
LOGICAL_ERROR“Invalid partition key size: 0” que podía abortar unINSERTen una tablaMergeTreeparticionada connon_replicated_deduplication_windowhabilitado, cuando un lote de inserción asíncrona solo se deduplicaba parcialmente (algunosinsert_deduplication_tokens estaban duplicados y otros eran nuevos). #110651 (groeneai). - Se corrige un problema por el que el plegado de constantes con el nuevo analizador cambiaba sin aviso el tipo de un valor
Geometryconstante.Geometryes unVariantcon nombre cuyas alternativas pueden compartir la misma disposición de almacenamiento (LineString/Ring,MultiLineString/Polygony los valores vacíos), por lo que dos constantes plegadas que solo se diferenciaban en su alternativa acababan fusionándose en una sola; por ejemplo, una constanteMULTIPOLYGON EMPTYse convertía enLINESTRING(). #110709 (groeneai). - Se corrige un resultado incorrecto (fusión mal ordenada) en consultas con lectura en orden en las que
distinct-in-orderoaggregation-in-orderamplían la lectura a un prefijo de clave de ordenación más largo que aquel para el queORDER BYconfiguró la fila virtual de lectura en orden. Las columnas de ordenación adicionales de la fila virtual se rellenaban con valores predeterminados, lo que podía alterar el orden enMergingSortedTransform(y provocar un aborto conLOGICAL_ERRORen compilaciones de depuración/sanitizer). #110725 (groeneai). - Los roles activos de una consulta (SET ROLE / role=) ahora se propagan a los nodos remotos en lecturas con réplicas paralelas y lecturas distribuidas sobre un clúster con secreto entre servidores; antes se recurría a los roles predeterminados del usuario, por lo que las políticas de filas se evaluaban de forma incoherente con respecto al initiator. #110867 (evillique).
- Se corrigió una condición de carrera poco frecuente por la que un
ALTERque solo modificaba comentarios o configuración de una tablaReplicatedMergeTreepodía descartar sin aviso una columna añadida por unALTER ... ADD COLUMNconcurrente, de modo que una réplica quedaba con una estructura de tabla obsoleta. #111029 (tiandiwonder). - Se corrige el error
NUMBER_OF_COLUMNS_DOESNT_MATCHen unGROUP BYcon una agregación sobre una tablaMergeque envuelve una tablaDistributed, cuando la clave de agrupación es una función de una columna y una agregación lee esa misma columna (p. ej.,SELECT toString(g), min(g) FROM merge_over_distributed GROUP BY toString(g)). #111334 (groeneai). - Se corrige un resultado incorrecto de un
FULL JOINconUSINGsobre una tabla con motorJoin(StorageJoin) cuando la clave izquierda esNullabley la clave de almacenamiento no lo es: una fila izquierda sin coincidencia y con claveNULLdevolvía0en lugar deNULL. #111371 (groeneai). ALTER TABLE ... DETACH PARTITION/PARTahora aplica fsync al clon que crea endetached/(el subárbol de la parte más la cadena de directorios hasta la raíz del disco) cuando la configuraciónfsync_part_directoryde la tabla está habilitada, tanto para el almacenamiento de partes Full (directorio) como Packed. Anteriormente nunca se aplicaba fsync al clon, pero sí a la parte de cobertura vacía que elimina las filas del conjunto activo, por lo que un corte de energía justo después de la confirmación podía destruir los datos desvinculados en btrfs (las entradas de directorio del clon no sincronizadas se revierten, lo que dejadetached/vacío y nada sobre lo que ejecutarATTACH). Depende de la configuración existentefsync_part_directory; el comportamiento predeterminado no cambia. #111426 (groeneai).- Ahora se rechaza una columna
Nullable(Nothing)(o de cualquier otro tipo no permitido en tablas) al ejecutarCREATE TABLEcuando el esquema se infiere del almacenamiento (por ejemplo, una tablaremote()/Remote/Distributedsin columnas sobre una vista que ejecutaSELECT NULL), en lugar de persistir metadata que no se puede cargar en el siguiente reinicio del servidor y que bloquea la carga de tablas no relacionadas. #111487 (groeneai). - Se corrige un
LOGICAL_ERROR(Got read request from replica N for unknown stream ...) que podía abortar el servidor al leer con réplicas paralelas cuando la consulta se resuelve por completo en el iniciador mediante una optimización de proyección (exact-count, minmax-count o una proyección almacenada de agregación/normal que no selecciona ningún rango). #111689 (groeneai). - Se corrige el
INSERTparticionado de DeltaLake (allow_experimental_delta_lake_writes=1), que corrompía los valores de partición que contenían caracteres de ruta y rechazabaNULL. Un valor comoa/bse confirmaba silenciosamente comoa,%generaba un archivo de datos que luego no se podía leer y un valor de particiónNULLfallaba conNOT_IMPLEMENTED. Ahora los valores de partición se convierten mediante codificación porcentual en un único segmento de ruta, el valor real se almacena enpartitionValuesen lugar de extraerse de nuevo de la ruta, y un valor de particiónNULL(o una cadena vacía) se escribe como__HIVE_DEFAULT_PARTITION__con una entrada nula enpartitionValues. #111793 (groeneai). - Se corrigen los errores lógicos
Expected UInt64 column for __grouping_set, got BLOByColumnBLOB should be converted to a regular column before usageen una consulta distribuida ejecutada en un shard conenable_parallel_blocks_marshalling(habilitado de forma predeterminada), por ejemplo conGROUP BY GROUPING SETSsobre un clúster que tiene una réplica local, o al leer una tablaMergeque abarca una tabla local y una tabla distribuida.BlocksMarshallingStepya no se añade a los planes cuyos bloques se consumen en el mismo proceso. #111997 (groeneai). - Se corrige un
LOGICAL_ERROR(Type mismatch when building statistics for column) durante una mutación deMergeTreeen una tabla cuyo tipo de columna se había cambiado mediante unALTER MODIFY COLUMNque solo afecta a la metadata (por ejemplo, deEnum8aInt8o deDateTimeaUInt32) cuando la columna tiene estadísticas. Ahora la mutación recalcula únicamente las estadísticas de las columnas que realmente reescribe y conserva el resto sin cambios; además, una columna reescrita porMATERIALIZE COLUMN, por unUPDATEde una columna de la que depende una columnaMATERIALIZEDo porCLEAR COLUMNrecalcula ahora sus estadísticas en lugar de conservar contenido obsoleto. #112009 (groeneai). - Corrige la omisión silenciosa de filas cuando una consulta filtra por
intDiv(constant, key)odivide(constant, key). El análisis de la clave primaria y de la partición indicaba una dirección de monotonicidad incorrecta para una constante dividida por una columna de clave, por lo que los gránulos coincidentes se descartaban y la consulta devolvía menos filas sin ningún error. También corrigeintDivcon un dividendo constante sin signo cuyo bit más alto está activado, deja de declarar monotonicidad cuando un operandoDecimalhace que la división se calcule con el ancho nativo del decimal, y evita que el análisis de claves genereCannot compare DB::IPv4 with longpara una consulta válida que divide una constanteIPv4/IPv6por una columna de clave. #112156 (groeneai). - Corrige que una vista parametrizada cuyo cuerpo
SELECTusaINTERSECT/EXCEPT, o una cadenaUNIONque combinaUNION DISTINCTconUNION ALL, se clasificara como una vista ordinaria. La vista se creaba correctamente, pero sus metadata no podían volver a leerse: al cargarla se lanzabaInvalid storage definition in metadata file, lo que impedía cargarla de forma permanente y hacía que un servidor de depuración o con sanitizer abortara durante el arranque. Además,system.tables.parameterized_view_parametersno mostraba ningún parámetro para esas vistas. #112211 (groeneai). - Corrige que
max_execution_timeyKILL QUERYse ignoraran mientras una consulta evalúageohashesInBox. La consulta expandía todas las filas de un bloque antes de poder interrumpirse, por lo que la cancelación no surtía efecto hasta varios minutos después; ahora la función comprueba el límite de tiempo de la consulta a medida que recorre las filas. Las evaluaciones dentro de una expresión de tabla persistida, como una clave de ordenación, un índice de omisión o unPARTITION BY, no están cubiertas y se abordan por separado. #112273 (groeneai). - Corrige un error lógico al usar PREWHERE en una tabla Merge construida sobre otra tabla Merge o sobre una vista materializada cuyo tipo de columna difiere. También corrige que una política de filas se ignorara silenciosamente en tablas que leen de servidores remotos (una tabla Distributed, o una tabla que la envuelve), lo que podía exponer filas que la política debía ocultar; ahora estas consultas se rechazan con un error ILLEGAL_PREWHERE. En su lugar, defina estas políticas en las tablas locales subyacentes de cada servidor remoto; tenga en cuenta que estas políticas siguen sin aplicarse a las lecturas enviadas con
serialize_query_plan = 1, lo cual es un bug distinto y preexistente. #112326 (PedroTadim). - Corrige la lectura de un índice secundario (de omisión) obsoleto tras un cambio de tipo mediante
ALTER TABLE ... MODIFY COLUMNcuya mutación nunca llegó a ejecutarse, por ejemplo porqueKILL MUTATIONla eliminó: los gránulos en disco se habían escrito con el tipo antiguo, pero se decodificaban con el nuevo, lo que generabaLOGICAL_ERROR, provocaba solicitudes de asignación de varios exabytes o devolvía silenciosamente un resultado incorrecto. También corrige un resultado incorrecto de un índice sobre una expresión cuyo significado cambia aunque todos los bytes almacenados permanezcan idénticos, de modo que no llega a crearse ninguna mutación: unMODIFY COLUMNque solo modifica la zona horaria de unDateTime, o solo un nombre de tipo personalizado, como deUInt8aBool. Ahora ese índice se omite para la parte afectada. #112484 (groeneai). - Corrige un
LOGICAL_ERROR(Cannot add transform Resize to Pipes because it has no outputs) que se producía cuando una consulta de agregación sobre un clúster se ejecutaba conserialize_query_plan = 1y réplicas paralelas basadas en el plan, debido a que el paso de fusión redimensionaba el pipeline a cero flujos. #112506 (groeneai). - Corrige un
LOGICAL_ERROR(“Part … contains column … that is absent in table …”) que se producía cuando una réplicaReplicatedMergeTreemutaba una parte obtenida de otra réplica antes de aplicar su propioALTER ... ADD COLUMNpendiente. Ahora esa mutación se pospone hasta que se aplique el cambio de metadata. #112510 (groeneai). - Corrige los contadores de lectura (
read_rows,read_bytes,ProfileEvents['SelectedRows'],ProfileEvents['SelectedBytes']) y las cuotasREAD_ROWSyREAD_BYTES, que se contabilizaban en exceso en consultas cuyoORDER BYvuelca datos a disco. Las filas que se volvían a leer de los archivos temporales de la ordenación externa se contaban de nuevo como lecturas de origen, por lo que una consulta con volcado a disco notificaba más datos leídos de los reales y podía rechazarse conQUOTA_EXCEEDEDaunque no hubiera superado su cuota. #112645 (groeneai). - Corrige que
ProfileEvents['JoinResultRowCount']notificara un tamaño de resultado inferior al real en unJOINque vuelca datos a disco. Las filas emitidas desde los buckets diferidos solo se contaban enJoinDelayedJoinedTransformRowCounty no se incluían en el total. Los resultados de las consultas siempre fueron correctos; solo el evento de perfil era erróneo. #112673 (groeneai). - Corrige que
max_execution_timeyKILL QUERYno tuvieran efecto, sin aviso alguno, en una consulta distribuida que está estableciendo conexiones con las réplicas. Ahora dicha consulta se detiene en el siguiente intento de conexión en lugar de recorrer todas las réplicas y reintentos restantes. #112689 (groeneai). - Se corrigió que se aplicara un
ALTERen tablasMergeTreemientras todavía estaba en curso una mutación de alteraciónRENAME COLUMNincompleta. Esto podía actualizar los metadatos de almacenamiento de forma incompatible y bloquear por completo las mutaciones posteriores. #112783 (Michicosun). - Corrige resultados incorrectos de
ORDER BYal leer de una tablaMergesobre tablasDistributed: las filas podían devolverse desordenadas y, al usarLIMIT, podían faltar filas que debían formar parte del resultado. #112931 (alexey-milovidov). - Se corrigieron resultados incorrectos cuando la precarga de lectura del sistema de archivos está habilitada y se lee una columna
Nestedjunto a una subcolumna que se eliminó y se volvió a añadir, en tablas conshare_nested_offsetshabilitado (el valor predeterminado). Una consulta de este tipo podía devolver valores predeterminados para una columna físicamente presente que losALTERnunca habían modificado. En almacenamiento de objetos, donderemote_filesystem_read_prefetchtiene1como valor predeterminado, el problema se produce sin cambiar ninguna configuración; en discos locales requierelocal_filesystem_read_prefetch = 1. Otro defecto, independiente de la precarga, sigue corrompiendo estas lecturas cuando un rango abarca varios bloques; ese caso no se resuelve aquí. #112997 (groeneai). - Se corrigió un error lógico
Pipeline stucken consultas que reparten datos por partición, como una función de ventana conPARTITION BYo una unión conjoin_algorithm = 'parallel_full_sorting_merge', cuando el procesamiento posterior de un shard finalizaba mientras un bloque solo se había distribuido parcialmente. #113190 (groeneai). - Se corrigió un bloqueo de las sentencias
ALTER,OPTIMIZE,TRUNCATEy de manipulación de particiones conalter_sync = 2enReplicatedMergeTreecuando la tabla comienza a cerrarse mientras la sentencia espera a otra réplica, por ejemplo debido a unDROP DATABASE ... SYNCconcurrente. Ahora dicha sentencia falla conUNFINISHEDy además respetamax_execution_timeyKILL QUERY. #113228 (groeneai). - Se corrigió el error
Cannot insert element into Set(NOT_IMPLEMENTED) cuandoread_in_order_use_virtual_rowestá habilitado y una consulta de lectura en orden sobreMergeTreecombinaWITH FILL ... INTERPOLATEcon un filtroINohas. #113264 (groeneai). - Se corrige un error lógico (excepción)
Chunk info was not set for chunk in MergingAggregatedTransformque se producía cuando el ajusteinject_random_order_for_select_without_order_byestaba habilitado y una consulta de agregación leía de una tablaMergeque contenía una tabla hijaDistributed: el envoltorio aleatorioORDER BY rand()ya no se inyecta en consultas planificadas solo hasta una etapa intermedia. #113266 (alexey-milovidov). - Se corrige un problema por el que las filas nunca se eliminaban cuando una tabla
MergeTreetenía dos o más reglasTTL ... DELETE WHEREcon una expresión de tiempo idéntica que solo se diferenciaban en la condiciónWHERE. Tras una fusión de eliminación por TTL, elrows_where_ttl_infode la parte se restablecía a cero, por lo que ya no se programaba ninguna otra fusión por TTL para ella y las filas expiradas se conservaban indefinidamente sin ningún error ni mensaje de log. #113384 (groeneai). - Se corrige un problema por el que
max_execution_timeyKILL QUERYse ignoraban mientras una consulta evaluabageohashesInBox,arrayFold,sleep,base58Decode,h3PolygonToCellsoh3PolygonToCellsWithContainmentdentro de una expresión almacenada en los metadatos de la tabla, como una clave de ordenación, un índice de omisión o una clavePARTITION BY. #113456 (groeneai). - Se corrige un
LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) que se producía cuando una tablaMergecon más de una tabla hija leía una CTE materializada referenciada por la consulta externa. #113558 (alexey-milovidov). - Se corrige
Logical error: 'Required output position N is out of range for pass-through inputs'enEXPLAIN ANALYZEsobre una tablaMergecon varias tablas hijas, unPREWHEREcon una columna simple y unWHEREindependiente. #113725 (groeneai). - Se corrige un error lógico (
Unexpected return type) que se producía al hacer pushdown al almacenamiento de un filtro sobre una vista cuyo tipo de columna difiere del del almacenamiento subyacente (p. ej.,information_schema.tables, dondeengineesNullable(String), sobresystem.tables, donde esString). #113984 (alexey-milovidov). - Se corrige el error
Not-ready Set is passed as the second argument for function 'in'que se producía cuando una mutación cuyo predicado contieneIN (subquery)se cancelaba (por ejemplo, medianteKILL MUTATIONoDETACH DATABASE) mientras el conjunto de la subconsulta aún se estaba construyendo. #114463 (groeneai). ALTER TABLE ... DROP COLUMNsobre una columna que se usa en la clave de ordenación, primaria o de partición ahora falla conALTER_OF_COLUMN_IS_FORBIDDENy una explicación, igual queALTER TABLE ... CLEAR COLUMN. Anteriormente fallaba con un error confuso,UNKNOWN_IDENTIFIER: Missing columns, procedente del recálculo de las expresiones de clave. Lo mismo ocurre al eliminar o vaciar un grupoNestedcompleto mediante su prefijo común cuando una columna del grupo se usa en una clave; antes, esto podía destruir silenciosamente los datos del grupo o dejar una mutación que nunca terminaba. Además, al eliminar una columna que solo se usa en una expresiónTTL, ahora se indica qué expresión TTL deja de funcionar #114468 (m7kss1).- Se corrige un problema por el que una columna renombrada, eliminada y añadida de nuevo en un mismo
ALTERdevolvía los valores de la columna eliminada en lugar de su propio valor predeterminado mientras la mutación seguía pendiente. #114601 (tiandiwonder). - Se corrigió la lectura de una subcolumna (
.size0,.null, un elemento de tupla,String.size) a través de una tablaMergecuando la tabla subyacente declara la columna padre comoALIAS. Esa lectura devolvía el valor predeterminado del tipo y, si la columna padre se seleccionaba en la misma consulta, podía devolver el valor de una columna no relacionada. #114673 (groeneai). - Se corrigió la ausencia de filas en el resultado de un
SELECTfiltrado porpointInPolygonsobre una clave primaria de MergeTree cuando el argumento del polígono es un literal constante no válido yvalidate_polygons = 0. El análisis de la clave primaria aplicaba la poda de gránulos a partir de un polígono que nunca había validado y descartaba gránulos que contenían filas coincidentes. #114710 (groeneai). - Se corrigió el formateo de
ALTER TABLE ... MATERIALIZE INDEX,MATERIALIZE STATISTICSyMATERIALIZE PROJECTION, que omitía la cláusulaIF EXISTS, de modo que la consulta formateada no coincidía con la consulta analizada. Además, ahora se rechazan cuatro cargas útiles JSON de AST deALTER ... STATISTICSque el analizador SQL no puede generar y que, al formatearse, daban lugar a un comando distinto. #115099 (groeneai). - Se corrigió una lectura fuera de límites de los hashes en caché del diccionario al agregar o hacer un join sobre una clave
LowCardinality(String)cuyo diccionario crece durante la agregación, situación que podía darse conTTL ... GROUP BY. Podía producir un hash incorrecto y provocar un heap-buffer-overflow en builds con sanitizador. #115604 (groeneai). CREATE TABLEyALTER TABLEahora rechazan códecs con pérdida, comoSZ3, en columnas utilizadas en la clave de partición. #115626 (groeneai).- La lectura a través de una tabla
Mergeque coincide con una tablaAliascuyo destino es una vista parametrizada ya no generaLOGICAL_ERROR: Table has no columns.(que provoca la terminación del servidor en builds de depuración y con sanitizador). Ahora esa tabla devuelveSTORAGE_REQUIRES_PARAMETER, el mismo error que devuelve la propia vista parametrizada. Cualquier otra tabla coincidente que no pueda proporcionar columnas devuelve ahoraUNSUPPORTED_METHODen lugar de un error interno. #115896 (groeneai). - Se corrigió la vista previa sobre la marcha de una mutación pendiente cuya expresión hace referencia a
_sample_factor. Conapply_mutations_on_fly = 1y una cláusulaSAMPLE, la expresión se evaluaba con el factor de muestreo de la consulta de lectura en lugar del valor que persiste la materialización en segundo plano, por lo que las filas previsualizadas no coincidían con el resultado materializado final, y unALTER TABLE t DELETE WHERE _sample_factor > 1pendiente podía hacer que una lectura conSAMPLEno devolviera ninguna fila. La columna_sample_factorpropia de la consulta no se modifica. #115906 (groeneai). - Los archivos de estadísticas con versión de formato
V3ahora se leen en lugar de rechazarse conILLEGAL_STATISTICS. Estos archivos solo los generaron builds demasterdurante un breve periodo, pero las partes que los contenían resultaban completamente ilegibles y, en un disco de solo lectura,ALTER TABLE ... MATERIALIZE STATISTICSno puede regenerarlos. #116030 (alexey-milovidov). - Se corrigió el error
Invalid number of columns in chunk pushed to OutputPort(LOGICAL_ERROR) que se producía cuando una consultaSELECT ... FROM t STREAM ... ORDER BY ... LIMIT nleía una tabla con unaPROJECTION. La materialización diferida ya no se aplica a las lecturasSTREAM. #116187 (groeneai). ALTER TABLE ATTACH PARTITION FROMya no se replica en bases de datos replicadas. #94835 (MikhailBurdukov).- Se corrigió una interrupción abrupta del servidor (en builds con sanitizador) y una pérdida silenciosa de datos durante el arranque de la tabla cuando una parte transaccional de MergeTree revertida se intersecaba con una parte committed.
PartLoadingTree::addahora identifica correctamente cuál de las dos partes que se intersecan fue revertida, la descarta y reasigna sus partes hijas huérfanas a la parte committed en el orden correcto. #100992 (tuanpach). - Se corrigió que
indexOfAssumeSorteddevolviera resultados incorrectos para columnasArray(LowCardinality(String))en tablas MergeTree. #101771 (Onyx2406). - Se corrigen las excepciones
LOGICAL_ERRORal leer tablas de data lakeIcebergoDeltaLakea través de rutas que pueden llegar al pipeline de lectura sin undatalake_table_statefijado, como las actualizaciones concurrentes de metadatos deIcebergo las lecturas conmergesobre tablasDeltaLake. #102033 (groeneai). - Se corrigió el error
Logical error: Parsed partition value: ... doesn't match partition value for an existing part with the same partition ID: ...que generabaOPTIMIZE TABLE ... PARTITION ...(y otras consultas que resuelven un valor de partición medianteconvertFieldToTypeImpl) en tablas con una clave de partición de tipoTime. #106202 (groeneai). - Se corrige que una parte de datos se marcara incorrectamente como si tuviera una proyección dañada cuando una eliminación ligera no dejaba ninguna parte de proyección, ya sea porque la proyección se reconstruye sin filas de salida o porque se elimina (
lightweight_mutation_projection_mode = 'rebuild'/'drop'). Anteriormente, este estado dañado deshabilitaba la optimización por proyecciones en las consultas sobre esa parte. #106273 (tiandiwonder). - Se corrigió que las advertencias de sobrecarga de memoria/CPU/mutaciones en
system.warningsllegaran con un ciclo de métricas asíncronas de retraso (y no aparecieran en el primer ciclo). #108035 (alexey-milovidov). - Se corrigió una excepción
LOGICAL_ERROR(ScatterExchangeStep should have one source shard, got 8) y la duplicación de filas al consultar una tablaMergesobre tablasDistributedo vistas con la configuración experimentalmake_distributed_plan = 1. #108401 (groeneai). - Se corrigió una interrupción abrupta del servidor (
Sort order of blocks violated) durante una fusión, así como lecturas incorrectas, cuando un elementoLowCardinalityno nullable de una columnaNullable(Tuple(...))se usa como subcolumna (por ejemplo, como clave de ordenación). #108679 (groeneai). - Se corrige un fallo en la función
Base64Decodedel SDK de Azure incluido en el código, accesible medianteazureBlobStorage()(y las funciones de tabla y almacenamiento de Azure relacionados), cuando la clave de la cuenta no es Base64 válido. Un byte>= 0x80provocaba una lectura fuera de límites de la tabla de decodificación, y cualquier byte no válido causaba un desplazamiento a la izquierda indefinido de un valor negativo (interrupción con sanitizadores). Ahora las claves no válidas se rechazan correctamente. #108716 (groeneai). - Se corrigió un
LOGICAL_ERROR(“New empty part is about to materialize but the directory already exist”) que podía interrumpir el servidor en builds de depuración y con sanitizador cuando se ejecutaba unDROP/DETACH/MOVE/REPLACE PARTITIONsobre una tabla MergeTree después de que una operación similar anterior se interrumpiera (por ejemplo, por una transacción revertida o un fallo) y dejara un directoriotmp_empty_<part>obsoleto. Ahora el directorio obsoleto se reutiliza en lugar de provocar un error. #108879 (groeneai). - Se corrige una proyección que devolvía el valor predeterminado del tipo de una columna (p. ej.,
0) en lugar de suDEFAULTde DDL (p. ej.,-1) después de que expirara elTTLde la columna en una parte ancha. #109013 (tiandiwonder). - Se corrige el fallo de las consultas
ALTERen tablasMergeTreecreadas con una configuracióndiskpersonalizada (SETTINGS disk = disk(...)). #109199 (Michicosun). - Se corrige la aparición de filas obsoletas y eliminadas al leer tablas de una base de datos
MaterializedPostgreSQLa través de una tablaMerge. #109339 (vdimir). - Se corrige la lectura de tablas Paimon particionadas por una columna
BIGINTcuyo valor no cabe enInt32. Estos valores de partición se truncaban (por ejemplo,9223372036854775807se convertía en-1), lo que generaba una ruta de partición incorrecta y provocaba un error del sistema de archivos. #109510 (groeneai). - Se corrige un error lógico (“Cannot determine row level filter; 0 columns deleted, 0 columns added”) al leer de una tabla
Mergecuya tabla hija tiene una política de filas con un filtro que consiste únicamente en una columna existente (por ejemplo,CREATE ROW POLICY ... USING flag). #109843 (groeneai). - IcebergLocal indicaba Azure como tipo de almacenamiento. #109872 (PedroTadim).
CHECK TABLEahora informa de la corrupción real de una parte de proyección cuyos metadatos no se pudieron cargar, en lugar de mostrar el engañoso errorColumns doesn't match ... Expected: 0 columns. #110262 (Algunenano).- Se corrige un fallo en el inicio del servidor con tablas
MergeTreeen discos de almacenamiento de objetos cuando un archivo residualtxn_version.txt.tmptiene metadatos a nivel de disco dañados. #110519 (alexey-milovidov). - Se corrige un problema por el que una tabla MergeTree con una proyección
_part_offseto de orden de commit dejaba de poder adjuntarse de forma permanente tras deshabilitarallow_part_offset_column_in_projectionsoallow_commit_order_projectiony desadjuntar la tabla o reiniciar el servidor. Estas dos configuraciones solo se aplican en el momento de CREATE, por lo que ya no se vuelven a comprobar en ATTACH. #110570 (groeneai). - Se corrige un
LOGICAL_ERRORpoco frecuente (“Unexpected number of parts to remove from parts_queue”) que podía abortar el servidor en unaReplicatedMergeTreecuando dos operaciones de partición (por ejemplo, dos consultasMOVE PARTITION/REPLACE PARTITION, o una en condición de carrera con unDROP_RANGEen segundo plano) cancelaban a la vez la comprobación de partes en segundo plano sobre rangos superpuestos. #110738 (groeneai). - Se corrige un error lógico
Hash is not set for serializationque podía producirse cuando una columna con un códecQuantized(...)estaba anidada dentro de una serialización reutilizable desde un grupo; por ejemplo, una tablaMergesobre orígenes cuya columna homónima tiene tipos distintos (fusionados en unVariant). #110776 (groeneai). - Se corrige un
std::length_error(LOGICAL_ERROR) al leer una tabla MergeTree con un valor anómalo demax_streams_for_merge_tree_reading(cercano al máximo deUInt64) junto conallow_asynchronous_read_from_io_pool_for_merge_tree = 1. Ahora la configuración se limita al mismo tope quemax_threads. #110936 (groeneai). - Se corrige el error lógico
Cannot calculate columns sizes when columns or checksums are not initializeddurante la fusión de una tablaMergeTreede una sola columna cuya única columna tiene unTTLde columna que expira por completo (conmin_bytes_for_wide_part = 1). #111169 (groeneai). - Se aplica fsync a los archivos del índice de texto de una parte fusionada o materializada cuando se configuran
min_rows_to_fsync_after_merge/min_compressed_bytes_to_fsync_after_merge/fsync_part_directory. Hasta ahora, estos archivos eran los únicos de la parte que quedaban sin sincronizar, por lo que un corte de energía justo después de una fusión podía dejar una parte committed pero dañada y provocar pérdida de datos. #111335 (groeneai). - Se corrige
OPTIMIZE TABLE ... MANIFESTpara tablasIcebergcuando las tuplas de partición del manifiesto no coinciden con su especificación de partición #111368 (SmitaRKulkarni). - Se corrige una lectura fuera de límites (release) / error lógico (depuración) en la optimización de materialización diferida, así como un error lógico en
Pipe::unitePipespara tablasMerge, cuando la optimización de lectura directa desde el índice de texto deja una columna virtual de índice sin usar en el encabezado de lectura de una tablaMergeTreecon varios índicestext. #111467 (groeneai). - Se corrige un
LOGICAL_ERROR(“Part level Min-Max index was constructed from unexpected columns set”) que podía abortar una fusión en segundo plano en builds de depuración/sanitizador tras reducirpart_minmax_index_columns(por ejemplo, dewith_block_number_offsetde vuelta apartition_key_only). #111511 (groeneai). - Se corrigió un fallo al ejecutar una lectura
STREAM(enable_streaming_queries = 1) sobre una tabla con más de una partición y una política de filas definida. En builds de depuración y con sanitizador fallaba con el error lógicoFilter column ... not found in DAG outputs; en builds release podía producirse un fallo de segmentación. #111572 (groeneai). - Se corrigió un
LOGICAL_ERROR(Cannot create part with type Compact and storage type Full because table does not support polymorphic parts) que se producía cuando una tablaMergeTreecargaba una parteCompactpreexistente mientras su configuración actual deshabilitaba las partes polimórficas (granularidad no adaptativa). Esto podía ocurrir, por ejemplo, cuando una tabla de solo lectura comparte una ruta en disco con otra tabla y recarga sus partes medianteSYSTEM RESTART DISKo durante el inicio del servidor. En builds de depuración y con sanitizador, la excepción aborta el servidor. #111626 (groeneai). - Con
fsync_part_directory = 1, el cambio de nombre de un directorio de parte de su nombre temporal a su nombre final ahora también se hace duradero aplicando fsync al directorio padre (y, cuando se mueve entre directorios padre distintos, también al padre de origen). Hasta ahora solo se aplicaba fsync al directorio movido, por lo que un corte de energía justo después de hacer commit de una parte podía hacer que la parte no existiera en disco aunque sus archivos ya estuvieran escritos, con la consiguiente pérdida de filas pese a tener habilitada la configuración. #111861 (groeneai). - Se corrigieron resultados incorrectos y un
LOGICAL_ERRORal seleccionar de una tablaMergeTreeuna columnaNullable(Tuple(...))junto con una de sus subcolumnas de elementos que admiten valores nulos (Variant,DynamicoLowCardinality). Al leer la subcolumna, las filas que sonNULLen la tupla padre se marcaban comoNULLen una columna que ya se había compartido a través de la caché de subflujos, por lo que la lectura de la columna completa obtenía valores desplazados. #111949 (groeneai). - Se corrigió la pérdida de las optimizaciones posteriores a la fase de build en los hash joins (conversión a una tabla hash fija, el runtime filter compartido, la reasignación de rangos de la tabla derecha) siempre que se configuraba un umbral automático de volcado a disco, que es el comportamiento predeterminado desde la versión 26.5. #111972 (alexey-milovidov).
- Corrige resultados incorrectos (filas que faltan de forma silenciosa) en
hasAllTokensy otras búsquedas multitoken en índicestexten builds que no usansimdcomp(todos los destinos excepto x86_64 Linux, p. ej., aarch64) cuandotext_index_posting_list_apply_mode = 'lazy'. El decodificador portable de empaquetado de bits no escribía los ceros decodificados para un bloque con un ancho de bits de cero, por lo que se descartaba una entrada ubicada en un segmento de una sola entrada. El formato en disco no cambia y los datos existentes se leen correctamente tras la corrección. #112178 (groeneai). - Ahora las operaciones fallan cuando se cargan estadísticas de MergeTree corruptas, en lugar de ignorar el error. #112201 (skuznetsov-clickhouse).
- Corrige la pérdida silenciosa de escrituras de Iceberg confirmadas en HDFS: un commit de Iceberg publica cada nuevo archivo de metadatos mediante una escritura condicional, pero
HDFSObjectStoragedescartaba la condición y realizaba una sobrescritura simple, por lo que todos los escritores concurrentes recibían confirmación mientras la instantánea de uno de ellos quedaba inaccesible. Ahora HDFS rechaza las escrituras condicionales, de modo que fallan las escrituras de Iceberg gestionadas por el almacenamiento en HDFS, incluidoCREATE TABLE ... ENGINE = IcebergHDFS(...)con una lista de columnas explícita. Las lecturas no se ven afectadas. #112437 (groeneai). - Corrige que
DELETEen tablasKeeperMapeliminara solo las primerasmax_block_sizefilas coincidentes y, aun así, informara de que la mutación se había completado correctamente. También corrige queDELETEconkeeper_map_strict_mode = 1no fuera atómico: podía recurrir a eliminaciones sin versión y borrar filas actualizadas de forma concurrente, y aplicaba las filas coincidentes bloque a bloque, de modo que un conflicto podía dejar la eliminación aplicada parcialmente. #112777 (alexey-milovidov). - Se corrigió que un error transitorio de Azure Blob Storage en la ruta de lectura o de fusión —un
403 Forbiddenpor propagación de permisos RBAC, un fallo de autenticación de credenciales o un tiempo de espera de conexión notificado como408— se clasificara erróneamente como no reintentable y se notificara comoPOTENTIALLY_BROKEN_DATA_PART(Code 740), lo que generaba una falsa alerta crítica para una parte en buen estado. Ahora estos fallos transitorios se tratan como reintentables, y uno realmente persistente se notifica como un error simple de Azure en lugar de como una parte de datos dañada inexistente. #112871 (arsenmuk). - Se corrigió que
listObjectsen un disco de Azure Blob Storage con endpoint con prefijo devolviera nombres de blob incorrectos en todas las páginas posteriores a la primera, porque la paginación omitía el envoltorio del cliente que elimina el prefijo del endpoint. Ahora la paginación vuelve a pasar por el envoltorio mediante el token de continuación, de modo que los nombres de blob de cada página son correctos. #112872 (arsenmuk). - Corrige la pérdida del índice minmax por parte sobre
_block_numbery_block_offsettras recargar una tabla cuando la parte se generó mediante una mutación que no reescribe la parte completa. #112878 (alexey-milovidov). - Se corrigió una excepción (en builds de release, un error que impide que el servidor se inicie) cuando un predicado de mutación usa la función de tabla
mergesin un nombre de base de datos explícito. Ahora se usa la base de datos de la tabla mutada, igual que se hace con los nombres de tabla. #113185 (alexey-milovidov). - Se corrigen resultados incorrectos y un
LOGICAL_ERRORal leer una subcolumna de un miembroNestedeliminado y vuelto a añadir junto con un miembro presente del mismo grupo, en una tablaMergeTreeconshare_nested_offsets = 1. Los miembros presentes devolvían valores de un bloque posterior siempre que la lectura abarcaba más de un bloque. #113225 (groeneai). - Se corrige una excepción aritmética en compilaciones de depuración y con sanitizadores al leer de una tabla
Mergecon un valor muy grande demax_streams_to_max_threads_ratio: el número de flujos se truncaba a 32 bits, por lo que los múltiplos de2^32se convertían en cero. Además, ahora se lanzaPARAMETER_OUT_OF_BOUNDen lugar de provocar un comportamiento indefinido cuando el producto del número de flujos de una tablaMergeexcedesize_t, se evita un desbordamiento al limitar los flujos deMergeTreeen función de la cantidad de datos y se rechaza cualquier lectura de una tablaMergecuyo número total de fuentes supere 65536. #113382 (alexey-milovidov). - Se corrigen las escrituras en el disco
hdfs: fallaban conParent directory doesn't existporque las claves de objeto generadas contienen un prefijo de directorio anidado, pero, a diferencia de los almacenamientos de blobs, HDFS tiene directorios reales y no crea el directorio padre que falta al crear un archivo.. #113396 (alexey-milovidov). - Se corrige el error que se notificaba cuando las funciones de tabla
remote/remoteSecureo los motores de tablaRemote/RemoteSecurerecibían una colección con nombre inexistente junto con una sobrescriturakey = value. Dicha llamada se reinterpretaba silenciosamente como una llamada posicional, por lo que la sobrescritura se analizaba como una expresión de datos y el error notificado hacía referencia a algo que no tenía relación (por ejemplo, Function with namemergedoes not exist pararemote(collection, database = merge(...))). Ahora se notifica que la colección con nombre no existe. #113510 (groeneai). - Se corrige un bucle infinito en las fusiones en segundo plano y en
OPTIMIZEcuandomerge_max_block_size_bytesse establecía por debajo delbyteSize()de una columna vacía. Una columnaLowCardinalityvacía sigue conteniendo su diccionario, por lo que el límite de bytes podía alcanzarse antes de fusionar una sola fila; la fusión producía entonces bloques vacíos indefinidamente, consumía el 100 % de un núcleo de CPU y nunca liberaba su ranura del pool en segundo plano. #113585 (groeneai). - Se corrige que una mutación de una parte Compact produjera un resultado distinto según si la información de serialización de la parte seguía en memoria o se había recargado desde
serialization.json, cuando la tabla usaserialization_info_version = 'basic'. EnReplicatedMergeTree, esto hacía que dos réplicas con una parte de origen idéntica byte a byte escribieran partes mutadas diferentes, y la mutación fallaba conCHECKSUM_DOESNT_MATCH. #113588 (groeneai). - Las copias de seguridad ahora notifican el error subyacente de acceso al archivo de bloqueo, en lugar de indicar erróneamente que hay una copia de seguridad concurrente, cuando el almacenamiento de destino no puede leer el archivo .lock. #113637 (kirillshokhin).
- Se corrige una condición de carrera de datos entre las tareas en segundo plano de una tabla
MergeTree(actualización de estadísticas, actualización de partes, carga de partes obsoletas/inesperadas) y la destrucción de la tabla. #113722 (alexey-milovidov). - Se corrige que
UPDATEy la eliminación ligeraDELETEleyeran tablas incorrectas cuando la base de datos de la tabla actualizada difiere de la base de datos de la sesión. La expresión de la mutación ahora se canonicaliza respecto a la base de datos de la tabla actualizada, tanto para la función de tablamerge, que usa implícitamente la base de datos actual, como para los identificadores de tabla no cualificados. Anteriormente, dichos nombres se resolvían respecto a la base de datos de la sesión, por lo que la sentencia actualizaba o eliminaba silenciosamente filas seleccionadas de otra tabla. #113748 (groeneai). - Se corrigió una excepción al leer una tabla
MergeTreepor capas de rango de clave primaria cuando una capa produce un pipe vacío. #114177 (alexey-milovidov). BACKUP,RESTOREyENGINE = Backupahora autorizan la ubicación de la copia de seguridad según los permisosSOURCESdel usuario, del mismo modo que lo hacens3(),file()yazureBlobStorage(). Anteriormente, un usuario conBACKUPpero sinSOURCESpodía escribir y leer copias de seguridad en cualquier ubicación accesible para el servidor. Ahora, escribir una copia de seguridad requiere la direcciónWRITEsobre la fuente del destino (WRITE ON S3,WRITE ON AZURE,WRITE ON FILE) y leerla requiereREAD; los destinosDisk(...)siguen restringidos únicamente porbackups.allowed_disk. #114405 (groeneai).- Se corrigió la lectura de una tabla mientras hay una mutación en curso: una columna
MATERIALIZEDpodía devolver un valor obsoleto y, si se seleccionaba junto con una columna actualizada, la consulta podía fallar con un error. #114561 (tiandiwonder). - Se corrigió un error lógico (
Block structure mismatch) al leer una tablaMergeconmake_distributed_planhabilitado sobre tablas hijas con operaciones de conjuntos internas. #114753 (alexey-milovidov). OPTIMIZE TABLEsobre una tabla de almacenamiento de objetos cuyo motor no implementa la compactación indicaba que se había ejecutado correctamente sin hacer nada. Ahora genera un error, como cualquier otro motor que no admite la sentencia. Esto afecta aDeltaLake,Paimon,Hudiy a los motores de almacenamiento de objetos simples (S3,GCS,COSN,OSS,AzureBlobStorage,HDFSyURLrespaldado por almacenamiento de objetos);Iceberg, que sí implementa la compactación, no se ve afectado. #114805 (groeneai).- Se corrigió
BAD_DATA_PART_NAME(“Trying to get part name in new format for old format version”) en una tablaReplicatedMergeTreecreada con la sintaxis posicional obsoleta medianteallow_deprecated_syntax_for_merge_tree. Una mutación podía notificarse como completada en una réplica que no la había aplicado, y la tabla podía quedar en modo de solo lectura tras un reinicio. #114980 (groeneai). - Se corrigió
Found patch part ... that intersects mutation with version ...(LOGICAL_ERROR) en tablas con actualizaciones ligeras. Una fusión de partes de parche podía producir un parche cuyo rango de versiones de datos abarcara la versión de datos de una parte existente; ese parche no podía aplicarse ni omitirse, por lo que todas las operaciones posteriores sobre la partición fallaban y la cola de replicación se bloqueaba. Este tipo de fusiones ya no se asigna. #115064 (alexey-milovidov). - Se corrigió el fallo de arranque del servidor cuando un motor de base de datos
Backuphace referencia a una copia de seguridad que ha dejado de estar disponible (por ejemplo, porque se eliminaron sus archivos o el almacenamiento subyacente no es accesible). Ahora la base de datos se carga sin tablas en lugar de impedir que arranque todo el servidor. #83188 (orloffv). - Se corrigió la recuperación del registro tras un error de disco lleno. Anteriormente, cuando el disco de logs se llenaba, ClickHouse entraba en un estado de fallo e inundaba syslog con mensajes de error (llegando a escribir más de 100 GB/hora), sin recuperarse nunca, ni siquiera después de liberar espacio en disco. Ahora el sistema de registro se recupera automáticamente en cuanto vuelve a haber espacio en disco disponible, sin necesidad de reiniciar el servidor. #93127 (jaehanbyun).
- Se corrigió un fallo en el visitante de esquemas del almacenamiento DeltaLake. #97112 (kssenii).
Correcciones en lagos de datos y almacenamiento externo
- Se corrigió un fallo transitorio
Code: 499 ... InvalidPart(S3_ERROR) en las cargas multiparte de S3 (por ejemplo,INSERT INTO ... hits_s3). MinIO puede indicar brevemente que una parte recién cargada no existe enCompleteMultipartUpload; ahora este error se reintenta del mismo modo queNoSuchKey, que ya se gestionaba, con el límite establecido pors3_max_unexpected_write_error_retries. #109364 (groeneai). - Ahora se rechazan
ALTER TABLE ... DELETEyALTER TABLE ... UPDATEen tablas Iceberg cuyo formato de archivo de datos no esParquet, con un errorNOT_IMPLEMENTEDclaro, en lugar de provocar la caída del servidor o corromper la tabla de forma silenciosa. #105893 (groeneai). - Se corrigió el error
Cannot add column ...: column with this name already existsenINSERT SELECTdesde una función de tabla comofile,s3oinputcuando la misma columna de origen se selecciona más de una vez. #105982 (crakjie). - Los valores sensibles pasados como parámetros de la cadena de consulta HTTP (por ejemplo, la vinculación de parámetros de consulta
param_*, comoparam_secret_key/param_aws_secret_access_key, el parámetropasswordo los parámetrossignaturede estilo S3) ya no se escriben literalmente ensystem.text_logni en los spans de OpenTelemetry. La línea de logRequest URIahora oculta los valores de los parámetros cuyos nombres parecen sensibles y los sustituye por[HIDDEN]. #108475 (groeneai). - Se corrigió la columna virtual
_etagde los motores de tablaS3QueueyAzureQueue: estaba declarada pero nunca se rellenaba, por lo queSELECT _etagsiempre devolvía una cadena vacía. Ahora devuelve el ETag del objeto, igual que el motorS3y la función de tablas3(). #108625 (groeneai). - Una consulta que lee o escribe en S3 y se cancela (por ejemplo, mediante
KILL QUERY) mientras hay una solicitud a S3 en curso ahora se notifica como cancelada, en lugar de con un error engañoso de red o de S3. En concreto, una copia de seguridad o restauración en S3 cancelada ahora notificaBACKUP_CANCELLED/RESTORE_CANCELLEDensystem.backups. #108673 (jkartseva). - Se corrigió la columna virtual
_tagsdel motor de tablaS3Queue: estaba declarada pero nunca se rellenaba, por lo queSELECT _tagssiempre devolvía un mapa vacío. Ahora devuelve las etiquetas del objeto, igual que el motorS3y la función de tablas3(). #108676 (groeneai). - Se corrigió un problema por el que SHOW TABLES y SELECT … FROM system.tables devolvían resultados distintos para bases de datos de catálogos de data lake: ahora las tablas que ClickHouse no puede leer se ocultan de forma coherente en ambos casos. #109273 (SmitaRKulkarni).
- Se corrigió una terminación abrupta del servidor (o, en las builds de release, un archivo de datos que quedaba sin finalizar de forma silenciosa) cuando un
INSERTen una tabla de Delta Lake (DeltaLakeLocal/deltaLake) falla después de que el sink haya empezado a escribir; por ejemplo, cuando la consulta de origen lanza una excepción a mitad de la inserción o se cancela la consulta. #109328 (groeneai). - Se corrigió el error
Not found column or subcolumn c.null in block(yBad cast from ColumnConst to ColumnNullableen builds de depuración/sanitizer) al ejecutarWHERE col IS NULL/IS NOT NULLsobre una columna Iceberg añadida mediante evolución del esquema después de que se escribieran archivos de datos más antiguos, conoptimize_functions_to_subcolumns=1(el valor predeterminado). #109515 (groeneai). - Se corrige el error
Host is empty in S3 URIcuando se usa una subconsulta escalar como argumento de URL de la función de tablas3(o como argumento de cualquier otra función de tabla) en consultasCREATE TABLE ... AS SELECT: las subconsultas escalares en los argumentos de funciones de tabla ahora se evalúan durante el análisis de la consulta. #110254 (CheSema). - Se corrige un error lógico (aborto del servidor en compilaciones de depuración/sanitizer) que se producía al ejecutar un
ALTERcon varios comandos, comoUPDATE ..., DELETE ..., sobre una tabla Iceberg. Ahora estas mutaciones se rechazan con un errorNOT_IMPLEMENTEDclaro. #110347 (groeneai). - Se corrige un problema por el que las tablas Iceberg generaban IDs de campo duplicados tras
ALTER TABLE ... ADD COLUMNcuando el esquema inicial contenía campos anidados (Tuple/Array/Map).last-column-idahora registra el ID de campo máximo asignado, incluidos los hijos anidados, de modo que una columna añadida posteriormente ya no reutiliza un ID de campo anidado y las lecturas ya no fallan conICEBERG_SPECIFICATION_VIOLATION(Duplicate field id). #110884 (groeneai). - Se corrige un problema por el que
DELETE/UPDATEsobre una tabla Iceberg eliminaba silenciosamente filas incorrectas (o lanzabaNOT_FOUND_COLUMN_IN_BLOCK) cuando la tabla contenía archivos de datos escritos tanto antes como después deALTER TABLE ... ADD COLUMNyoptimize_move_to_prewhereestaba habilitado. #111693 (groeneai). - Se corrige un problema por el que
made_current_atensystem.iceberg_historypasaba a ser1970-01-01para una instantánea conservada tras ejecutarALTER TABLE ... EXECUTE expire_snapshotssobre una tabla Iceberg. También se corrige quesystem.iceberg_historyno devolviera filas para una tabla cuyos metadata no incluyensnapshot-log. #111781 (groeneai). - Se corrige la corrupción de datos al insertar en una tabla Iceberg a través de una
MATERIALIZED VIEW. El archivo de datos se escribía con los tipos de columna que tenía el destino en el momento delCREATE, en lugar de con su esquema Iceberg actual, por lo que un valorDateTimese almacenaba como un simpleintde Avro y se leía como microsegundos, y conDateTime64(0)oDateTime64(9)el archivo directamente no podía leerse. En consecuencia,INSERT INTO <materialized view>sobre un destino cuyo esquema Iceberg es más amplio que las columnas declaradas de la vista ahora generaTYPE_MISMATCHen lugar de escribir una fila corrupta. #112359 (groeneai). - Se corrige la escritura de tablas Iceberg cuyo esquema contiene una tupla anidada dentro de otra tupla. Los metadata publicados de la tabla sustituían los nombres de campo de la tupla interna por nombres posicionales
1,2, …, por lo que con el formato predeterminadoParquetelINSERTfallaba conINCORRECT_DATAy conAvrola columna no podía volver a leerse. #112480 (groeneai). - Se corrige un interbloqueo que dejaba bloqueada de forma permanente una base de datos
FilesystemoHDFScuando dos consultas resolvían el mismo nombre de tabla simultáneamente. Todas las consultas posteriores sobre esa base de datos quedaban bloqueadas indefinidamente sin posibilidad de interrumpirlas, por lo que era necesario reiniciar el servidor para recuperarla. #112495 (groeneai). - Se corrige un problema por el que las tablas
DeltaLakedevolvían menos filas de las debidas cuando el predicadoWHEREcontenía, bajo unNOT, una subexpresión que el traductor de predicados de delta-kernel no puede manejar. Ahora dicha subexpresión se notifica a delta-kernel como un predicado desconocido explícito en lugar de como el final del iterador hijo, lo que antes truncaba silenciosamente la conjunción que la contenía. #112652 (groeneai). - Se corrigió que
ALTER TABLE ... EXECUTE remove_orphan_fileseliminara unmetadata/version-hint.textactivo de una tabla Iceberg. Su entrada en el conjunto de archivos alcanzables se construía mediante concatenación de cadenas suponiendo una barra final en un valor que nunca la tiene, por lo que el archivo de pista real nunca se reconocía como alcanzable y se eliminaba en cuanto superaba el umbralolder_than. Coniceberg_use_version_hint = 1, la tabla dejaba de poder leerse por completo. #113548 (groeneai). - Se corrigió un
LOGICAL_ERRORal filtrar una columna Iceberg queALTER TABLE ... MODIFY COLUMNhabía convertido enNullable. #114521 (groeneai). - Se corrigió un caso en el que
ATTACH TABLEcon una definiciónENGINE = URL(...)no comprobaba el permisoTABLE ENGINEdel motor al que redirige el esquema de la URL. Un usuario que solo tuvieraTABLE ENGINE ON URLpodía adjuntar y luego leer una tabla respaldada porFile,S3,AzureBlobStorageoHDFS, algo queCREATE TABLErechaza correctamente. #115914 (groeneai). - Se corrigió que las solicitudes HTTP salientes (p. ej., `aiGenerate`, la función de tabla `url`, S3) fallaran con `No route to host` en hosts que anuncian tanto IPv4 como IPv6 cuando solo una de las familias de direcciones es enrutable. El pool de conexiones HTTP ahora recurre a la siguiente dirección resuelta cuando la primera falla con un error de red, en lugar de propagar el error ya en la primera solicitud. #103786 (alexey-milovidov).
- Ahora se puede leer un
arrayde Avro compuesto por registros{key, value}de dos campos en una columnaMapde ClickHouse. Esta es la codificación que generan Iceberg y Spark para unMAP<K, V>cuya clave no es de tipo cadena (los mapas nativos de Avro solo admiten claves de tipo cadena). Antes, un archivo así podía leerse comoArray(Tuple(key, value)), pero no comoMap(K, V), que fallaba conType Map(...) is not compatible with Avro array. #109289 (groeneai). - Se corrigió la lectura de una tabla Iceberg con un archivo de metadata cuyo número de versión está compuesto solo por dígitos, pero excede el rango de los enteros de 32 bits (por ejemplo,
v99999999999999999999.metadata.json). Antes, un nombre así producía un error poco descriptivostd::out_of_range(STD_EXCEPTION) en lugar de un errorBAD_ARGUMENTSclaro. #109619 (groeneai). - Se corrigió el nombre de los archivos de metadata de Iceberg comprimidos con gzip. ClickHouse los escribía como
v{N}.gzip.metadata.json(el tokenContent-Encodingde HTTP), mientras que la especificación de Iceberg espera la extensióngz:v{N}.gz.metadata.json. Por ello, Spark y otros lectores de catálogos Hadoop no encontraban la metadata escrita por ClickHouse. ClickHouse ahora escribev{N}.gz.metadata.jsony sigue leyendo el nombre heredadogzippor compatibilidad con versiones anteriores. #109812 (groeneai). - Se corrigió que una tabla Iceberg con formato de escritura
Avroserializara como obligatorio un campo declarado"required": falsecuyo tipo eslist,mapostruct, sin una unión["null", T], de modo que el propio esquema del archivo de datos no coincidía con la metadata de la tabla y otros lectores de Iceberg veían un campo obligatorio. Ahora, dicho campo se escribe como la unión["null", T]que la especificación de Iceberg utiliza para los campos opcionales. #112648 (groeneai). - Se corrigió que
made_current_atensystem.iceberg_historyindicara el primer momento en que una instantánea pasó a ser la actual, en lugar del más reciente, cuando el mismosnapshot-idaparece más de una vez en elsnapshot-logde Iceberg (como ocurre tras un rollback). #113598 (groeneai). - Se corrigió un bloqueo de hasta una hora en
BACKUP/RESTORE ... TO S3, en los discos GCS y en la función de tablas3cuando la colección con nombre establecehttp_client = 'gcp_oauth'y el endpoint de tokens OAuth2 de Google acepta la conexión pero nunca responde. La solicitud del token Bearer ya no hereda el tiempo de espera de solicitud de transferencia de datos del llamador; la espera de su respuesta está limitada a 10 segundos, igual que el límite de la solicitud STSAssumeRole. #115531 (groeneai). - Se corrigió un error lógico en la caché del sistema de archivos (
Expected file ... not to exist) que podía producirse cuando una descarga de caché en segundo plano fallaba con una excepción distinta deErrnoException(por ejemplo, al ejecutarOPTIMIZEsobre una tabla Iceberg) y dejaba un archivo de caché huérfano vacío. #110549 (groeneai). - Se corrigió que las cachés configuradas con un número máximo de entradas (política
SLRU) dejaran de admitir nuevas entradas sin previo aviso una vez que ese mismo número de entradas se hubiera accedido al menos dos veces. Entre las cachés afectadas figuran las cachés de archivos de metadatos de Iceberg y Paimon, la caché de metadatos de Parquet, las cachés de índices de texto, la caché de índices de similitud vectorial, la caché de expresiones compiladas y la caché de estado de archivos de ObjectStorageQueue. #115517 (groeneai). - Se corrigieron las lecturas de tablas Paimon que podían fallar mientras la pista mutable
snapshot/LATESTse reemplazaba de forma concurrente. Ahora, ante pistas no válidas u obsoletas, se recurre de forma segura al listado de instantáneas. #112010 (JiaQiTang98). - Ahora se muestra la excepción subyacente real cuando no se puede descomprimir un archivo zip porque el búfer de entrada (p. ej., un búfer de lectura de S3 con
restricted_seek = true) rechaza un reposicionamiento o una lectura solicitados por minizip. Antes, el error real quedaba oculto tras el mensaje genéricoCouldn't unpack zip archive: Code = -100/Couldn't open zip archive. #105103 (groeneai). - Se corrigió la escritura en Iceberg para metadatos sin refs #106896 (AVMusorin).
- Se corrigió una excepción al insertar en una tabla Iceberg cuyos metadatos fueron creados por un motor externo y omiten los arrays opcionales
snapshots,metadata-logosnapshot-log. Estas inserciones ahora se completan correctamente en lugar de fallar. #107473 (tiandiwonder). - Se corrigió un error
ReadBuffer is canceled. Can't read from it.que podía producirse al reintentar una subida a S3 (por ejemplo, una copia de seguridad) tras un error de lectura transitorio. #108573 (groeneai). - Se corrigió un
std::future_error(“The associated promise has been destructed prior to the associated state becoming ready”) que podía producirse, y abortar el servidor en compilaciones de depuración o con sanitizador, cuando fallaba la planificación de la tarea asíncrona final que completa la subida multiparte a S3/Azure (por ejemplo, al agotarse el pool de hilos). Ahora se notifica el error de planificación real. #108730 (groeneai). - Se corrigió la lectura de marcas de tiempo ORC posteriores aproximadamente al año 2262 en una columna
DateTime64con una escala menos precisa que 9. El lector ORC nativo convertía cada marca de tiempo mediante un valor intermedio fijoDateTime64(9), que desbordaInt64a escala de nanosegundos, y rechazaba dichos valores conVALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, incluso cuando la escalaDateTime64solicitada (por ejemplo,DateTime64(6), como la que genera Iceberg) podía representar el valor. Ahora las marcas de tiempo se leen directamente en la escala solicitada y se respetadate_time_overflow_behaviorcuando ni siquiera la escala de destino puede contener el valor. #109302 (groeneai). - Al leer una tabla Paimon cuyo esquema contiene un tipo anidado no compatible (por ejemplo, un campo
ROW), ahora se notifica un errorBAD_ARGUMENTSclaro que indica el tipo no compatible, en lugar de un simpleDB::Exception. (OK)con código de error 0 y sin mensaje. #109762 (groeneai). - Se corrigió la lectura de tablas Iceberg particionadas más de una vez por la misma columna de origen (por ejemplo,
PARTITIONED BY (hours(ts), ts)). Anteriormente, estas tablas fallaban conCannot add column ...: column with this name already exists (ILLEGAL_COLUMN). #109895 (groeneai). - Los archivos de datos que ClickHouse escribe en tablas Iceberg ahora incorporan los ID de campo de Iceberg para los formatos Avro (
field-id) y ORC (atributos de tipoiceberg.id/iceberg.required), y las columnasStringde ORC se escriben comostringde ORC en lugar de binario. Anteriormente solo Parquet incorporaba los ID de campo, por lo que los lectores que cumplen la especificación (p. ej., Spark/iceberg-java) devolvían NULL sin avisar en las filas Avro escritas por ClickHouse tras renombrar una columna, y no podían leer en absoluto los archivos ORC escritos por ClickHouse. #109994 (groeneai). - Se corrigió un error lógico
ChunkInfoRowNumbers does not existal ejecutarOPTIMIZE TABLEsobre una tabla Iceberg que contenía un archivo de datos en un formato distinto de Parquet (p. ej.,ORC) más reciente que todos los archivos de eliminación por posición. #110107 (alexey-milovidov). - Se corrigió la lectura de archivos
Parquetgrandes desde entradas zipSTOREDsin comprimir mediantes3yfile. #110495 (Gudauu). - Un fallo al iniciar un pool de programación en segundo plano (por ejemplo, el pool
iceberg, cuando se agota el pool global de hilos) ya no aborta el servidor: ahora el error es una excepción recuperable. Además, leersystem.background_schedule_poolya no crea esos pools como efecto secundario. #111209 (groeneai). - Se corrigió la autenticación DLF en el catálogo REST de Paimon: la firma de la solicitud se calculaba una sola vez y se reutilizaba, por lo que todas las solicitudes al catálogo posteriores a la primera fallaban con HTTP 401 y SHOW TABLES devolvía una lista vacía. También se corrigió la detección de HTTP 404 en las comprobaciones de existencia de tablas. #112015 (JiaQiTang98).
- Se corrigió un
LOGICAL_ERROR(partitions_count > 0) al particionar fragmentos de datos deIcebergque habían quedado vacíos tras eliminaciones por posición, p. ej., durante la compactación de una tablaIcebergparticionada con archivos de datos completamente eliminados. #112432 (PedroTadim). - Se corrigió un problema por el que la eliminación de objetos por batch en Azure no registraba eventos Delete en
system.blob_storage_logcuando fallaba la propia solicitud del batch, con lo que todo el batch quedaba sin registrar. Ahora se registra un evento Delete para cada objeto cuando se produce un fallo a nivel de batch. #112873 (arsenmuk). - Se corrigió la lectura de tablas
Paimonparticionadas por una columnaTIMESTAMPcon una precisión superior a milisegundos, que fallaba conscale 6 is not supported, only support scale <= 3. #113401 (JiaQiTang98). - Se corrige un fallo al leer una tabla de lago de datos cuyo esquema declara una columna con un nombre vacío. Los metadatos de Iceberg mal formados se rechazan con
ICEBERG_SPECIFICATION_VIOLATION; un esquema proporcionado por un catálogo, Delta Lake o Paimon se rechaza conAMBIGUOUS_COLUMN_NAME. La comprobación es incondicional, por lo que una tabla Iceberg que simplemente conserve un esquema histórico sin usar con un nombre de campo vacío también pasa a ser ilegible, en lugar de provocar un aborto en el momento en que se lee dicho esquema. #114394 (groeneai). - La lectura de una tabla Iceberg cuyos metadatos describen una evolución de esquema prohibida por la especificación de Iceberg ya no provoca el aborto del servidor. Cuatro infracciones de la especificación en
IcebergSchemaProcessorse notificaban comoLOGICAL_ERROR, que se trata como una aserción fallida, o llegaban sin comprobar a una aserción fatal; ahora generanICEBERG_SPECIFICATION_VIOLATION. #114518 (groeneai). - Se corrigió que la columna virtual
_timede las funciones de tablaurl/urlClusterfuera siempreNULLen compilaciones basadas en musl, debido a un análisis no portable del encabezado HTTPLast-Modified. #111619 (thevar1able). - Se corrigió un problema por el que el servidor no arrancaba tras crear una tabla con
CREATE TABLE ... AS url('http://host/**/', ...)conallow_experimental_url_wildcard_from_index_pageshabilitado. Al cargar los metadatos de dicha tabla se volvía a evaluar la comprobación experimental, que fallaba conSUPPORT_IS_DISABLEDe interrumpía el arranque. #115095 (groeneai). - Una tabla del motor de base de datos
URLya no revela si existe un archivo local a un usuario que carece del permiso de lectura de origen: niEXISTS TABLE, que solo requiere el privilegioSHOW TABLES, ni la resolución de una tabla consultan ya el sistema de archivos antes de confirmar el permiso. #113029 (alexey-milovidov). - Se aplica
query_masking_rulesa los mensajes añadidos medianteException::addMessage, de modo que las credenciales codificadas en URL de los sufijos(in file/uri ...)de los errores dejdbc()/odbc()no se filtren cuando hay reglas de enmascaramiento configuradas. #106916 (gaurav0107).
Correcciones de formatos e ingestión
- Las lecturas sin esquema de
time32/time64de Arrow (p. ej.,SELECT * FROM file(..., 'Arrow')) ahora infierenTime64en lugar deDateTime64. Anteriormente se inferíaDateTime64. Cualquier proceso posterior que dependa del tipo inferido anterior dejará de funcionar tras la actualización. También se añade compatibilidad para exportarTime/Time64a Arrow, seleccionando el tipo de tiempo de Apache Arrow adecuado según la precisión. #104316 (Maoyao233). - Se corrigieron posibles resultados incorrectos o lecturas fuera de límites cuando un
INSERTse revierte tras un error a mitad de lote (por ejemplo, en tablasBuffer, inserciones asíncronas o los motoresKafka/RabbitMQ/FileLog) mientras está activa la replicación diferida de columnas (enable_lazy_columns_replication). #108935 (groeneai). - Se corrigió una incoherencia del analizador por la cual una lista de columnas de
INSERTaceptaba un selector de columnas calificado escrito comot.* LIKE '<pattern>'/t.* ILIKE '<pattern>', pero rechazaba su forma canónicat.COLUMNS('<regexp>'), lo que impedía el formateo de ida y vuelta de la consulta (y abortaba el servidor en compilaciones de depuración/sanitizador). #109176 (groeneai). - Se corrigió el fallo de
INSERTconIncorrectEndpointError(HTTP 400) en una tablaDataLakeCatalogde Microsoft Fabric / OneLake: ahora las escrituras de ADLS Gen2 (DFS) se dirigen al host del endpoint.dfsen lugar del host.blob. Nota: conremote_url_allow_hosts, tanto el host.blob(lectura) como el.dfs(escritura) de Fabric deben incluirse en la lista de permitidos paraINSERT. #110290 (zlareb1). - Se corrigieron las escrituras mediante funciones de tabla de data lake (p. ej.,
INSERT INTO FUNCTION icebergS3(...)) que generaban archivos Parquet cuyas columnas de cadena perdían la anotación de tipoString, lo que hacía que los datos escritos fueran ilegibles para lectores externos como Spark. Estas escrituras ahora usan la misma configuración de formato que las realizadas mediante el motor de tabla. #110465 (tiandiwonder). - Se corrigió que
system.session_logquedara ilegible tras un inicio de sesión mediante Arrow Flight: la columnainterfacees unEnum8, pero faltaba el valorArrowFlighten su enumeración, por lo que un inicio de sesión mediante el protocolo Arrow Flight escribía el valor bruto10y cualquierSELECTque leyera esa fila lanzaba la excepciónUnexpected value 10 in enum. #110758 (alexey-milovidov). - Se corrige la inferencia de esquema de la familia de formatos
TSV, que inferíaStringpara un valor decimal escrito con un cero inicial, como0.0o0.5, mientras queCSVinfiere correctamenteFloat64. Además, la detección automática de encabezados deTSVconsumía como encabezado una primera fila con dichos valores, que desaparecía del resultado. También se corrige queTSKVinfiriera un tipo numérico para un valor escrito con una secuencia de escape, comox=1\x2E5, que después no se podía analizar. Los valores cuyo cero inicial es relleno de un entero, como007, se siguen infiriendo comoString, ya que el analizador de valores deTSVno puede volver a leerlos. #112226 (groeneai). - Se corrigió que la inferencia de esquema propusiera un tipo numérico para valores de texto que el analizador de valores no puede volver a leer. La inferencia aceptaba un exponente incompleto (
1e+), una mantisa ausente (.) o un signo repetido (++inf), quereadFloatTextPreciserechazaba después conCANNOT_PARSE_NUMBERal leer el esquema inferido; en una columnaDynamic, esto provocaba un error en el momento del INSERT. Ahora la inferencia valida el número con el mismo analizador que utiliza el lector. Esto también elimina un caso en el que el tipo inferido dependía demax_read_buffer_sizey permite que las formas válidas de exponente con ceros a la izquierda, como0e5, se infieran comoFloat64en TSV, tal como ya ocurre en CSV. Además, corrige las formas de exponente mal formadas. #112453 (groeneai). - Se corrige que
KILL QUERYymax_execution_timese ignoraran durante minutos mientras un formato de entrada basado en filas analizaba un bloque. Ahora los formatos de entrada basados en filas comprueban si la consulta se ha cancelado cada 8192 filas, de modo que una inserción terminada (en particular, un vaciado de inserción asíncrona en segundo plano, que analiza hastamax_insert_block_sizefilas por bloque) se detiene de inmediato en lugar de continuar hasta el final del bloque. #112646 (groeneai). - Se corrigió que el tipo de columna inferido dependiera del orden de las consultas anteriores en un origen cuyo esquema está en caché. Las configuraciones que modifican un tipo inferido no formaban parte de la clave de la caché de inferencia de esquema, por lo que el valor de la primera consulta determinaba el tipo que veían todas las consultas posteriores:
input_format_try_infer_exponent_floats,max_parser_depth,input_format_json_infer_array_of_dynamic_from_array_of_different_typesy, paraParquet, tambiéninput_format_parquet_local_time_as_utc,input_format_parquet_allow_geoparquet_parser,input_format_parquet_skip_columns_with_unsupported_types_in_schema_inferenceyschema_inference_make_json_columns_nullable. Asimismo, registra el getter de clave de caché que faltaba paraFormy hace que el getter deTemplateutilice la regla de escape de su propio formato de fila. #113533 (groeneai). - Se corrigió el formateo de un argumento de subconsulta de las funciones de tabla
viewyviewIfPermittedcuando la consulta que las contiene termina con una cláusulaSETTINGS. Dicha consulta se formateaba comoview((SELECT ...)), que no puede volver a analizarse, por lo que no superaba la comprobación interna de formateo-análisis-formateo y generabaInconsistent AST formatting. #114658 (groeneai). - Se corrige que los datos JSON se detectaran erróneamente como TSKV durante la detección automática del formato. #106009 (Avogar).
- La exportación al formato
Arrowde valoresTime/Time64fuera de una hora del día válida (negativos o>= 24h) ahora se rechaza con un error claro en lugar de escribir datos Arrowtime32/time64no válidos. #107179 (tiandiwonder). - Se corrigió la lectura de archivos
Arrow,ArrowStreamyORCbasados en Arrow cuya columna de marca de tiempo usa como zona horaria un desfase UTC numérico fijo (p. ej.,+05:30,-08:00,00:00) o el marcador no IANAfixed, que antes fallaba conCannot load time zone ...(BAD_ARGUMENTS). #108633 (groeneai). - Ahora una columna
Nullable(Tuple(...))se serializa como un único campo CSV en lugar de aplanarse en columnas separadas. Antes, un valor no nulo se escribía como varios campos CSV, mientras que unNULLera un único\N, lo que daba lugar a un número de columnas variable según la fila que rompía los encabezados deCSVWithNames/CSVWithNamesAndTypesy las conversiones de ida y vuelta. #108959 (groeneai). - Se corrigió una asignación de memoria excesiva durante la inferencia de esquema del formato
MsgPack: una entrada corrupta o generada mediante fuzzing cuyo encabezado de array/mapa/string/binario declara un número enorme de elementos ya no provoca una única asignación de varios gigabytes (ahora se rechaza como entrada mal formada). Esto corrige una interrupciónallocation-size-too-bigcon sanitizadores y una condición de falta de memoria en las builds de release. #109019 (groeneai). - Se corrigió un
LOGICAL_ERRORal escribir una columnaLowCardinality(Time)en el formatoArrowconoutput_format_arrow_low_cardinality_as_dictionary = 1. #109730 (groeneai). - Se corrigió la lectura de un stream corrupto en formato
Nativecuyo número de tiposDynamico de rutasJSON/Objectse aproxima aSIZE_MAX: este tipo de entrada mal formada ahora se rechaza con un errorINCORRECT_DATAclaro, en lugar de producir unstd::length_errorno capturado. #110590 (alexey-milovidov). - Se corrigió un
LOGICAL_ERROR: Cannot sum Bools(interrupción del servidor en builds de depuración o con sanitizadores) al combinar estados de agregación desumMap/sumMapWithOverflow/sumMapFilteredcon valoresBoolserializados en el formato de estado antiguo (versión 0). La misma corrección resuelve además dos casos en los que se devolvían resultados incorrectos de forma silenciosa con estadosBoolde versión 0: las claves de mapa de tipoBoolno se deduplicaban entre estados y la compactación de valores cero eliminaba entradas equivocadas. #110922 (groeneai). - Se corrigió que la función de tabla
formatlanzaraNOT_FOUND_COLUMN_IN_BLOCKcuando el análisis de los datos de entrada no produce ninguna fila (por ejemplo, un JSON vacío o unFeatureCollectionde GeoJSON sin features). Ahora devuelve un resultado vacío con las columnas correctas. #111428 (groeneai). - Ahora es posible leer archivos GeoParquet, Arrow y ArrowStream cuya columna de geometría codificada en WKT usa una palabra clave de tipo que no está en mayúsculas (
point(1 2)) o un contenedor vacío (LINESTRING EMPTY,POLYGON(),POLYGON(())). Hasta ahora, la importación de estos archivos fallaba conBAD_ARGUMENTSoCANNOT_PARSE_NUMBER, aunque la funciónreadWKTanalizaba correctamente esas mismas cadenas. También se corrige la lectura de un archivo que almacena la salida dewktpara una geometría vacía, que se escribe comoLINESTRING(). #112020 (groeneai). - Se corrigió el error
Unknown compression methodque se lanzaba con las pistas de compresiónautoynonecuando no estaban escritas completamente en minúsculas, por ejemplofile('data.csv.gz', 'CSV', 'x String', 'AUTO'). Los nombres de códecs comoGZIPya se aceptaban sin distinguir entre mayúsculas y minúsculas; ahora estas dos pistas especiales se comportan igual. #113631 (groeneai). - Se corrigió la lectura de una columna
Tuplecuyo primer elemento esNULLen los formatosCustomSeparated,RegexpyTemplatecon la regla de escapeCSV. En estos formatos, unTuplesimple ocupa un campo por elemento, por lo que el campo\Ninicial corresponde a ese elemento y no a toda la columna. Antes se interpretaba como la columna completa, lo que desplazaba los campos de los elementos restantes a las columnas siguientes e impedía queCustomSeparatedpudiera volver a leer su propia salida. #114471 (groeneai). - Se corrigió que el formato de entrada
Regexpdescartara silenciosamente el resto no analizado de un campo coincidente, lo que almacenaba un valor truncado o inventado en lugar de notificar un error: con la reglaJSON,v=-1enUInt64se leía como0, yv=2020-01-01junkenDatese leía como1975-07-14. Ahora los campos mal formados se rechazan con las reglasEscaped,CSVyJSON, en consonancia con los formatos a los que, según la documentación, se asemeja el comportamiento de dichas reglas. ConRaw, un campo coincidente que contiene un tabulador ahora se lee completo en lugar de truncarse en el tabulador. #114520 (groeneai). - Se corrigió un error lógico
Inconsistent AST formatting(que provocaba la terminación abrupta del servidor en builds de depuración y con sanitizador) en expresionesCREATE INDEX/CREATE HYPOTHETICAL INDEXque no superaban un ciclo completo de formateo-análisis-formateo, por ejemploCREATE HYPOTHETICAL INDEX i0 ON t0 ((a())) TYPE ayCREATE INDEX i0 ON t0 ((a, b).1) TYPE minmax. #109175 (groeneai). - Se corrige un error lógico (
Logical error: 'KeyCondition uses PREWHERE output') en el lector de Parquet v3 que se producía cuando una condición de clave a nivel de formato hacía referencia a una columna que no se lee del archivo Parquet. #109267 (groeneai). - Se corrige una excepción en el HTTP handler predefinido cuando falta un encabezado #108324 (vitlibar).
- Se corrigió un posible
Logical error: 'ReadBuffer is canceled. Can't read from it.'cuando un formato de entrada basado en filas (p. ej.,TSV/CSV) no lograba analizar la entrada y la lectura subyacente ya se había cancelado (por ejemplo, por un fragmento HTTP mal formado o un cuerpo truncado). La generación de los diagnósticos detallados de análisis ya no lee de un búfer cancelado. #109708 (groeneai). - El formato
Valuesya no registra errores de análisis ensystem.errorsni ensystem.error_logcuando el análisis en streaming recurre correctamente al análisis de expresiones SQL. #111141 (pamarcos). - Se corrige que
SYSTEM REFRESHsobre una tablaRabbitMQdetenida a veces no consumiera los mensajes pendientes en cola. Un REFRESH concede exactamente un ciclo de streaming fuera de orden, pero ese ciclo podía finalizar de inmediato con cero filas porque el bucle de entrega AMQP acababa de iniciarse de forma asíncrona, con lo que se desperdiciaba el único permiso y los mensajes quedaban sin consumir hasta el siguienteSYSTEM START. #111480 (groeneai). - Se corrige que una tabla
NATSconnats_streamconfigurado dejara de consumir mensajes silenciosamente tras reiniciarse el servidor NATS. La suscripción deJetStreamahora se restablece automáticamente, sin necesidad de ejecutarDETACH TABLEyATTACH TABLE. #112828 (groeneai). - Se rechaza un valor desmesuradamente grande de
kafka_num_consumerscon un error claro, en lugar de que falle una asignación dentro del motor de tablaKafka. Anteriormente, conkafka_disable_num_consumers_limithabilitado, dicho valor producía una excepciónstd::length_error. #114764 (alexey-milovidov). - Servidor Arrow Flight: se aceptan credenciales de autenticación
Basiccodificadas en Base64 sin relleno, tal como las envían los clientes de Flight basados en Go (por ejemplo, el controlador ADBC Flight SQL), y se devuelve un error de autenticación adecuado en lugar del genéricoUnexpected error in RPC handlingcuando el encabezadoauthorizationestá mal formado. #115085 (alexey-milovidov). - Servidor Arrow Flight: ahora rechaza las credenciales de autenticación Basic mal formadas que omiten el separador entre el nombre de usuario y la contraseña. #115347 (alexey-milovidov).
Correcciones de tipos de datos, funciones y serialización
- Se corrigió un error lógico
Stream <col>.variant_discr ... is not found(aborto del servidor en compilaciones de depuración y con sanitizers) que se producía cuandoALTER TABLE ... MODIFY COLUMNconvertía una columna a un tipo con subcolumnas dinámicas (por ejemplo, deVariantaDynamic) en una tabla con partes Wide, y la parte se leía o fusionaba posteriormente. #110204 (groeneai). - Se corrigió la lectura de una subcolumna de una columna
Nullable(Tuple(...))cuyo elemento es unLowCardinality(T)no nullable cuando la misma consulta también lee la subcolumna padre. En una parte Compact, la subcolumna padre devolvía valores incorrectos, la consulta fallaba conUnexpected return type from assumeNotNullo el servidor terminaba abruptamente por una aserción de refuerzo destring_view, porque la subcolumna extraída se deserializaba en un búferLowCardinality(Nullable(T))cuyos subflujos se compartían luego con la lectura de la subcolumna padre. #112232 (groeneai). - Se corrigió un
LOGICAL_ERROR“Not-ready Set is passed as the second argument for functionglobalNullIn” y la pérdida del mensaje de error real de la consulta, que podían producirse cuando la poda de partes basada en estadísticas ejecutaba de forma especulativa una subconsultaIN/GLOBAL INdurante el análisis de índices y dicha subconsulta fallaba. #114121 (groeneai). - Se corrigió el error
Cannot read all data of type FixedStringal leer la subcolumnaproduct_quantization_codebookde una columna con un códecQuantized('product', ...). El codebook de cada parte se escribe después de los datos de todos los gránulos, por lo que no está delimitado por marcas, y una lectura cuyo rango de marcas terminara antes de la marca final de la parte podía leerlo de forma incompleta. #112818 (alexey-milovidov). - Ya no se escriben partes cuya disposición de
Mapcontradice sus propios metadata, en el caso de un valorMapdentro de una columnaDynamic. Las tablas que solo diferían enmap_serialization_versioncompartían un mismo objeto de serialización en caché, de modo que una parte podía recibir la disposición de Mapbasicmientras sus metadata declarabanwith_buckets, y su lectura posterior fallaba conLOGICAL_ERROR: Stream ...buckets_info ... is not found. Las partes que una versión anterior ya haya escrito de esta forma siguen siendo ilegibles y deben eliminarse. #113514 (groeneai). - Se corrigió que
ALP,FPCyGCDomitieran en el hash del códec su parámetro derivado del tipo. En una parte Compact, el escritor comparte un flujo comprimido por cada hash de códec distinto, por lo que dos columnas con distinto ancho de valor y el mismo códec colisionaban y compartían un único objeto de códec con el ancho incorrecto. Como consecuencia, se rechazaban inserciones válidas conCANNOT_COMPRESScuando los anchos no coincidían y, en otros casos, una de las columnas se comprimía peor de lo debido. #114189 (groeneai). - Se corrigió una poda de índice incorrecta cuando la clave de ordenación de una tabla envuelve una columna
DateentoDateTime(por ejemplo,ORDER BY toDateTime(date_column)) y una consulta filtra por la columna original con una comparación comoWHERE date_column >= '...'.toDateTime(Date)se desborda con valoresDatefuera del rango deDateTime(posteriores a2106-02-07), por lo que la clave almacenada no es monótona; ClickHouse ya no utilizará la poda por clave primaria para esta combinación de clave y predicado, ya que hacerlo podría descartar gránulos que contienen filas coincidentes. #101814 (nihalzp). - Se corrigió el fallo de
ALTER MODIFY COLUMNal convertir una columnaNullablecon unDEFAULTa un tipo diferente (p. ej.,Nullable(UInt8)→String,LowCardinality(String)oArray(UInt8)). #102156 (il9ue). - Se corrigió el escapado incorrecto de literales SQL en
StorageSQLitey en la función de tablasqlite()al enviar predicadosWHEREa SQLite: las comillas simples y los caracteres de control (\n,\r,\t,\) se escapaban con barras invertidas, que SQLite no interpreta, lo que provocaba errores de sintaxis o resultados de consulta incorrectos. También se corrigió el escapado de los literales de cadena a los que se hace pushdown hacia PostgreSQL: las cadenas anidadas dentro de listasINconservaban el escapado de ClickHouse, y los caracteres de control se enviaban como secuencias con barra invertida que PostgreSQL interpreta como bytes distintos. #104217 (tiandiwonder). - Se corrige la excepción
NOT_FOUND_COLUMN_IN_BLOCKen consultasINNER JOIN ... ON arrayJoin(...) = ...cuandoquery_plan_convert_join_to_inestá habilitado y el SELECT hace referencia a la columna del array de origen. #104809 (tiandiwonder). - Se corrigen las expresiones IN y NOT IN cuyos operandos del lado derecho no son constantes y hacen referencia a columnas de la fila actual, y se alinea el tratamiento de tuplas en el lado derecho del nuevo analizador con la semántica actual de IN en ClickHouse. Con el analizador antiguo, una columna de origen aislada en el lado derecho (
x IN (arr)) se sigue resolviendo como nombre de tabla y queda fuera del ámbito. #104993 (niyue). - Se corrigió un problema por el que un
JOINcontra tablasEmbeddedRocksDB,RedisyKeeperMappodía devolver cero filas sin avisar al usarDirectKeyValueJoincon clavesStringoNullable(String). #105253 (vdimir). - Se corrige un
LOGICAL_ERROR(“Unexpected expression in JOIN ON section. Expected boolean (UInt8), got ‘Nothing’”) que se producía cuando un predicadoJOIN ... ONsin igualdad hacía referencia a una columna de tipoNothing, como la generada porARRAY JOIN []. #106981 (groeneai). - Se corrigió un error lógico
Inconsistent AST formattingque podía abortar el servidor en compilaciones de depuración y con sanitizadores al usar una lambda con alias como operando de un operador de acceso (elemento de tupla.No elemento de array[]) en cualquier posición salvo la primera de una lista de expresiones, p. ej.,SELECT 1, ((p0, p1) -> p0 AS a7).4[3] FROM t. #107092 (groeneai). - Una función de tabla de cluster (
urlCluster,fileCluster,s3Cluster, …) anidada dentro de otra consulta distribuida, comoclusterAllReplicas(..., urlCluster(...)), ahora se rechaza con un errorBAD_ARGUMENTSen lugar de fallar con un error lógico (Distributed task iterator is not initialized). #107107 (groeneai). - Se corrigió el fallo de la función de tabla
valuesconARGUMENT_OUT_OF_BOUNDal usar un literal decimal que no puede representarse exactamente en una columna de coma flotante de menor precisión (como0.1en una columnaFloat32), p. ej.,SELECT * FROM values('x Float32', 0.1). Ahora estos valores se aceptan y se convierten al valor representable más cercano, en coherencia conCASTeINSERT ... VALUES. #108055 (alexey-milovidov). - Se corrigió un problema por el que
mapFilter,mapSort(y sus variantes) ymapConcateliminabanLowCardinalityde los tipos de clave y valor de unMap. Anteriormente,mapFiltersobre una columnaMap(LowCardinality(String), String)devolvíaMap(String, String), lo que podía corromper los metadatos de una tabla creada medianteCREATE TABLE ... AS SELECTy hacer queCHECK TABLEfallara. #108057 (alexey-milovidov). - Se corrigió que un
INSERTcancelado o finalizado conKILLsiguiera ejecutándose durante mucho tiempo mientras construía un índice de omisión (por ejemplo, un índiceset(0)sin límite sobre una columna de alta cardinalidad). Ahora la construcción del índice se detiene de inmediato al cancelarse la consulta. #108351 (tiandiwonder). - Se corrigió que un
SELECTsobre la función de tablaprimesno respondiera a la cancelación: con unstep(olimit) grande, la consulta podía seguir ejecutándose durante mucho tiempo después deKILL QUERYo de agotarse el tiempo de espera. Ahora se detiene de inmediato. #108353 (tiandiwonder). - Se corrigió el análisis de nombres de tipos de datos que contienen la subcadena
INT(por ejemplo, un nombre similar a una función, comoquantileInterpolatedWeighted, usado en la posición de un tipo de datos). Estos nombres se confundían con tipos enteros de MySQL y su primer grupo de argumentos(...)se consumía silenciosamente como modificador de ancho de visualización, lo que podía romper el ciclo de ida y vuelta del formateo de la consulta. #108354 (groeneai). - Se corrigió una inconsistencia por la que un
ARRAY JOINmal formado seguido de una coma y una lista de tablas entre paréntesis se interpretaba erróneamente como una unión cruzada en lugar de rechazarse. #108365 (Algunenano). - Se corrigió una excepción
LOGICAL_ERROR(“Invalid action query tree node …”) que se producía cuando una consulta distribuida deduplicaba columnasALIASduplicadas y estructuralmente idénticas y, a la vez, hacía referencia a una función de tabla con un argumento de colección con nombrekey = value(por ejemplo,oss(s3_conn, filename = '...')). #108435 (groeneai). - Se corrigió un error lógico (una excepción en las builds de release y una interrupción del servidor en las builds de depuración y con sanitizadores) que podía producirse en una llamada a función con más de un argumento
LowCardinalitysobre una tabla distribuida, por ejemplo,concatAssumeInjective((SELECT toLowCardinality('p')), s)usado como clave deGROUP BYconremote(). Los mensajes eranDefault functions implementation for LowCardinality is supported only with a single LowCardinality argumentoExpected the argument ... to have N rows, but it has M. #108871 (groeneai). - Se corrigió que
use_client_time_zonese ignorara en los literales de cadenaDateTime/DateTime64interpretados en el servidor (INSERTasíncrono, literales enSELECT). Ahora el cliente propaga su zona horaria local comosession_timezonecuandouse_client_time_zoneestá habilitado, de modo que el análisis en el servidor coincide con el de la ruta síncrona deINSERT. #109051 (groeneai). - Se corrigió que
max_execution_time(contimeout_overflow_mode = 'throw') a veces no llegara a cancelar nunca una consulta: cuando el vigilante interno de tiempos de espera ya estaba esperando una consulta con un plazo posterior, una consulta registrada después con un plazo anterior podía pasarse por alto por completo, lo que le permitía ejecutarse mucho más allá de su límite de tiempo. #109792 (tiandiwonder). - Se corrigió el error
NOT_FOUND_COLUMN_IN_BLOCKque se producía cuando una consulta sobre una tablaDistributedusaba_shard_num(oshardNum()) convertido enNullable(por ejemplo, conFULL JOINyjoin_use_nulls = 1) junto conORDER BY, con el analizador habilitado. #109798 (groeneai). - Se corrigió el error
NOT_IMPLEMENTED(“Method getDataAt is not supported for Nullable(String)”) que podía producirse en una unión conenable_join_runtime_filters = 1(activado de forma predeterminada desde 26.2) cuando la clave de unión del lado de construcción eraLowCardinality(Nullable(...))con valores NULL y el filtro en tiempo de ejecución recurría a su filtro Bloom. #109824 (groeneai). - Se corrigió un fallo del servidor que se producía al pasar una expresión lambda donde una función de orden superior espera un valor concreto (por ejemplo, el acumulador de
arrayFold, como enarrayFold(lambda, arr, another_lambda)). Ahora, cuandoenable_analyzer = 0, estas consultas se rechazan conILLEGAL_TYPE_OF_ARGUMENTen lugar de provocar un fallo. #109840 (groeneai). - Se rechaza el alias
unnestdearrayJoinen los filtros de row policy, lo que cierra un resquicio por el que dicha política podía generar un error lógicocolumn->size() == num_rowsdurante la lectura. #109973 (Algunenano). - Se corrigió un problema por el que los índices de omisión definidos sobre subcolumnas de
Tupleno se utilizaban cuando se accedía al campo mediantetupleElement(t, 'name'),tupleElement(t, N)ot.Ny, a la vez, se leía la tupla completa en la misma consulta (p. ej.,SELECT *). Ahora todas estas formas descartan gránulos del mismo modo que el acceso a la subcolumna por nombret.name. #110056 (groeneai). - Se corrigió el error
BAD_GETal comparar una columnaArray(String)con un literal de array (arr = ['x']) cuando la columna tiene un índice de omisióntext,tokenbf_v1ongrambf_v1. Ahora el índice trata dicha comparación como un escaneo completo en lugar de hacer fallar toda la consulta. #110057 (groeneai). - Se corrigió un error espurio
ILLEGAL_COLUMNenALTER TABLE ... ADD COLUMN IF NOT EXISTScuando la columna ya existe en el momento de aplicar el cambio. Esto ocurría cuando la misma columna se añadía dos veces conIF NOT EXISTSen una sola sentencia, o cuando unALTERconcurrente añadía la columna entre las fases de preparación y aplicación. #110080 (groeneai). - Se corrigió un
LOGICAL_ERROR(Bad cast from type ColumnLowCardinality to ColumnString) que se producía cuandoidentity()(o el resultado de una subconsulta escalar) envuelve un valor que contiene unLowCardinalityanidado y la consulta usaWITH TOTALS/WITH ROLLUP. #110138 (groeneai). - Se corrigió un error
NOT_FOUND_COLUMN_IN_BLOCKal usarGROUP BY ALLsobre una expresión de tupla junto conORDER BY. #110206 (alexey-milovidov). - Se corrigió un error
NOT_FOUND_COLUMN_IN_BLOCKal ejecutarINSERTen una tabla con una restricciónCHECKque hace referencia a una subcolumna (comox.nullde una columnaNullableoarr.size0de unArray). #110208 (alexey-milovidov). - Se corrigieron resultados de consulta incorrectos de la optimización optimize_and_compare_chain (habilitada de forma predeterminada): una condición derivada por transitividad a partir de a < b AND b < c podía usar una semántica de comparación distinta de la de las condiciones originales cuando la cadena mezclaba tipos con reglas de conversión específicas de cada par (p. ej., Enum frente a String, Decimal frente a Float64 o FixedString de distintos anchos). Ahora las condiciones transitivas solo se derivan dentro de grupos de tipos que comparten un único orden de comparación. #110621 (yariks5s).
- Se corrigió que
optimize_injective_functions_in_group_byalterara los resultados de las consultas conGROUP BY GROUPING SETSyGROUP BY ... WITH TOTALS. La configuración está documentada como una que preserva los resultados, pero al eliminar una función inyectiva de una clave de agrupación se producía un valor incorrecto (o se descartaba una fila) en las filas en las que esa clave no forma parte del conjunto agregado (un conjunto deGROUPING SETSal que no pertenece) o en la fila deWITH TOTALS. El valor incorrecto podía coincidir con un valor de clave real, de modo que una fila de superagregación resultaba indistinguible de un grupo real dentro del mismo conjunto de resultados. #110721 (groeneai). - Se corrige un bloqueo del servidor al multiplicar un estado de función de agregación
median/quantile(basada en ReservoirSampler) por una constante entera enorme (p. ej.,medianState(x) * 18446744073709551615). La consulta dejaba de responder a la cancelación y podía ejecutarse indefinidamente. #110779 (groeneai). - Se corrige un fallo (desreferencia de puntero nulo durante el análisis de la consulta) al llamar a
getSubcolumnsobre un argumentoJSONcon un nombre interno de subcolumna de indicación de tipo, es decir, uno que empieza por un marcador de tipo con acento grave. #110940 (groeneai). - Se corrigió que
map[key]devolviera el valor de una clave duplicada posterior en lugar del de la primera. Cuando una columnaMapcontenía claves duplicadas, el resultado demap[key]podía depender de las filas anteriores del mismo bloque y de la configuraciónoptimize_functions_to_subcolumns, por lo que unSELECTy unWHEREsobre la misma fila podían dar resultados distintos. #111246 (groeneai). - Se corrige un error lógico
!rhs_literal->getValue().isNull()en el optimizador de expresiones lógicas cuando una cadenaANDcompara una columna con una constante de valor NULL de un tipo noNullable(por ejemplo, unVariantcon valor NULL) conuse_variant_default_implementation_for_comparisons = 0. #111292 (groeneai). - Se corrigieron resultados incorrectos cuando una consulta tiene un índice de omisión
sety un predicado de la forma(x AND <null-value>) OR y, donde el NULL lo genera una función (p. ej.,toInt64OrNull('x'),nullIf(1, 1),CAST(NULL AS Nullable(Int64))). Dicho valor se envolvía con__bitWrapperFuncy propagabaNULLen lugar de la máscara “desconocido”, por lo que el índice set podía descartar gránulos que sí coincidían y la consulta devolvía menos filas de las debidas. #111604 (groeneai). - Se corrige que
CREATE TABLE/ALTER TABLEcon el analizador aceptara una expresión de columnaDEFAULT/MATERIALIZEDque hiciera referencia a una columna virtual como_tableo_database. Las inserciones en dicha tabla fallaban conNOT_FOUND_COLUMN_IN_BLOCK, y una columnaMATERIALIZED(que no puede proporcionarse explícitamente) impedía de forma permanente insertar datos en la tabla. Ahora estas expresiones se rechazan en el momento de la definición, igual que ocurre sin el analizador. Las columnasALIAS(evaluadas en tiempo de lectura) y las columnasEPHEMERAL(entradas de inserción no almacenadas) basadas en columnas virtuales siguen funcionando. #111776 (groeneai). - Se corrigió el error
UNKNOWN_QUERY_PARAMETERal llamar a una vista parametrizada con un argumento cuyo valor es una subconsulta de tipoArray,TupleoLowCardinality, p. ej.,SELECT * FROM v(param = (SELECT groupArray(x) FROM t)). #111790 (groeneai). - Se corrigieron tres errores en las reescrituras del analizador que convierten una cadena de comparaciones en
IN/NOT IN(x = c1 OR x = c2 OR ...,x != c1 AND x != c2 AND ...yhas(const_array, x)). Para una expresiónVariantconuse_variant_default_implementation_for_comparisons = 0, la reescritura cambiaba el tipo de resultado de la expresión deUInt8aNullable(UInt8), lo que provocaba unLOGICAL_ERRORen la comprobación de validación del árbol de consulta en las compilaciones de depuración y con sanitizadores. Para una expresión con estructura dinámica (Dynamic,Array(Dynamic),JSON), la reescritura hacía que una consulta que antes funcionaba fallara conIllegal type ... of argument of function in, porqueINrechaza ese tipo de argumentos. Además, en ambos sentidos se devolvían resultados incorrectos cuando una constante no se convierte sin pérdida al tipo de la expresión, por ejemplo, una constanteDateTimecon hora del día comparada con una columnaDate. #111924 (groeneai). - Se corrige que
quantileDeterministic,quantilesDeterministicymedianDeterministicdevolvieran resultados distintos para los mismos datos en cada ejecución cuando la consulta usa réplicas paralelas, una tabla distribuida o agregación externa, o cuando los estados se almacenan en una tabla (incluso dentro de un valorDynamic). Los estados escritos antes de esta versión con la notación de tipo sin versión conservan el comportamiento anterior, ya que su estructura no puede cambiar. #112052 (alexey-milovidov). - Se corrigen resultados incorrectos causados por consultas de búsqueda vectorial que contaminaban la caché de condiciones de consulta. Una consulta
SELECT ... WHERE <condition> ORDER BY <distance function> LIMIT nsobre una tabla con un índicevector_similaritypodía registrar gránulos como no coincidentes con<condition>, de modo que una consultaSELECT ... WHERE <condition>ordinaria posterior sobre la misma tabla devolvía, sin avisar, menos filas. Las lecturas de búsqueda vectorial ya no escriben en la caché de condiciones de consulta. #112086 (groeneai). - Se corrige que
serialize_string_in_memory_with_zero_bytese omitiera del plan de consulta serializado. Conserialize_query_plan = 1, en un clúster con este ajuste deshabilitado, la representación en cadena en memoria podía diferir entre el iniciador y el nodo que ejecutaba el plan deserializado, porque el ajuste se leía al deserializar pero nunca se escribía al serializar y, por tanto, en el nodo de ejecución siempre tomaba su valor predeterminado. #112131 (groeneai). - Se corrigió un resultado incorrecto en un
JOINcuya expresiónONcontiene una conjunción constante, por ejemploON l.id = r.id AND CAST(NULL AS Nullable(UInt8)). La optimización del plan de consulta descartaba silenciosamente la constante, por lo que la unión se ejecutaba como si no existiera: las unionesINNER,LEFT SEMIyRIGHT SEMIdevolvían filas coincidentes cuando una condición que nunca es verdadera no debe devolver ninguna, yRIGHT ANTIno devolvía ninguna fila en lugar de devolverlas todas. #112155 (vdimir). - Se corrigen resultados incorrectos al llamar a una vista parametrizada con un argumento que no es una asignación
parameter = value. Conenable_analyzer = 0, y enEXPLAIN SYNTAXcon la configuración predeterminada, llamadas comopv(concat(name, '!')),pv(name, 'a'),pv(name != 'a')ypv(tuple(name = 'a'))vinculaban silenciosamente un parámetro de la vista a una expresión sin relación en lugar de devolverUNKNOWN_QUERY_PARAMETER, como hace el analizador. Ahora estas llamadas se rechazan de la misma forma en ambas rutas de ejecución. #112194 (groeneai). - Corrige un error por el cual se aceptaba un
CREATE VIEWoCREATE FUNCTIONcuya definición llama asubstr,midobyteSlicede una forma que la gramática desubstringno puede volver a analizar, aunque la metadata que ClickHouse escribe para ello no es SQL válido. Al leer esa definición posteriormente, se produce el errorSYNTAX_ERRORy, durante el inicio del servidor, se interrumpe la carga de metadata, por lo que el servidor no llega a iniciarse. Ahora estas definiciones se conservan correctamente en un ciclo de ida y vuelta, y los archivos de metadata existentes con la formasubstring(x, a, b, c)vuelven a ser legibles, de modo que un servidor afectado se inicia sin intervención manual. #112195 (groeneai). - Se corrigieron resultados incorrectos, una salida de
ORDER BYmal ordenada y una excepciónBAD_TYPE_OF_FIELDcuando la clave primaria es unArrayoTupley la consulta le aplicaplus,minus,multiply,divideointDiv. La aritmética sobre un valor compuesto se evalúa elemento a elemento, mientras que la comparación de valores compuestos es lexicográfica, por lo que el análisis de la clave primaria ya no considera monótona dicha expresión. #112339 (groeneai). - Se corrigió el error
Code: 62 ... You must not specify ANY or ALL for PASTE JOIN. (SYNTAX_ERROR)que generaba un servidor remoto ante una consulta conPASTE JOINenviada a otro servidor, por ejemplo, cuando la tabla izquierda es una tablaDistributedo una función de tabla*Cluster. El formateador generabaALL PASTE JOIN, una sintaxis que el analizador rechaza, por lo que el servidor receptor no podía analizar la consulta recibida. #112404 (groeneai). - Corrige que una lista de alias de columna como
(SELECT 1) AS t(x)oWITH t(x) AS (SELECT 1)no fuera visible dentro de la función de tablaview, donde una referencia at.xfallaba conUNKNOWN_IDENTIFIERpese a que la misma construcción funciona fuera deview. #112690 (groeneai). - Corrige un error lógico en el formateo de consultas cuando una cláusula
ARRAY JOINno contiene expresiones. Ahora dicha cláusula se rechaza durante el análisis conSYNTAX_ERROR, de forma coherente con unUSINGvacío, en lugar de aceptarse y formatearse como un texto que no puede volver a analizarse. #112699 (groeneai). - Se corrigió que
connectionIdlanzaraContext has expiredcuando las acciones de expresión preparadas para una subconsulta se ejecutaban después de haberse liberado su contexto de construcción. #112870 (clickgapai). - Corrige un error lógico y resultados incorrectos cuando una condición
JOIN ONque no es de igualdad y que se evalúa durante la unión contienearrayJoin. Las unioneshash,parallel_hashygrace_hashahora rechazan dicha condición conINVALID_JOIN_ON_EXPRESSION. Si la expansión depende de un solo lado, muévala a unARRAY JOINdentro de una subconsulta previa a la unión; si el argumento dearrayJoinlee columnas de ambos lados, será necesario reestructurar la condición. #112889 (groeneai). - Se corrigió que
geohashesInBoxdedicara un tiempo ilimitado a un recuadro de área cero, comogeohashesInBox(0., 0., 180., 0., 12). Dicha consulta devolvía el único geohash correcto, pero desperdiciaba aproximadamente 5e8 iteraciones de bucle vacías por fila e ignoraba tantomax_execution_timecomoKILL QUERY. #112976 (groeneai). - Se rechaza un cambio de
SETTINGSmarcado como escrito sin valor cuando contiene un valor distinto detrue, y ya nunca se omite el valor de dicho cambio al formatear una consulta. Anteriormente, una carga útil JSON de AST manipulada podía ejecutar un ajusteBoolconfalsemientrassystem.query_logyformatQueryFromJSONmostraban la forma sin valor. #113025 (alexey-milovidov). - Se corrigió el error
UNKNOWN_IDENTIFIERal seleccionar desde unaVIEWcuyos tipos de columna declarados difieren de los que produce su consulta interna, por ejemploSELECT sum(length(arr)) FROM v, dondevdeclaraarr Array(UInt8)sobre una columnaString. Con el valor predeterminadooptimize_functions_to_subcolumns = 1, el optimizador reescribíalength(arr)como una lectura de la subcolumnaarr.size0y propagaba ese nombre a la consulta interna, que no tiene dicha subcolumna. #113057 (groeneai). - Se corrigió la cancelación de las lecturas con la función de tabla
postgresqly el motor PostgreSQL. Cancelar mientras la lectura aún se estaba iniciando podía provocar una condición de carrera sobre el puntero de la transacción, y la cancelación podía perderse por completo, de modo que la consulta seguía ejecutándose hasta que PostgreSQL la terminaba. Una cancelación que llegue a PostgreSQL antes de que la sentenciaCOPYhaya empezado a ejecutarse todavía puede descartarse. #113150 (groeneai). - Se corrigió un
LOGICAL_ERROR(Next task callback is not set for query) que se producía cuando una vistaSQL SECURITY DEFINERoSQL SECURITY NONEsobre una función de tabla de cluster (s3Cluster,urlCluster,fileCluster) se leía como consulta secundaria, por ejemplo a través deremoteoclusterAllReplicas. Este anidamiento no compatible ahora se rechaza con un error de consulta normal, en lugar de abortar el servidor en builds de depuración y con sanitizador. #113371 (groeneai). - Se corrige un error lógico
IDENTIFIER is not a table expressionque se producía cuando una función de tabla de la familia remote con un argumentoview(...)se usaba en el lado izquierdo de unJOIN ... USINGcuya clave es un alias de la listaSELECT, conanalyzer_compatibility_join_using_top_level_identifier = 1. #113400 (groeneai). - Se corrigió el error
Not-ready Set is passed as the second argument for function 'in'cuando una consulta filtrasystem.databasespor la columnanamecon una subconsulta dentro deindexHint, por ejemploSELECT count() FROM system.databases WHERE indexHint(name IN (SELECT 'foo')). Dicha consulta se rechazaba con unLOGICAL_ERRORen builds de release y abortaba el servidor en builds de depuración y con sanitizador. #113556 (groeneai). - Se corrigió que una consulta sobre una columna
Variantignoraramax_execution_timeyKILL QUERY. Al llamar a una función con varios argumentosVariant, la función se resolvía una vez por cada alternativa de cada argumento, y ninguno de los dos bucles que realizaban ese trabajo comprobaba la cancelación, por lo que la consulta no podía detenerse hasta que terminaba. #113612 (groeneai). - Se corrige que
ALTER TABLE ... MODIFY COLUMNfallara conCannot specify codec for column type ALIAScuando una misma sentencia convierte una columnaALIASen física (DEFAULToMATERIALIZED) y además especifica unCODEC. #113853 (groeneai). - Se corrigió un fallo del servidor al realizar una unión con una expresión
ONconstante sobre un lado derecho que contiene unARRAY JOIN. La lectura de una columna del lado derecho replicada de forma diferida usaba unColumnReplicatedya liberado. #113901 (groeneai). - Corrige una fuga de memoria con
optimize_aggregation_in_order = 1cuando la clave de ordenación de la tabla es un prefijo estricto de la clave deGROUP BYy se utiliza una función de agregación cuyo estado reserva memoria en el heap, comoquantileDD. La memoria del servidor crecía con cada consulta de este tipo hasta que se reiniciaba. #114010 (groeneai). - Se corrigió que
isProbablePrimesobreUInt128/UInt256ignoraramax_execution_timeyKILL QUERY. Un bloque de valores anchos se procesaba por completo dentro de una única llamada a la función, sin ningún punto de cancelación, por lo que una consulta podía seguir ejecutándose durante minutos después de agotar su tiempo límite. #114032 (groeneai). - Se corrigió el error
Code: 46. DB::Exception: Unknown function exists. (UNKNOWN_FUNCTION)que se producía cuando una cláusulaPREWHEREcontenía un predicadoIN (subquery)y se había establecidorewrite_in_to_join = 1(omake_distributed_plan = 1, que lo habilita de forma forzosa). La misma consulta escrita conWHEREfuncionaba correctamente. #114067 (RohithPariki). - Se corrigió un
LOGICAL_ERRORenarrayAutocorrelationcuando el argumento es un array no vacío cuyo tipo de elemento esNothing, por ejemplo,SELECT arrayAutocorrelation([arrayMax([])]). Ahora dicho argumento se rechaza conILLEGAL_COLUMN. El literal de array vacío[]sigue devolviendo[]. #114249 (groeneai). CREATE TABLEyALTER TABLEahora rechazan códecs con pérdida, comoSZ3, en columnas utilizadas en la clave de ordenación. #114531 (groeneai).- Se corrigió un bucle infinito y no cancelable en las funciones
hopywindowIDcuando la duración de un argumento de intervalo en segundos es múltiplo de 2^32 (por ejemplo,toIntervalDay(2147483648)): la resta desbordada eludía la comprobación de desbordamiento temporal y, con argumentos constantes, el bucle se ejecutaba durante el análisis, donde ni siquiera era posible terminar la consulta. El mismo intervalo también podía dejar un hilo en segundo plano de unaWINDOW VIEWgirando indefinidamente; ahora una window view de este tipo se rechaza al crearla. #114607 (alexey-milovidov). - Corrige el error lógico
Not-ready Set is passed as the second argument for function 'in'en consultas con una subconsultaINque lee de un clúster remoto: ahora la consulta falla con el error real de la subconsulta, como un fallo de conexión. #114983 (alexey-milovidov). - Se corrigió un
INSERTen una tablaLog,TinyLogoStripeLogque fallaba al confirmar los tamaños de archivo registrados. Dicha inserción podía conservar sus filas en la tabla aunque informara de un error, o dejar los archivos de datos de una columna de tipo array inconsistentes entre sí. Al leer una tablaLogoTinyLogcuya columna de tipo array no contiene elementos pero cuyos offsets indican que sí los hay, ahora se genera un error que indica el nombre de la columna, en lugar de leer más allá del final de los elementos. Las columnas de elementos escritas parcialmente ya se rechazaban. #115027 (groeneai). - Corrige
TYPE_MISMATCH(“CAST AS Array can only be performed between same-dimensional array types”) en consultas con una constante de tipoArray(Map(...)), comohas([map('k', 'v')], m), ejecutadas sobre una tablaDistributedo con réplicas paralelas. #115883 (alexey-milovidov). - Se corrigieron resultados incorrectos al realizar una unión con una vista o
view()cuya columna proyectada tiene el mismo nombre que una columna de una de sus propias relaciones internas, por ejemploSELECT expr(x.c0) AS c0 FROM a AS x, b AS y. El optimizador del orden de join fusionaba dicha expresión en el grafo de uniones aplanado y después la aplicaba dos veces, por lo que la consulta devolvía valores sesgados sin ningún aviso. Si la expresión además cambiaba el tipo de la columna, la misma causa producía en su lugar el errorAMBIGUOUS_COLUMN_NAMEdurante la planificación. #116152 (groeneai). - Se corrigió una excepción en subconsultas correlacionadas cuando las columnas externas pasan a ser
Nullablecongroup_by_use_nullsy ROLLUP/CUBE. #100365 (alexey-milovidov). - Ahora se rechaza
max_replication_lag_to_enqueue = 0en bases de datosReplicated. Este valor hacía que la comprobación de falta de sincronización posterior a la recuperación fuera trivialmente verdadera y provocaba que el servidor abortara conLOGICAL_ERRORen compilaciones de depuración y con sanitizador. Ahora0se rechaza durante el análisis conBAD_ARGUMENTS, independientemente del origen (CREATE DATABASE ... SETTINGS, el bloque<database_replicated>de la configuración del servidor, la reproducción deATTACHy la reproducción de los metadatos existentes durante una actualización). El valor mínimo válido es1. #106006 (groeneai). - Se prohíbe crear índices de omisión minmax en columnas JSON (Object) para evitar la excepción NO_COMMON_TYPE al insertar arrays de tipos mixtos. En su lugar, utilice subcolumnas tipadas (p. ej.,
INDEX idx json.field TYPE minmax). #106094 (linhaojie). - Se corrigió que
JSON_QUERY/JSON_VALUE/JSON_EXISTSdevolvieran Dynamic en lugar de String/UInt8 al recibir argumentos Dynamic. #106877 (Avogar). - Se corrigió un desbordamiento de entero con signo cuando una configuración de tiempo de espera, como
interactive_delay, se establecía en un valor muy grande: la espera podía agotarse de inmediato en lugar de esperar, y el servidor podía abortar con el Undefined Behavior Sanitizer. #106961 (groeneai). - Se corrigió un
LOGICAL_ERROR(“Unsupported argument types”) en la funcióngeohashesInBoxcuando sus argumentos de coordenadas combinaban valores constantes y no constantes, o cuando una coordenada era de tipoBFloat16. Ahora funcionan los argumentosFloat32que combinan valores constantes y no constantes, y los argumentosBFloat16se rechazan con un mensaje de error claro. #107063 (groeneai). - Se corrigió que el encabezado de
CSVWithNamesyCSVWithNamesAndTypestuviera menos columnas que los datos cuandooutput_format_csv_serialize_tuple_into_separate_columnsestá habilitado (valor predeterminado). Ahora el encabezado (y la fila de tipos) descompone las columnasTupleen sus campos hoja con nombres separados por puntos (p. ej.,t.a,t.b), de modo que el número de columnas del encabezado coincide con el de los datos. Una nueva configuración,output_format_csv_header_serialize_tuple_into_separate_columns(predeterminado1), controla este comportamiento y puede establecerse en0para recuperar el encabezado anterior con un único nombre. #107371 (groeneai). - Se corrigió una fuga de memoria en el
mongo-c-driverintegrado que podía producirse al leer desde MongoDB (por ejemplo, mediante un diccionario de MongoDB o la función de tablamongodb) cuando a un error de lectura reintentable le seguía un fallo en la selección del servidor para el reintento. #107448 (groeneai). - Se corrige un error lógico (
WhichDataType(const_type).isArray()) y la terminación abrupta del servidor durante el análisis de la clave primaria cuando se llama apointInPolygoncon un argumento de polígono constante de un tipo contenedor comoVariantoDynamic(por ejemplo,pointInPolygon((x, y), if(c, [(0, 0), ...], NULL))). #107589 (groeneai). - Se corrigieron errores lógicos (
Bad cast) causados por la eliminación inconsistente deLowCardinalityanidado dentro de columnasVariantyDynamic, por ejemplo, enconcat,formaty en el análisis de la clave primaria. #107773 (Avogar). - Se corrigió el análisis de los parámetros de comando de las funciones definidas por el usuario de tipo executable, de modo que ya no se aceptan como parámetros los marcadores de posición con nombres vacíos o no válidos. #107983 (goutamadwant).
- Se corrige
accurateCastOrNullde unTuplecuyo elemento esDynamic/Variant: unNULLreal en el origen se trataba como un fallo de conversión. Si el elemento de destino esNullable, unNULLen el origen ahora se mantiene comoNULLen el elemento (igual que con un origenTuple(Nullable(...))simple); si el elemento de destino no esNullable, unNULLen el origen ahora convierte en nula toda la tupla (igual que en la referencia sinDynamic), en lugar de generar el valor predeterminado del elemento. Los fallos de análisis o de desbordamiento siguen convirtiendo en nula toda la tupla. #108023 (groeneai). - La función de tabla
mongodbahora aceptaoid_columnscomo argumento con nombre (p. ej.,oid_columns='_id'), en lugar de rechazarlo conBAD_ARGUMENTS. #108039 (alexey-milovidov). - Ahora es posible consultar un diccionario
range_hashedocomplex_key_range_hashedque utilice un rangoDateTime64,Decimalo de coma flotante pasando adictGet/dictHasun argumento del tipo correspondiente. Anteriormente, estas consultas fallaban conmust be convertible to Int64, y los intervalos abiertos de rangosDecimal/DateTime64devolvían incorrectamente el valor predeterminado. #108052 (alexey-milovidov). - Se corrige una terminación abrupta del servidor (
Logical errorenIColumn::insertFrom) al convertir unArray(Dynamic)oArray(Variant)aQBitconaccurateCastOrNull, p. ej.,accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)'). #108288 (groeneai). - Se corrigió un fallo del servidor (
Received signal 4, instrucción ilegal) que podía provocarse mediante un flujo del protocolo TCP nativo malformado o desincronizado. Ahora se valida que el campoinitial_addressdeClientInfosea unhost:portnumérico antes de analizarlo, en lugar de permitir que un puerto no numérico llegue a la función de libcgetservbyname, que está bloqueada mediante una trampa. #108410 (groeneai). - Se corrigió la asignación excesiva de memoria al deserializar estados de funciones de agregación manipulados para
mannWhitneyUTest,rankCorr,largestTriangleThreeBuckets,quantileGK,sequenceMatch/sequenceCountygroupArrayIntersect. Un estado malformado podía declarar un número enorme de elementos y hacer que el servidor intentara asignar decenas de gigabytes a partir de unos pocos bytes de entrada; ahora estos estados se rechazan conTOO_LARGE_ARRAY_SIZE. #108465 (groeneai). - Se corrigió un error lógico (
Bad cast from type DB::ColumnNullable to DB::ColumnString) y posibles resultados incorrectos al usargroup_by_use_nullscon una clave de agrupación constanteLowCardinalityenGROUPING SETS/ROLLUP/CUBE. #108771 (alexey-milovidov). - Se corrigió
TYPE_MISMATCHenmapFilter,mapSort,mapReverseSort,mapPartialSortymapConcatcuando un valorMapcontiene unMapanidado conLowCardinality, p. ej.,mapFilter((k, v) -> 1, map('a'::LowCardinality(String), map('x'::LowCardinality(String), 'y'))). #108798 (groeneai). - Se corrigió un
LOGICAL_ERROR(“Inconsistent AST formatting”) que provocaba la terminación abrupta del servidor en builds de depuración y con sanitizador al formatear un tipo de datosTupleque combina elementos con nombre y sin nombre (por ejemplo,Tuple(a UInt8, UInt16)). #108915 (groeneai). JSONExtractahora respetacast_string_to_date_time_modeal convertir valores JSON de tipo cadena aDateTime/DateTime64, de forma coherente conCAST. #109252 (Utkal059).- Se corrigió un problema por el que
INcon una columna de array simple como argumento derecho devolvía silenciosamente un resultado incorrecto (siempre falso) o lanzaba una excepción; ahorax IN arrse comporta comohas(arr, x). #109416 (alexey-milovidov). - Se corrigió un
LOGICAL_ERRORenarrayFoldsobre un argumentoArray(LowCardinality(T))no constante (por ejemplo,arrayFold((acc, x) -> acc + x, materialize([1, 2, 3]::Array(LowCardinality(Int64))), toInt64(0))), que fallaba con “Arguments of ‘plus’ have incorrect data types” (lo que provocaba la terminación abrupta del servidor en builds de depuración y con sanitizador). #109462 (groeneai). - Se corrigió una excepción
ILLEGAL_COLUMNenconval convertir correctamente los argumentosFixedStringaString. #109771 (hp77-creator). - Se corrigieron resultados incorrectos en lecturas de funciones de tabla con
FINAL/SAMPLEconserialize_query_plan = 1, así como la clave de caché de estadísticas de la tabla hash de agregación para funciones de tabla (antes, todas las funciones de tabla compartían una única entrada de preasignación). #109847 (azat). - Se corrigió el análisis de los valores numéricos
1/0como valoresBooldentro de tipos contenedores (p. ej.,Array(Bool),Tuple(Bool, ...)). Antes,[1,0]fallaba conCANNOT_READ_ARRAY_FROM_TEXT, mientras que[true,false]funcionaba. #109976 (groeneai). - Se corrigió el error
NOT_IMPLEMENTED(Method getDataAt is not supported for Nullable(String) in case if value is NULL) que se producía al construir un índicetextsobreArray(LowCardinality(Nullable(String)))(incluidos los camposNestedalmacenados de esa forma) cuando un array indexado contenía un elementoNULL. Ahora los elementosNULLdel array se omiten durante la construcción del índice, igual que conArray(Nullable(String)). #110055 (groeneai). - Se corrigieron resultados incorrectos de
subBitmap,bitmapSubsetInRangeybitmapSubsetLimiten bitmaps que aún se encontraban en la representación pequeña, incluidos valores de elementosUInt64eInt64superiores a2^32, que se truncaban a 32 bits. Las comparaciones en las funciones de bitmap sobre tipos de elemento con signo ahora usan de forma coherente el valor sin signo del tipo de elemento, de modo que en un bitmapInt8el elemento-1se compara como255y no como el valor con extensión de signo4294967295; esto también corrigebitmapMin,bitmapMax,bitmapContainsybitmapTransformen bitmaps que ya han superado la representación pequeña. Las consultas que pasaban umbrales con extensión de signo deben ajustarse: sobre un bitmapInt8,bitmapSubsetInRange(bm, 4294967168, 4294967296)pasa a serbitmapSubsetInRange(bm, 128, 256). También se corrigió quegroupNumericIndexedVectordevolviera resultados distintos para columnas del índiceInt8eInt16que para tipos de índice más anchos, así como quenumericIndexedVectorGetValuedevolviera0para índices negativos. Se corrigió la documentación de las funciones de bitmap, incluidas las funciones de subconjunto, que se describían como basadas en indexación desde 1, y la compatibilidad debitmapBuild/bitmapToArraycon valores con signo. #110072 (RamiDarwiche). - Se corrigieron rutas con desbordamiento con signo de comportamiento no definido en la aritmética de intervalos para
WITH FILL STEPde tipo intervalo y para las funciones de intervalo de fecha/horaadd*/subtract*con deltas extremos, de modo que los valores de intervalo extremos ahora son deterministas en lugar de depender del desbordamiento con signo. También se corrigió un bloqueo deWITH FILLde tipo intervalo con un pasoYEARenorme, que hacía retroceder el calendario. #110158 (groeneai). - Se corrigió un aumento cuadrático del tiempo de ejecución (y la falta de respuesta a
max_execution_time) en la agregación en orden al agrupar por varias claves cuyo orden de clasificación es solo un prefijo de las grouping keys. #110159 (alexey-milovidov). - Se corrigieron comparaciones que antes lanzaban
ILLEGAL_TYPE_OF_ARGUMENTcuando los operandos no tienen un supertipo común mínimo. Los arrays comoArray(Int64)frente aArray(UInt64)yArray(Int256)frente aArray(UInt256)ahora pueden compararse lexicográficamente con=,!=,<,<=,>,>=,IS DISTINCT FROMeIS NOT DISTINCT FROM. Las comparaciones seguras frente a NULL, comoisDistinctFrom/isNotDistinctFrom, ahora también comparan por valor los pares numéricos o decimales compatibles que no son arrays, en lugar de lanzar una excepción. Las comparaciones de igualdad también funcionan con arrays cuyos elementos sonTuple(Nullable(...))anidados. #110245 (diegomestre2). - Se corrigió un desbordamiento de entero con signo (UBSan) al convertir un valor
DateTime64extremo (p. ej.,INT64_MIN) aTime/Time64en una zona horaria con desfase negativo. #110451 (groeneai). - La conversión de valores de coma flotante fuera de rango (
BFloat16,Float32,Float64) y de valoresUInt64superiores aInt64::max()aDateTimeyTimeahora se satura de forma fiable en los límites del rango en todas las arquitecturas (anteriormente, el resultado de una conversión fuera de rango dependía de la arquitectura y podía dar la vuelta en x86-64), y los valores no finitos (NaN,inf) ahora lanzan una excepción en lugar de producir un resultado arbitrario. La misma corrección se aplica a la ruta de conversión de coma flotante aDatedetoDatey a las conversiones deUInt64y de enteros anchos ((U)Int128,(U)Int256) aDateyDate32, que podían devolver un día anterior a la época en lugar de saturarse. La conversión de un número aTimeahora se satura al rango del tipo para todos los tipos numéricos de origen (anteriormente, los valores procedentes de enteros sin signo estrechos o de enteros anchos se almacenaban sin acotar y solo se acotaban al imprimirse), y la conversión precisa aTimeya no rechaza los valores negativos queTimeadmite, ni satura silenciosamente los valores que no caben en él. La conversión precisa de un número aDate32(accurateCast,accurateCastOrNull) ya no satura silenciosamente un valor fuera de rango o no finito, sino que lanza una excepción o devuelveNULL, como ya ocurría conDateyDateTime, y las variantesOrDefaultdevuelven el valor predeterminado deDate32para dicha entrada. La conversión precisa de un número de coma flotante no entero aDate,Date32,DateTimeoTimeahora se rechaza en lugar de truncarse silenciosamente. También se corrigió la documentación de la funcióntoDateTime32, que mostraba por error ejemplos detoDateTime64y describía el rango de valores deDateTime64. #110459 (alexey-milovidov). - Se corrige el fallo de la inferencia de esquema con
Map cannot have a key of type LowCardinality(Nullable(String))al leer archivos ORC cuyas claves de mapa están codificadas mediante diccionario, incluidos los archivos ORC escritos por Spark y los escritos por el propio ClickHouse conoutput_format_orc_dictionary_key_size_thresholdhabilitado. #110492 (tiandiwonder). - Se corrige un error lógico (
Function node with name '...' is not resolved as ordinary function) que podía producirse conoptimize_or_like_chainhabilitado cuando una función de agregación o de ventana aparecía en el lado izquierdo de unLIKE/ILIKE/matchdentro de una cadenaOR. #110641 (groeneai). - Se corrigió un desbordamiento de entero con signo en
toStartOfIntervalcon un número extremo de intervalosMONTH,WEEKoDAYsobre valoresDate/Date32/DateTime64. #110688 (groeneai). - Se corrigió que
readWKTyreadWKTPointdevolvieran coordenadas sin inicializar (escalar) u obsoletas de la fila anterior (vectorizado) paraPOINT EMPTY.POINT EMPTYahora se rechaza conCANNOT_PARSE_TEXT, ya que unPointde ClickHouse es unTuple(Float64, Float64)fijo sin representación vacía. #110692 (groeneai). - Se corrigió que
flipCoordinatesperdiera el tipoGeometry: para un argumentoGeometry, el resultado vuelve a ser de tipoGeometryen lugar delVariant(...)subyacente, por lo que puede pasarse directamente a funciones comoareaCartesian. #110694 (groeneai). - Se corrigió la serialización WKB no canónica de un polígono vacío:
wkb(POLYGON EMPTY)ahora emitenumRings = 0en lugar de un anillo espurio de cero puntos, de modo que una conversión de ida y vuelta WKB de un polígono vacío estándar preserva la identidad. #110796 (groeneai). - El análisis de los valores numéricos
1/0enBoolde JSON ahora respeta el ajusteallow_special_bool_values. Antes, una entrada JSON como{"v":1}paraVariant(Bool, UInt32)se leía comoBoolincluso conallow_special_bool_values_inside_variant = 0, porque los analizadores deBoolde JSON ignoraban el ajuste yBooltiene mayor prioridad de deserialización enVariantque los tipos enteros. #110835 (groeneai). - Se corrigió que
throwIf(notLike(col, pattern))(y cualquier otrothrowIfaplicado sobre una función) lanzara una excepción de forma incondicional cuandocolesLowCardinality. La implementación predeterminada deLowCardinalityejecutabathrowIfsobre todo el diccionario, que siempre contiene el valor predeterminado reservado aunque ninguna fila haga referencia a él, de modo que un valor distinto de cero en esa posición sin usar provocaba quethrowIflanzara una excepción con datos que no cumplen la condición. #110864 (groeneai). - Se corrigió un fallo que se producía cuando una función de agregación con el combinador
-Tuplese usaba conRESPECT NULLSy generaba un estado intermedio (-State, agregación distribuida,WITH ROLLUP/WITH CUBE). La función combinada tomaba el nombre de una variante de estado incorrecta, por lo que, al serializarse y deserializarse, su tipoAggregateFunctionse volvía a resolver a una disposición en memoria incompatible. #110930 (groeneai). - Se corrigió el error
Nested type LineString cannot be inside Nullable type (ILLEGAL_TYPE_OF_ARGUMENT)al leer una columna espacial de MySQL que admite NULL (LINESTRING,POLYGON,MULTILINESTRING,MULTIPOLYGON,MULTIPOINTo el genéricoGEOMETRY) mediante la función de tablamysqlo los motores de tabla/base de datosMySQL. Ahora estas columnas se leen comoNullable(String), con el valor tal como lo devuelve MySQL (un prefijo SRID de 4 bytes seguido de la carga útil WKB).POINTsigue asignándose aNullable(Point). #110943 (groeneai). - Se corrigió la serialización
Nativede los contenedoresSimpleAggregateFunctionque incluyen estados de agregación versionados cuando se comunican con pares de versiones anteriores. #110997 (groeneai). - Se corrigió el error
CANNOT_CONVERT_TYPEcon constantes de tipoVariant(incluidoGeometry) en consultas distribuidas y en consultas con réplicas paralelas. #111136 (fm4v). - Se corrigió un
LOGICAL_ERROR(“Lambda resolved type … is not equal to type from actions DAG …”) que se producía cuando el cuerpo de la lambda de una función de orden superior es unif/multiIfcon condición constante que combina una rama con un literalBooly una rama de comparaciónUInt8, p. ej.,arrayFilter(p -> multiIf(false, true, p = 'ALL'), ['ALL']). #111245 (groeneai). - Se corrigió un desbordamiento de entero con signo en
toStartOfIntervalcon intervalos inferiores a un segundo: para valoresDateTime64situados a menos de un intervalo del límite inferior deInt64, el resultado redondeado se desbordaba silenciosamente y daba un valor positivo sin sentido; ahora la función lanza una excepciónDECIMAL_OVERFLOW. #111370 (alexey-milovidov). - Se corrigió una excepción (
CANNOT_CONVERT_TYPEo un error lógico) en consultas distribuidas que usan el combinador-Tuplecon un modificadorRESPECT NULLS/IGNORE NULLSdentro de combinadores anidados, p. ej.,anyRespectNullsStateTuple(...) IGNORE NULLS. #111570 (alexey-milovidov). - Corrige un intento de análisis de texto de
FixedStringque dejaba bytes añadidos parcialmente en la columna cuando fallaba el análisis, lo que podía provocar un error lógicoSizes of nested column and null map of Nullable column are not equaldurante la serialización de columnasVariant/Array/Nullable, o bien bytes desplazados en el resultado sin ningún aviso. #111908 (groeneai). - Corrige una excepción y la omisión silenciosa de datos al leer una subcolumna dinámica (una ruta dentro de una columna
JSONoDynamic) a través de una tablaBuffer. #111948 (alexey-milovidov). - Se corrigió la complejidad cuadrática de
countSubstringsCaseInsensitiveUTF8, que hacía que la función tardara minutos en procesar un texto de unos pocos megabytes con muchas coincidencias. Ahora el desplazamiento en caracteres de cada coincidencia se calcula de forma incremental en lugar de volver a contarse desde el inicio de la fila. #112003 (groeneai). - Se corrigió un desbordamiento de entero con signo en la sobrecarga de tres argumentos de
toStartOfInterval: con un argumentoorigincercano al límite inferior deInt64, la función devolvía un valor desbordado en lugar de notificar un error. #112045 (alexey-milovidov). - Se prohíben los estados de agregación en los parámetros de funciones de tabla, ya que no son compatibles en absoluto. #112087 (PedroTadim).
- Se corrigió que la función de tabla
valuesrepresentara como1/0, en lugar detrue/false, una constanteBoolno literal (p. ej.,CAST(true, 'Nullable(Bool)')) insertada en una columnaString/textual. #112308 (yakov-olkhovskiy). - Corrige un error lógico (que provoca la interrupción en compilaciones de depuración y con sanitizador) al aplicar
finalizeAggregationa una columna cuyos estados de agregación provienen de funciones distintas que comparten la representación del estado, pero cuyo resultado final es de tipos diferentes; por ejemplo,quantileStateyquantilesState(0.9)combinados mediante unUNIONo generados conarrayReduce. Ahora estas consultas generan un error normal en lugar de provocar un fallo. #112662 (zainulabidin302). - Se corrigió el análisis de enteros que no caben en el tipo de destino en
Poco::NumberParser, que se utiliza para leer números JSON. Estos números se analizaban silenciosamente con un valor incorrecto (por ejemplo,18446744073709551617se convertía en1) en lugar de rechazarse, y un númeroUInt64superior al máximo deInt64no se conservaba tras convertir el AST a JSON y viceversa. #112904 (alexey-milovidov). - Se corrigió que una constante
Boolen el lado derecho deINse convirtiera a'1'/'0'frente a un lado izquierdo de tipoString, en lugar de a los valores canónicos'true'/'false'(ahora es coherente conCASTy con la función de tablavalues). #113051 (yakov-olkhovskiy). - Corrige el formato inconsistente del AST de
viewIfPermitted: afectaba a las funciones que normalmente se escriben como operador (p. ej.,not) en la ramaELSEde la forma de función de tabla, y a la forma de expresiónviewIfPermitted(...), que se formateaba incorrectamente conELSE. #113652 (alexey-milovidov). - Se corrigen el comportamiento no definido y los resultados incorrectos de
avgsobreDate/DateTime/DateTime64/Time/Time64: ahora el promedio se calcula de forma exacta en el espacio de enteros, lo que corrige tanto el desbordamiento en el límite deInt64(UB, resultado incorrecto en x86) como la pérdida de precisión deFloat64por encima de 2^53 (visible a escala de nanosegundos). #113912 (alexey-milovidov). - Se corrige una fuga de memoria en el códec de compresión experimental
SZ3: cuando la compresión de datos poco comprimibles o corruptos fallaba con una excepción, los búferes temporales de trabajo no se liberaban. #113916 (alexey-milovidov). - Se corrige que
hasAny,hasAll,has,indexOf,mapContainsKey,mapContainsValueymapContainsdevolvieran menos filas de las esperadas, o fallaran conTOO_LARGE_STRING_SIZE, al consultar un índicebloom_filtercon una constanteFixedString. El índice calculaba el hash de la forma rellenada de la constante, mientras que la función compara la forma sin relleno, por lo que se omitía un gránulo coincidente. #114089 (alexey-milovidov). - Se corrige que
minymaxsobre columnasDateTime64devolvieran resultados incorrectos cuando la agregación se compila con JIT y los datos contienen marcas de tiempo anteriores a 1970.is_signedno estaba especializado paraDateTime64yTime64, que derivan deDecimal64, por lo que el código generado comparaba los recuentos de ticks como enteros sin signo, y una marca de tiempo anterior a 1970 ganaba enmaxy perdía enmin. #114168 (groeneai). - Se corrige que
arrayExists(x -> x = needle, arr)devolviera un resultado incorrecto, o fallara conTOO_LARGE_STRING_SIZE, cuando el elemento del array y el needle son de tipos de cadena distintos (por ejemplo, un needleStringfrente a un elementoArray(FixedString(N))). La optimizaciónoptimize_rewrite_array_exists_to_has, habilitada de forma predeterminada, reescribía dicha llamada comohas, que, a diferencia de=, no compara con relleno de ceros. #114496 (groeneai). - Se corrige la evaluación del índice de texto del operador
LIKE/ILIKEaplicado sobre contenedores Map o JSON. #114544 (ahmadov). - Se corrigieron el comportamiento no definido y los resultados incorrectos en los límites de
quantileyquantilespara valoresDateTime64yDecimalanchos. #114919 (alexey-milovidov). - Se corrigió que
ifymultiIfdevolvieran un valor positivo grande en lugar de uno negativo cuando una ramaTimese combina conTime64,DateTimeoDateTime64y la expresión se compila con JIT. #115146 (groeneai). - Se corrigió que
timezoneOffset(aliastimeZoneOffset) devolviera un desplazamiento erróneo en exactamente un día para zonas horarias cuyo desplazamiento respecto a UTC difiere en un día completo del que tenían el 1970-01-01, comoPacific/KiritimatiyPacific/Apiatras cruzar la línea internacional de cambio de fecha, y para la mayoría de las zonas antes de 1970. Esto también corrigeparseDateTime,parseDateTimeOrNull,parseDateTime64,parseDateTimeInJodaSyntax,EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE ...), el%zdeformatDateTime,toUTCTimestampyfromUTCTimestamp, que utilizan dicho desplazamiento. #115332 (groeneai). - Se corrigió el error
Code: 349. Cannot convert NULL value to non-Nullable typeque se producía cuando un predicadohasonotHascontenía un elemento de array NULL y la clave primaria eraString,Array(String)oMap(String, String). También se corrigieron los resultados incorrectos que se obtenían cuando ese elemento era unDynamicoVariantque contenía NULL. Ahora el NULL se descarta del conjunto durante el análisis de claves, como ya ocurría con otros tipos de clave. #115647 (groeneai). - Se corrigió un problema por el que
cast_keep_nullableno conservaba la nulabilidad cuando el tipo de destino eraLowCardinality. Al convertir un valor que admite NULL aLowCardinality(T), se lanzabaCANNOT_INSERT_NULL_IN_ORDINARY_COLUMNen lugar de obtenerseLowCardinality(Nullable(T)). #115851 (groeneai).
Correcciones de índices y de la caché de consultas
- Se corrige la lectura de subcolumnas de una columna que tiene una expresión
DEFAULTy no está materializada en una parte (p. ej., después deALTER TABLE ADD COLUMNo duranteALTER TABLE MATERIALIZE COLUMN): la subcolumna se rellenaba con los valores predeterminados del tipo en lugar de con el resultado de evaluar la expresiónDEFAULT, y las funciones de distancia vectorial transpuestas (cosineDistanceTransposedy otras) sobre dichas columnasQBitfallaban con el errorSIZES_OF_ARRAYS_DONT_MATCH. #110636 (alexey-milovidov). - Se corrige la excepción
Not-ready Set is passed as the second argument, que podía producirse cuando la construcción del conjunto de una subconsultaINdurante el análisis de la clave primaria fallaba de forma silenciosa (por ejemplo, por un tiempo de espera agotado de la subconsulta conoverflow_mode = 'break'), lo que dejaba el conjunto sin construir de forma permanente para la canalización de la consulta. #107924 (alexey-milovidov). - Se corrige un
SELECTque fallaba conNOT_FOUND_COLUMN_IN_BLOCKen una tabla con un índice de omisión de datossetcuando una política de filas la filtraba mediante una condición siempre verdadera combinada con una comprobación sobre una columna no indexada. #107971 (tiandiwonder). getClientHTTPHeaderahora se trata correctamente como no determinista, por lo que la caché de resultados de consultas ya no reutiliza su resultado de forma indebida. #108029 (alexey-milovidov).- Se corrigen resultados erróneos que se producían cuando la caché de condiciones de consulta (
use_query_condition_cache = 1) reutilizaba una exclusión de marcas derivada de índices de omisión para una consulta que ejecutaba un conjunto distinto de índices de omisión, por ejemplo conuse_skip_indexes = 0,ignore_data_skipping_indiceso un modo distinto deuse_skip_indexes_for_disjunctions. Ahora, las entradas de caché derivadas de índices de omisión usan como clave el conjunto efectivo de índices de omisión ejecutados, mientras que las entradas a nivel de fila de la caché de condiciones de consulta siguen pudiendo reutilizarse en todos estos casos. #108548 (groeneai). - Se corrige un bloqueo por el que una consulta que leía a través de la caché del sistema de archivos podía seguir esperando una descarga en curso tras cancelarse con
KILL QUERY, y por el que eliminar una vista materializada actualizable, o aplicarleSYSTEM STOP VIEW, se quedaba bloqueado si su actualización estaba atascada en dicha espera. #109116 (murphy-4o). - Se corrigen resultados de consulta erróneos causados por el índice de clave primaria al descartar incorrectamente gránulos en tablas con una columna de clave en orden inverso (
DESC) cuando las partes no tienen marca final (granularidad no adaptativa,index_granularity_bytes = 0). #109901 (nihalzp). - Se corrigen el error lógico
Expected CommonSubplanReferenceStep to reference CommonSubplanStep, el errorSubplan cannot be used to build pipeliney el error lógicoTrying to extract chunk from ChunkBuffer before all inputs are finishedenIN (subquery)cuando la subconsulta contiene una subconsulta correlacionada y el conjunto se construye durante el análisis de índices. #110491 (alexey-milovidov). - Se corrige el error
NOT_FOUND_COLUMN_IN_BLOCKen las funciones de distancia transpuestas sobre columnasQBit(comocosineDistanceTransposed) cuando se invocaban con un vector de referencia constante o procedente de una subconsulta escalar con las réplicas paralelas habilitadas. #110729 (alexey-milovidov). - Se corrige que el índice de texto no se utilizara cuando su expresión contenía una comparación con una cadena vacía, como
arrayFilter(s -> s != '', ...), ya que el ajusteoptimize_empty_string_comparisonsreescribe la comparación comonotEmptysolo en el lado de la consulta. #112115 (Ergus). - Ya no se eliminan columnas referenciadas tanto en las condiciones de filtro de
PREWHEREcomo en las deWHERE, aunque se reescriban como una columna virtual de índice de texto. #114460 (ahmadov). - Se corrigió el error lógico
Multi-block postings must be compresseden consultas sobre tablas con un índice de texto en el modo de aplicación diferida de posting-lists, cuando la consulta se cancelaba durante la lectura. #114636 (CurtizJ). - Se corrigieron resultados incorrectos cuando una cláusula
WHEREcontenía una expresiónNULLdentro de unNOT, por ejemploSELECT count() FROM t WHERE NOT (id >= 20 AND NULL). El análisis de índices consideraba que dicha condición era demostrablemente verdadera para todo el rango, por lo que se omitía el filtro:count()devolvía filas que la consulta rechaza, yALTER TABLE ... DELETEcon esa condición eliminaba filas que debería haber conservado. #115152 (groeneai). - Se corrigió un
LOGICAL_ERROR(Join is supported only for pipelines with one output port) en un JOINfull_sorting_mergeconquery_plan_join_shard_by_pk_rangeshabilitado cuando la poda deja sin ninguna parte a uno de los dos lados, ya sea por la clave primaria, por las estadísticas de columna o porque la tabla está vacía. #115352 (alexey-milovidov). - Se deshabilita la caché de condiciones de consulta para filtros sobre _part_starting_offset #115358 (azat).
- Se corrigió
LOGICAL_ERROR: Index with name auto_minmax_index_<column> already existscuando una única sentenciaALTER TABLEcombinabaRENAME COLUMNcon otro comando, comoMODIFY SETTING, en una tabla con índices minmax implícitos (add_minmax_index_for_numeric_columnsy similares). Además, renombrar una columna simple ya no provoca que unDROP COLUMNposterior falle conUNKNOWN_IDENTIFIER, ni que unADD COLUMNposterior quede sin su índice implícito. #116063 (groeneai). - Un patrón
LIKE/NOT LIKEsin comodines (%,_) ahora utiliza un rango exacto de la clave primaria, por lo que lee el mismo número de gránulos que el predicado equivalente=/!=, en lugar de un rango de prefijo más amplio. #107077 (groeneai). - Se corrigieron un
LOGICAL_ERROR(Invalid binary search result in MergeTreeSetIndex) y la falta de poda de índices en builds de release cuando una condiciónIN/NOT INsobre la clave primaria envuelve la clave enintDivpor una constante y la clave es un entero sin signo cuyos valores cruzan el límite del tipo con signo resultante deintDiv(por ejemplo,intDiv(uint64_column, -9223372036854775807)). #107586 (groeneai). - Se corrigió que
numericIndexedVectorPointwiseMultiplydevolviera un resultado vacío al multiplicar por un vector de unos con una configuración de bits BSI diferente. #108027 (alexey-milovidov). - Se corrigió un desbordamiento de búfer en el heap al construir un índice de texto con
positions = 1sobre muchos tokens cortos distintos. #108659 (groeneai). - Se permite que las expresiones
preprocessorypostprocessorde un índice de texto hagan referencia a columnasALIAS. #110014 (Ergus). - Se omite la optimización de búsqueda vectorial cuando se usa
LIMIT ... WITH TIES, ya que la optimización limita la búsqueda ANN a exactamente n candidatos y se descartan las filas empatadas con la n-ésima fila. #110453 (tamish560). - Se corrigió un problema por el que el índice de texto no se utilizaba para
ILIKEcuando el índice se define sobre una expresión en lugar de una columna simple (por ejemplo,assumeNotNull(col)con un preprocesadorlower(...)). Ahora estas consultas usan el índice en lugar de leer todos los gránulos. #110595 (ahmadov). - Se corrige un
LOGICAL_ERROR(LazyMaterializingTransform: Number of rows in lazy chunk N does not match number of offsets M) que podía producirse en consultas de búsqueda vectorial convector_search_with_rescoring = 1combinadas con materialización diferida cuando había empates entre varias distancias. #111003 (groeneai). - Se rechazan los vectores cuya magnitud al cuadrado se desborda a infinito al usar un índice
vector_similaritycon cuantizacióni8(anteriormente, estos vectores provocaban un comportamiento no definido en usearch y generaban datos basura sin ningún aviso). #111085 (groeneai). - Se corrigieron lecturas obsoletas en discos
plain_rewritablecon la caché de páginas habilitada. #111105 (Michicosun). - Se corrigieron resultados incorrectos de
count()y filas descartadas cuando una claveString(oFixedStringde menor longitud) o un índice de omisión minmax se filtraba mediante una comparación con una constanteFixedStringde mayor longitud, p. ej.,toFixedString('abc', 257) = string_col. La poda por clave primaria y por minmax construía el rango a partir de la constante rellenada con NUL y omitía erróneamente gránulos que sí coincidían. #111106 (groeneai). - Se corrigió la lectura de archivos Parquet cuyo índice de offsets no comienza en la fila 0. Un archivo de este tipo podía hacer que el lector nativo de Parquet devolviera filas incorrectas o notificara
LOGICAL_ERRORen lugar deINCORRECT_DATA. Ahora el índice de offsets se valida al leerse. #114530 (groeneai).
Correcciones de seguridad, acceso, copias de seguridad y restauración
RESTOREahora ejecuta fsync sobre los archivos de las partes restauradas cuando la tabla de destino tienefsync_after_inserthabilitado, de modo que una parte restaurada resiste un corte de energía igual que una insertada. Anteriormente, los archivos restaurados solo se escribían y cerraban (nunca se ejecutaba fsync sobre ellos), por lo que un corte de energía justo después de queRESTOREdevolvieraRESTOREDpodía dejar las partes dañadas y la tabla vacía. #111378 (groeneai).- Se corrige un problema de seguridad por el cual un cliente TCP no autenticado podía sondear la existencia de tablas y el estado de replicación a través del puerto entre servidores. #99854 (tiandiwonder).
- Se corrigió que
DELETE FROM(eliminación ligera) requiriera el privilegioALTER UPDATEademás deALTER DELETE. Un usuario al que solo se le haya concedidoALTER DELETEahora puede ejecutarDELETE FROM, tal como indica la documentación. #107491 (tiandiwonder). - Se corrigió que
CREATE TABLE ... AS SELECTen bases de datos Atomic dejara una tabla vacía cuando la consulta fallaba, por ejemplo, cuando el usuario no tiene acceso a una tabla referenciada desde una subconsulta. Anteriormente, al reintentar se informaba de que la tabla ya existía en lugar de mostrar el error original. Ahora la tabla se crea mediante una tabla temporal y solo se vuelve visible una vez que se ha llenado por completo. #108048 (alexey-milovidov). - Se corrigió un
LOGICAL_ERROR(No available columns) al ejecutarSELECT count()(u otras consultas triviales) sobre una tabla en la que al usuario solo se le ha concedido accesoSELECTa una columnaALIAS. #108056 (alexey-milovidov). - Se corrige un problema por el cual solicitudes no autenticadas podían hacer que ClickHouse resolviera nombres de host proporcionados en encabezados de dirección de cliente redirigida. Ahora ClickHouse solo acepta direcciones IP numéricas en estos encabezados. Los valores no válidos se ignoran, sin resolución DNS, a efectos de atribuir cuotas por dirección redirigida. Cuando
auth_use_forwarded_addressestá habilitado, las direcciones redirigidas no válidas se rechazan durante la autenticación. Los rechazos se registran en el log con nivel de depuración. #111060 (otselnik). - Se corrige que
SQL SECURITY DEFINER(ySQL SECURITY NONE) no se respetaran en las vistas parametrizadas cuando el analizador está deshabilitado (enable_analyzer = 0). Anteriormente, consultar una vista de este tipo como usuario sin privilegios sobre la tabla subyacente fallaba conACCESS_DENIED, aunque la misma vista funciona con el analizador habilitado. #111458 (groeneai). - Se corrigió un defecto en las integraciones de
MySQLpor el cual se aceptaba sobrescribir una credencial TLS de una colección con nombre con un valor vacío dessl_ca_pem/ssl_cert_pem/ssl_key_pemcuando la colección almacenaba la credencial como contenido, lo que descartaba silenciosamente la CA o el certificado de cliente configurados en lugar de rechazar la sobrescritura. #113947 (alexey-milovidov). - Se corrigió que
EXPLAIN ANALYZEperdiera las estadísticas de unión de una vista declarada conSQL SECURITY DEFINERoSQL SECURITY NONEcuyo cuerpo contiene un JOIN. En las compilaciones de depuración y con sanitizers, la consulta se abortaba con el error lógicoJoinStep analyzed without the analyze mode. #115156 (groeneai). - Se corrige que
RESTORE ... AS <new name>dejara la listaREFRESH ... DEPENDS ONde una vista materializada actualizable apuntando a la base de datos original. La vista restaurada se actualizaba en respuesta a una tabla que ya no leía, ignoraba las actualizaciones de su propia tabla padre y dejaba de actualizarse por completo en cuanto se eliminaba la base de datos original. #115689 (groeneai). - Se corrigió una excepción
LOGICAL_ERRORdurante la copia de seguridad de una base de datosReplicatedque se estaba eliminando y recreando de forma concurrente; ahora estas copias de seguridad fallan de forma controlada conCANNOT_GET_REPLICATED_DATABASE_SNAPSHOT. #100651 (alexey-milovidov). GRANT role TO rolesobre el mismo rol ahora se rechaza conBAD_ARGUMENTS, en lugar de crear silenciosamente una entrada autorreferencial ensystem.role_grants. #103315 (zxuhan).BACKUPde una base de datosMaterializedPostgreSQLya no se queda bloqueado indefinidamente con “Table … were created or changed its definition during scanning” y ahora sí realiza la copia de seguridad de los datos de la tabla (delegándola en elReplacingMergeTreesubyacente), que puede restaurarse como unReplacingMergeTreeindependiente. #107433 (alexey-milovidov).- Se permite
EXISTS <dictionary>a un usuario que solo tiene el privilegioSHOW DICTIONARIESsobre el diccionario (antes se requeríaSHOW TABLES). #108084 (alexey-milovidov). - Se corrigió la limpieza de un
BACKUP ... TO Memory(...)que falla antes de finalizar: la copia de seguridad fallida permanecía registrada, por lo que su nombre no podía reutilizarse. #109947 (jkartseva). - Se corrigió un error lógico
ReadBuffer is canceled. Can't read from it.(que abortaba el servidor en builds de depuración o con sanitizador) que podía producirse al leer un archivo zip (p. ej., durante unRESTOREdesde una copia de seguridad en zip) después de que una lectura previa del mismo archivo fallara a mitad del flujo. #110197 (groeneai). - Se corrigió una corrupción del heap, que podía provocar el fallo del servidor durante el apagado, causada por que el método
constAccessRights::getFiltersmodificaba un árbol de derechos de acceso compartido por consultas concurrentes. #112692 (groeneai).
Ejecución distribuida, tablas, vistas y diccionarios
- Se corrigió un error espurio
Inconsistent AST formattingenALTER TABLE ... MOVE PART ... TO SHARD '<path>'. El formateador de consultas omitía la palabra claveSHARD, por lo que la consulta reformateada no podía volver a analizarse y se producía unLOGICAL_ERROR(una excepción gestionada en las builds de release y una interrupción en las builds de depuración y con sanitizadores). #109060 (groeneai). - Se corrigió un error lógico (
!part.empty()) que se producía al usar en un JOIN condistributed_product_mode = 'local'una tablaDistributeddefinida con un nombre de base de datos remota vacío. #110677 (groeneai). - Se corrigió que
DISTINCTcon unLIMIT/OFFSETordenado devolviera filas incorrectas cuando la pista de límite de detención anticipada de DISTINCT no podía acotar el inicio del resultado: unLIMITnegativo (devolvía el inicio en lugar del final), unLIMIT/OFFSETfraccionario (la fracción solo se resuelve tras una lectura completa) y unOFFSETsinLIMIT(se descartaba el final posterior al offset). Por ejemplo,SELECT DISTINCT intDiv(x, 100) FROM t ORDER BY intDiv(x, 100) LIMIT -1sobre una tabla con varias partes devolvía el valor distinto más pequeño en lugar del más grande. #111326 (groeneai). - Corrige el caso en que el analizador no aceptaba un alias después de una subconsulta en DESCRIBE TABLE, lo que provocaba un error de sintaxis. Corrige https://github.com/ClickHouse/ClickHouse/issues/100031. #100205 (yariks5s).
- Se corrigió una interrupción del servidor (
Logical error: 'Block structure mismatch') que podía producirse durante unINSERTconcurrente mientras se ejecutaba unALTER RENAME COLUMNen una base de datosAtomicconlazy_load_tables = 1después deDETACH DATABASE/ATTACH DATABASE. #104852 (groeneai). - Corrige la corrupción de nombres de columnas y la excepción
BAD_ARGUMENTScausadas por el ajusteinject_random_order_for_select_without_order_by. Con el ajuste habilitado, los SELECT de varias columnas ya no fallan y los nombres de las columnas de salida (p. ej., enCREATE TABLE AS SELECT,CREATE VIEW AS SELECToJSONEachRow) se conservan en lugar de sustituirse por alias internos__subquery_column_<UUID>. #105896 (groeneai). - Corrige la confusa pista “Maybe you meant X?” que aparecía tras reiniciar el servidor (o tras
DETACH/ATTACH DATABASE): al intentar eliminar una tabla ya eliminada, se sugería como alternativa el mismo nombre recién eliminado. Ahora, las tareas de carga asíncrona se eliminan deDatabaseOrdinary::startup_tableyload_tableal desconectar la base de datos. #106238 (groeneai). - Corrige los motores de tabla y de base de datos
MaterializedPostgreSQLpara que una sola tabla o base de datos pueda replicarse desde un esquema de PostgreSQL distinto del predeterminado (materialized_postgresql_schema), incluido el caso en que existen tablas con el mismo nombre en varios esquemas de la misma base de datos (antes compartían una publicación y un slot de replicación, e interferían entre sí). #107425 (alexey-milovidov). - Se corrigieron los errores
NO_SUCH_COLUMN_IN_TABLEcuando una consulta con réplicas paralelas selecciona una columnaALIASde una tabla enviada como tabla temporal deGLOBAL JOIN;MULTIPLE_EXPRESSIONS_FOR_ALIAScuando ambos lados de unJOINdistribuido declaran una columnaALIAScon el mismo nombre; yUNKNOWN_IDENTIFIERcuando una tablaDistributeddeclara una columnaALIASbasada en otra columnaALIAS, también cuando se usa como clave deJOIN USING. #107700 (yakov-olkhovskiy). - Se corrigió un desbordamiento de entero con signo cuando una vista materializada actualizable reintenta una actualización fallida con
refresh_retriesestablecido en un valor muy grande (cercano al máximo deInt64). El desbordamiento podía provocar la terminación abrupta del servidor en builds con el sanitizador de comportamiento indefinido. #108005 (groeneai). - Se corrigió una excepción (
CANNOT_PARSE_TEXT) al cargar un diccionario con una clave compuesta cuyas columnas de clave no son las primeras de la definición del diccionario, con una fuente localClickHouseque usa una consulta explícita. Ahora las columnas de origen se asocian a la estructura del diccionario por nombre en lugar de por posición. #108053 (alexey-milovidov). - Se corrigió un fallo (desreferencia de puntero nulo) al consultar una tabla
Hivesin cláusulaWHERE, p. ej.,SELECT * FROM hive_table. #108094 (alexey-milovidov). - Se corrigió un fallo del servidor (violación de segmento) que podía producirse cuando una consulta distribuida hacía referencia a un CTE
MATERIALIZEDaún no materializado como tabla externa y la fuente remota se creaba de forma diferida (fuente retrasada). El fallo se debía a la desreferencia de unLoggernulo dentro deRemoteQueryExecutor::sendExternalTables(). #108547 (groeneai). - Se corrigió un error lógico (
Equal values are not contiguous within the range assumed to be sorted) al ejecutarDISTINCTsobre una lecturaSTREAM(SELECT DISTINCT ... FROM table STREAM). Las optimizaciones de lectura en orden ya no se aplican a las lecturasSTREAM, que devuelven las filas en orden de confirmación y no según la clave de ordenación. #108568 (groeneai). - Se corrigió una excepción (
Cannot find sharding key columny, en builds de depuración/sanitizador, la terminación abrupta del servidor) cuando la clave de sharding de una tablaDistributedes una expresión que el analizador pliega como constante, por ejemploif(1, toInt32(id), toInt32(id) + 1), conoptimize_skip_unused_shards = 1. #108737 (groeneai). - Se corrigió una terminación abrupta del servidor (
LOGICAL_ERROR/ aserción en builds de depuración y sanitizador) cuando unINSERT ... SELECTa través de una tablaAliasse cancela sin lanzar una excepción, por ejemplo contimeout_overflow_mode = 'break'. #108783 (groeneai). - Se corrigió una terminación abrupta del servidor (
LOGICAL_ERROR/ aserción en builds de depuración y sanitizador) cuando unINSERT ... SELECTen una tablaTimeSeriesse cancela sin lanzar una excepción, por ejemplo contimeout_overflow_mode = 'break'. #108796 (tiandiwonder). - Se corrigió un problema por el que las consultas distribuidas fallaban ocasionalmente con
UNEXPECTED_PACKET_FROM_SERVER(“expected TablesStatusResponse, got ProfileInfo”) al reutilizarse desde el pool una conexión que una consulta cancelada previamente había dejado desincronizada. #108854 (alexey-milovidov). - Se corrigió un
LOGICAL_ERROR(CTE '...' does not have query tree, but was not planned yet) cuando se hace referencia a un CTEMATERIALIZEDdesde más de una posición del árbol de uniones (por ejemplo, dos subconsultas unidas, o una subconsulta unida más una subconsulta escalar enWHERE) en una consulta sobre una tablaDistributed. Ahora la consulta se ejecuta en lugar de lanzar la excepción (que provocaba la terminación abrupta del servidor en builds de depuración/sanitizador). #108924 (groeneai). - Corrige un problema de seguridad de memoria por el que el trabajo asíncrono programado desde el procesamiento de una vista materializada podía seguir usando la contabilidad a nivel de consulta después de que esta hubiera finalizado. #108988 (filimonov).
- Corrige un
LOGICAL_ERROR(“Cannot find__grouping_setcolumn in header of MergingAggregatedTransform with grouping sets”, o “Chunk info was not set for chunk in MergingAggregatedTransform”) que podía producirse, sin el analizador, en unUNION ALL/INTERSECT/EXCEPTen el que una rama usaGROUP BY GROUPING SETScon réplicas paralelas y otra usaFINAL. #109003 (groeneai). - Corrige el fallo de
CREATE TABLE ... AS SELECT FROM s3Cluster(...)(y de otras funciones de tabla de cluster comofileCluster/urlCluster) conNOT_FOUND_COLUMN_IN_BLOCKdentro de una base de datosReplicated. #109266 (groeneai). - Se corrigió un error (
NOT_FOUND_COLUMN_IN_BLOCK, ostd::bad_function_callen versiones anteriores) al ejecutarCREATE TABLE ... ON CLUSTER ... AS SELECTpara leer una tablaDistributeden un cluster con dos o más shards. #109407 (alexey-milovidov). - Se corrigió un error interno confuso (
Method getResultType is not supported for TABLE query tree node) que se producía al usar una expresión de tabla como argumento izquierdo del operadorIN; ahora estas consultas devuelven un mensaje de error claro. #109412 (alexey-milovidov). - Corrige un error lógico
Bad cast from type DB::FunctionNode to DB::ConstantNode(cierre abrupto del servidor en builds de depuración/sanitizador) al ejecutarSELECT ... ORDER BY ... WITH FILLsobre una tablaDistributedcon un valor bajo deoptimize_const_name_size. #109938 (groeneai). - Corrige un
LOGICAL_ERROR(Left and right columns have same names) en el optimizador del orden de join que podía desencadenarse con una unión mediante coma sobre una vista de varias tablas cuandoquery_plan_merge_expression_into_joinestá habilitado. #110227 (groeneai). - Corrige un
Logical error: 'No more packets are available.'poco frecuente que se generaba en una consulta distribuida válida conLIMITy que provocaba el cierre abrupto del servidor en builds de depuración y con sanitizador. #110334 (groeneai). - Se corrigió un error del analizador sintáctico por el que COMMENT se interpretaba incorrectamente como alias implícito cuando una consulta SELECT terminaba justo después de un identificador de tabla sin más (p. ej.,
... FROM t COMMENT 'x'), lo que provocaba un error de sintaxis engañoso en lugar de aplicar el comentario a la vista/tabla. #110372 (adityaksolves). - Se corrigió un resultado incorrecto por el que
length()(y la dimensión de QBit) sobre una columnaFixedStringdevolvía0en lugar del tamaño fijoNcon réplicas paralelas cuando la consulta tenía un filtro selectivo. #110427 (groeneai). - Corrige el error
NOT_FOUND_COLUMN_IN_BLOCKen consultas con una subconsulta enFROMcuando las réplicas paralelas se ejecutan en modocustom_key_sampling/custom_key_range. Hasta ahora, estas consultas (p. ej.,SELECT * FROM (SELECT id, k, v FROM t WHERE id < 20) ORDER BY k) fallaban conNot found column __table2.id in block .... #110690 (groeneai). - Se corrige
Logical error: 'clock'(en builds de depuración/sanitizer el servidor se cae; en builds de release se queda colgado indefinidamente) al ejecutarEXPLAIN ANALYZEsobre una consulta con una lectura en streaming (FROM ... STREAM) que no es una expresión de tabla simple de nivel superior: anidada en una subconsulta (por ejemplo, dentro deWHERE ... IN (...)o de una CTE), u oculta tras una vista ordinaria o parametrizada.EXPLAIN ANALYZEahora rechaza estas consultas conNOT_IMPLEMENTED, igual que ya rechazaba una lectura en streaming de nivel superior. #110935 (groeneai). - Se corrige la resolución de nombres de columna completamente calificados, como
db.table.column, en el analizador para tablas que tienen el mismo nombre que su base de datos. #110976 (alexey-milovidov). - Se corrigieron los errores
NOT_FOUND_COLUMN_IN_BLOCK/THERE_IS_NO_COLUMN(y, en algunas versiones, resultados incorrectos sin ningún aviso) en unRIGHT JOINcuando se estableceparallel_replicas_min_number_of_rows_per_replicay se proyecta una columna de la tabla izquierda. #111332 (groeneai). - Se corrige una condición de carrera en las UDF ejecutables, el motor de tabla
executabley los diccionarios ejecutables, en la que unfcntlsobre un descriptor de archivo ya cerrado podía corromper un descriptor ajeno perteneciente a una consulta concurrente (eliminandoO_NONBLOCK), lo que podía dejar las consultas colgadas indefinidamente. #111779 (Algunenano). - Se corrigió un
LOGICAL_ERROR(“Invalid number of rows in Chunk”) —y, en builds reforzados, una interrupción relacionada por acceso fuera de límites— enORDER BY ... WITH FILL ... INTERPOLATEsobre una tablaDistributedcon dos o más segmentos, sobreclusterAllReplicaso sobre réplicas paralelas con clave personalizada, incluso con resultados vacíos.WITH FILLahora se aplica solo en el nodo que produce el resultado final, lo que además corrige la duplicación de las filas de relleno generadas entre segmentos/réplicas. #111919 (yakov-olkhovskiy). - Se corrigió que
DROP TABLE ... SYNCse quedara colgado indefinidamente cuando una consulta sobresystem.replicasse había terminado antes de que se procesaran sus solicitudes de estado. #112164 (evillique). - Se corrige una excepción
LOGICAL_ERROR(Block structure mismatch in joined block stream) en una unión de varias tablas cuyas dos subuniones no producen ninguna columna de salida, por ejemploSELECT count() FROM t1, t2, t3, t4 WHERE (t1.b = t2.b) AND (t3.a = t4.a)conquery_plan_optimize_join_order_limitestablecido en0o1. #112205 (groeneai). - Se corrige un error lógico
Cannot add step Expression to QueryPlan because it has incompatible header with root step JoinLazyColumnsStepen una consulta conFINAL, un filtroPREWHERE, unLIMITpequeño ymake_distributed_plan = 1, cuando las columnas seleccionadas se enumeran en un orden distinto al de las columnas de la tabla. La materialización diferida reemplazaba un nodo del plan sin conservar su encabezado de salida, lo que volvía inconsistente el plan de consulta. #112303 (groeneai). - Se corrigen resultados incorrectos y un error lógico cuando un argumento que debe ser constante, como la escala de
toDecimal32o la zona horaria detoDateTime, proviene de una subconsulta escalar y se utiliza el analizador antiguo. Dicho argumento se analizaba como si su valor fuera cero o vacío, por lo que el tipo de resultado declarado no coincidía con el valor calculado, yCREATE VIEWyCREATE MATERIALIZED VIEWguardaban un tipo de columna incorrecto. #112492 (groeneai). - Corrige un error lógico y un registro de dependencia incorrecto cuando el cuerpo de una
VIEWordinaria hace referencia a una tabla o diccionario mediante un parámetro de consulta, como enCREATE VIEW v AS SELECT x FROM {db:Identifier}.t. Este tipo de vista ya no registra una dependencia referencial con una tabla homónima de la base de datos actual, por lo que vuelve a ser posible eliminar tablas no relacionadas. #112704 (groeneai). - Corrige un error lógico cuando se usa una tabla con motor
Joinen el lado derecho de un JOIN cuya secciónONcontiene una condición que hace referencia a columnas de ambas tablas, por ejemploON (t.key = j.key) AND (t.a < j.a). Ahora este tipo de consulta se rechaza con una excepción clara en lugar de generarrequired columns: ... but not found any in left tableostd::bad_variant_access. #112815 (groeneai). - Se corrigió un comportamiento indefinido y un error silencioso de planificación cuando una tarea en segundo plano se programa con un retraso muy grande, por ejemplo, desde una vista materializada actualizable con un período
REFRESH AFTERenorme. Ahora los retrasos se limitan al mayor valor representable en lugar de desbordarse. #113041 (groeneai). - Se corrigió el error que se notificaba cuando un
INSERTasíncrono en una tablaDistributednecesita un directorio de cola cuyo nombre supera el límite de 255 bytes del sistema de archivos (algo que puede ocurrir conuse_compact_format_in_distributed_parts_names = 0). Se producía unLOGICAL_ERRORen un shard coninternal_replicationy, en los demás casos, unCode: 1001. std::exceptionsin contexto; ahora ambos casos notificanARGUMENT_OUT_OF_BOUNDe indican la tabla, el clúster y el límite. #113083 (groeneai). - Ahora
UNDROP TABLEpuede interrumpirse conKILL QUERYmientras espera a que las consultas en ejecución liberen la tabla eliminada. #113263 (alexey-milovidov). - Se corrigió un bloqueo permanente de
DROP TABLEy una fuga de memoria tras el fallo de una consulta que usaba un CTE materializado. La tabla quedaba atascada en la cola de eliminación hasta que se reiniciaba el servidor. #113397 (tiandiwonder). - Corrige un fallo de segmentación y un
LOGICAL_ERROR(No host found for exchange stream final_result__0_0) cuando una subconsulta establecedistributed_plan_execute_locallyen su propia cláusulaSETTINGSconmake_distributed_plan. El plan distribuido y el código que lo ejecuta leían la configuración desde dos contextos distintos y podían no coincidir, de modo que el iniciador construía un pipeline contradictorio. #113422 (groeneai). - Se corrigió que un
CREATE TABLE ... AS SELECTcuyoSELECTde llenado fallaba no pudiera terminarse cuandodatabase_atomic_wait_for_drop_and_detach_synchronouslyestá habilitado: elDROPinterno de limpieza de la tabla temporal esperaba a la cola de eliminación en segundo plano e ignoraba tantoKILL QUERYcomomax_execution_time. #113504 (groeneai). - Corrige resultados incorrectos y, en compilaciones con aserciones habilitadas, un aborto por aserción en un
JOINcon un diccionario cuya cláusulaONincluye una condición de no igualdad sobre ambas tablas, comoON (t.key = d.key) AND (t.a * 10 < d.a), cuandojoin_use_nullsestá habilitado. La condición se evaluaba sobre una columna leída con un tipo que no correspondía, por lo que las filas podían coincidir de forma arbitraria. #113534 (alexey-milovidov). - Se corrigió un problema por el que una vista parametrizada perdía su base de datos cuando una consulta que la referenciaba sin calificar se enviaba a un segmento, de modo que el segmento resolvía el nombre en su propia base de datos predeterminada. Según lo que contuviera esa base de datos, la consulta fallaba con
UNKNOWN_FUNCTIONo devolvía silenciosamente filas de otra vista. Afecta aIN,JOINyremote()a través de una tablaDistributed. #113550 (groeneai). - Se corrigió
Unsupported JOIN keys of type keys256 in StorageJoinal leer una tabla con motorJoincuya clave es compuesta (varias columnas) o un único valor de 16/32 bytes, comoUUID,Int256oFixedString(4). Una tabla así podía crearse, recibir escrituras y usarse en uniones, pero nunca podía leerse conSELECT. #113578 (groeneai). - Se corrigió un error lógico
Sending a distributed query with unknown (zero) client versionque se producía al adjuntar una tablaDistributedsin estructura sobre un segmento remoto, o al cargarla a partir de metadatos escritos por una versión anterior del servidor. #113675 (alexey-milovidov). - Se corrigió un
LOGICAL_ERRORque se producía cuando unSELECTusaba el modificadorSTREAMsobre una tabla con nombre junto con réplicas paralelas en el modo de tareas de lectura. Con un CTE materializado usado como conjuntoINenPREWHERE, el servidor generabaReading from materialized CTE ... DelayedPortsProcessor gate is missing in the query plan(lo que provocaba un aborto del servidor en builds de depuración y con sanitizador). Ahora se rechaza una tabla conSTREAMcuando se solicitan réplicas paralelas: conenable_parallel_replicas = 2, la consulta falla conSUPPORT_IS_DISABLED, y con1se ejecuta sin ellas, tal como ya ocurre conFINAL. #113754 (groeneai). - Se corrigió la complejidad cuadrática del análisis del argumento de dirección de las funciones de tabla
remote,mysqly similares: una dirección muy larga (p. ej., unFixedStringde un megabyte rellenado con ceros) hacía que la consulta se quedara bloqueada durante el análisis, fase en la que no podía cancelarse. #113918 (alexey-milovidov). - Se corrigió un error espurio
Failed to drop temporary table after refresh. Table ... is left behind and requires manual cleanup.que se registraba cuando se cancelaba la actualización de una vista materializada actualizable (por ejemplo, por un apagado del servidor) condatabase_atomic_wait_for_drop_and_detach_synchronouslyhabilitado. En realidad, la tabla temporal sí se eliminaba, por lo que nunca fue necesaria una limpieza manual. #113957 (groeneai). - Se corrigió la ausencia de una fila en
system.query_views_logpara una vista materializada que falla mientras se recopilan sus dependencias conmaterialized_views_ignore_errorshabilitado. En builds de depuración y con sanitizador, esto además abortaba el servidor constd::out_of_rangeen lugar de registrar la vista. #114064 (groeneai). - Se corrigieron resultados inconsistentes cuando un filtro sobre una columna no clave de la tabla derecha se desplazaba por debajo de un ANY INNER JOIN. #114313 (kirillshokhin).
- Se corrigió que
CREATE OR REPLACEdejara huérfana una tabla interna_tmp_replace_*y queCREATE OR REPLACE VIEWfallara conNOT_IMPLEMENTEDcuando se establecíaignore_drop_queries_probability. Los DROP que emite internamente forman parte de una única sentencia del usuario, por lo que la inyección de fallos en DROP ya no se les aplica. #114420 (groeneai). - Se corrigió un
LOGICAL_ERRORal leer una tabla de Delta Lake cuyometaData.partitionColumnshace referencia a una columna quemetaData.schemaStringno declara. Ahora estos metadata se rechazan conBAD_ARGUMENTSen el lector delta-kernel y conINCORRECT_DATAen el lector heredado siempre que la tabla o su esquema se lean desde una instantánea, y no solo cuando la consulta incluye un predicado. #114538 (groeneai). - Se corrigió un problema por el que las estadísticas de tablas hash —y, con ellas, la preasignación de tablas hash de agregación— quedaban deshabilitadas de forma silenciosa y permanente para todo el servidor cuando una consulta que usaba la optimización diferida de
FINAL(query_plan_optimize_lazy_final) era la primera agregación ejecutada tras el inicio del servidor. #114597 (alexey-milovidov). - Se corrigió un problema por el que una vista materializada actualizable dejaba huérfana su tabla de destino rotada cuando
ignore_drop_queries_probabilityestaba habilitado. ElDROPque emite una actualización para limpiar el destino anterior forma parte de la propia actualización, no es unDROPsolicitado por el usuario, por lo que la inyección de fallos ya no se le aplica. #114622 (groeneai). - Se corrigió un problema por el que
ANY RIGHT JOINySEMI RIGHT JOINcon varias condiciones combinadas conORen la secciónONdevolvían algunas filas de la tabla derecha por duplicado y perdían las coincidencias de otras. UnANY LEFT JOINescrito explícitamente también se veía afectado, ya que el planificador puede intercambiar las tablas y ejecutarlo comoANY RIGHT JOIN. #114676 (vdimir). - Se corrige un
LOGICAL_ERROR(Cannot find input column ... on its position in inputs of expression actions DAG) cuando una consulta tiene unJOINsobre una tabla cuya columna con índice de texto se usa tanto en un predicado de búsqueda de texto dePREWHEREcomo en uno deWHERE. #114771 (groeneai). - Se corrige el error
NOT_FOUND_COLUMN_IN_BLOCKque se producía en cadaINSERTen una tabla que declaraSTATISTICS(...)sobre una columnaALIASoEPHEMERAL, lo que dejaba dichas tablas en modo de solo lectura. #115231 (groeneai). - Se corrige
dictGety sus variantes en consultas distribuidas: ahora un nombre de diccionario no calificado se vincula a la base de datos actual del initiator, en lugar de resolverse con la base de datos actual de cada shard, donde o bien no se encontraba o bien se resolvía a otro diccionario con el mismo nombre. #115541 (alexey-milovidov). - Se corrigió un error por el que, al restaurar una base de datos o tabla con un nuevo nombre, se eliminaban los alias de tabla de los cuerpos de las vistas almacenadas, por lo que la lectura de una vista restaurada fallaba con
UNKNOWN_IDENTIFIER. #115645 (groeneai). - Se corrige el
LOGICAL_ERROR“Reading from materialized CTE ‘X’ before its materialization completed - DelayedPortsProcessor gate is missing in the query plan” cuando se lee una CTEMATERIALIZEDdesde una subconsultaINsobre una tablaDistributed. #115740 (groeneai). - Se corrige el error BAD_ARGUMENTS “Dictionary not found” en dictGet tras un DETACH DICTIONARY … PERMANENTLY rechazado por la comprobación de dependencias (HAVE_DEPENDENT_OBJECTS). Ahora el diccionario sigue siendo plenamente utilizable cuando se rechaza el detach. #105259 (groeneai).
- Se corrigió un
Logical error: 'removed'(aborto del servidor en compilaciones de depuración) en la cola en segundo plano de eliminación de tablas. Podía producirse al reutilizar el mismo UUID explícito en varias consultasCREATE OR REPLACE TABLE, lo que añadía a la cola más de una tabla eliminada con ese mismo UUID. #107031 (groeneai). - Se corrigió que
MaterializedPostgreSQLdetuviera la replicación de toda una base de datos (conLOGICAL_ERROR: Columns number mismatch) cuando la estructura de una sola tabla replicada cambiaba mientras el servidor estaba detenido. Ahora solo se omite la tabla afectada, que puede recuperarse conDETACH/ATTACH. #107427 (alexey-milovidov). - Se corrigió un desequilibrio grave en el reparto del trabajo con réplicas paralelas cuando el cluster contiene réplicas inactivas (por ejemplo, entradas obsoletas que quedan tras el escalado automático). El coordinador de lectura ya no tiene en cuenta dichas réplicas, por lo que el trabajo se reparte entre las réplicas en línea en lugar de acumularse en una sola. #107805 (alexey-milovidov).
- Se corrigió un bloqueo de
SYSTEM RELOAD DICTIONARIES(yRELOAD DICTIONARY) cuando muchos diccionarios de MySQL definidos en XML compartían un único grupo de conexiones medianteshare_connection. Ahora dichos grupos respetan los valores deconnection_pool_sizeyconnection_wait_timeout(5 segundos por defecto) de la configuración, igual que los diccionarios definidos mediante colecciones con nombre. #108083 (alexey-milovidov). - Se evita que, al agotarse los reintentos de un DDL distribuido replicado ejecutado por el líder, se bloqueen de forma permanente las consultas DDL
ON CLUSTERposteriores. #108505 (ahaanlimaye). - Se corrigió un posible fallo (use-after-free) cuando
SYSTEM FLUSH DISTRIBUTEDse ejecuta simultáneamente conDROP TABLEsobre la misma tablaDistributed. #108684 (groeneai). - Se corrigió un
LOGICAL_ERROR(local_replica_plan_reading_step->getAnalyzedResult() == nullptr) en el planificador automático de réplicas paralelas que podía producirse al habilitarautomatic_parallel_replicas_modejunto con un valor deparallel_replicas_min_number_of_rows_per_replicamayor que 0. #109011 (groeneai). - Se corrigió un
LOGICAL_ERROR(creation_csn is not set while removal_csn is set to 1) que podía producirse cuando unTRUNCATEno transaccional se ejecutaba simultáneamente con una transacción sin commit que había insertado datos en la misma tabla. DichoTRUNCATEya no elimina las partes creadas por transacciones que aún no han hecho commit. #109598 (tuanpach). - Los motores de base de datos externos (p. ej.,
PostgreSQL) ya no delegan las comparaciones de rango (>=,>,<=,<) sobre columnasUUID. ClickHouse y las bases de datos externas ordenan los UUID de forma distinta, por lo que delegar estas comparaciones descartaba silenciosamente filas del resultado; ahora es ClickHouse quien evalúa dichos predicados. #109833 (vismaytiwari). - Se corrigió un fallo del servidor en el motor de base de datos
MaterializedPostgreSQLque podía producirse al desvincular una tabla (o cambiar su estructura) mientras aún estaba en cola para sincronizarse. #110596 (alexey-milovidov). - Se corrigió que las
query_masking_rulesdel servidor reescribieran el tipo de una columnaEPHEMERAL. Una regla que coincidía dentro del tipo hacía queCREATE TABLEalmacenara un tipo incorrecto o fallara. #112048 (alexey-milovidov). - Corrige un desbordamiento por debajo (underflow) sin signo en la comprobación de la longitud del nombre de tabla que permitía crear una tabla que luego era imposible eliminar. Cuando el nombre escapado de la base de datos alcanzaba los 214 bytes, el límite calculado para el nombre de archivo
metadata_droppedse desbordaba, por lo queCREATE TABLEse aceptaba y el posteriorDROP TABLEoDROP DATABASEfallaba conFile name too long. Ahora ese nombre se rechaza conARGUMENT_OUT_OF_BOUND, el mismo error que ya se devolvía justo por debajo de ese límite. #112527 (groeneai). - Se corrigió que
RENAME TABLEcomprobara la longitud máxima del nombre de tabla con respecto a la base de datos de origen en lugar de la de destino. Al renombrar una tabla para moverla a una base de datos con un nombre largo, se podía obtener una tabla queDROP TABLEno podía eliminar, y al moverla fuera de dicha base de datos, la operación se rechazaba erróneamente. #113019 (groeneai). - Corrige la columna
viewsdequery_log, que siempre quedaba vacía en las inserciones en una tablaAliascuyo destino dispara vistas materializadas. #113076 (eclbg). - Las expresiones
parallel_replicas_custom_keyno válidas, comotuple()o(x, y), ahora se rechazan conILLEGAL_TYPE_OF_COLUMN_FOR_FILTERen lugar de leer más allá de la lista de tipos de la clave personalizada. #113359 (nickitat). - Se corrigió que
RENAME DATABASEaceptara un nombre de destino lo bastante largo como para que las tablas de la base de datos ya no pudieran eliminarse. La comprobación de la longitud del nombre de tabla ahora se ejecuta independientemente decheck_table_dependenciesy abarca también las tablas desacopladas (detached), que nunca se comprobaban y, por tanto, se veían afectadas incluso con la configuración predeterminada. #113557 (groeneai). - Al usar inserciones en segundo plano en tablas con el motor
Distributed, los retrasos causados por errores repetidos al enviar datos a shards remotos ahora disminuyen una vez que los errores se resuelven. Antes, el retraso solo aumentaba y nunca se restablecía. #87378 (Blackmorse). - Se rechazan los handshakes del protocolo nativo que usan
USER_INTERSERVER_MARKERpara un cluster desconocido o para un cluster configurado sin<secret>. Antes, un handshake de este tipo permitía que un cliente no autenticado entrara en modo entre servidores y utilizara paquetes del protocolo previos a la autenticación (p. ej.,TablesStatusRequest) respaldados por unfake_interserver_context, con lo que podía obtener información sobre las tablas locales sin demostrar que conocía el secreto del cluster. #99675 (MillaFleurs).
Correcciones de SQL, del analizador y de JOIN
- Se corrige la sustitución de parámetros de consulta dentro de las definiciones de una cláusula
WINDOWcon nombre. Anteriormente, esos parámetros se quedaban sin sustituir sin ningún aviso, y un parámetroIdentifiersin asignar podía provocar la excepciónLogical error: '!part.empty()'duranteEXPLAIN SYNTAX. #110506 (alexey-milovidov). - Se corrige un fallo poco frecuente del servidor al eliminar o reemplazar de forma concurrente vistas materializadas actualizables. Se desreferenciaba un puntero nulo en
RefreshTask::doSchedulingcuando otro hilo establecía laviewde la tarea ennullptrmientras el código de planificación había liberado temporalmente su mutex. #105588 (groeneai). - Se corrige un resultado incorrecto de una vista definida con
EXCEPToINTERSECTcuyo operando es una cadenaUNIONtrasDETACH/ATTACHo un reinicio del servidor. El formateador omitía los paréntesis alrededor de los hijosUNIONdeINTERSECT/EXCEPT, por lo que el SQL almacenado se volvía a analizar con la precedencia invertida. #105935 (groeneai). - Se corrigen resultados incorrectos (filas duplicadas) en
SELECT DISTINCTsobre unGROUP BYconWITH CUBE,WITH ROLLUPoGROUPING SETSsobre las mismas claves. La optimizaciónquery_plan_remove_redundant_distinctya no elimina elDISTINCTen estos casos, ya que los modificadores de agrupación emiten filas adicionales con las columnas clave en sus valores predeterminados, que pueden coincidir con valores reales de grupo. #107072 (groeneai). - Se corrige un resultado incorrecto en un OUTER JOIN cuando el filtro
WHEREes una conjunción que contiene un término constante (por ejemplo,p AND 1, oWHERE p QUALIFY NULL, dondeQUALIFY NULLse fusiona enWHERE). El término constante de la conjunción podía trasladarse al lado no preservado de la unión y eliminarse del filtro posterior a la unión, de modo que la unión producía filas sin coincidencia con las columnas de ese lado en sus valores predeterminados, y dichas filas superaban el filtro de forma incorrecta. #107084 (groeneai). - Se corrige un
LOGICAL_ERROR(“Cannot find input column … on its position in inputs of expression actions DAG”) que abortaba el servidor en una subconsulta escalar correlacionada sobre un origen que proyectaba dos veces el mismo identificador de columna (p. ej.,SELECT number, *) cuandocorrelated_subqueries_default_join_kind = 'left'. #107112 (groeneai). - Se corrige un
LOGICAL_ERROR(aborto del servidor en compilaciones de depuración/sanitizer) cuando unJOINutiliza el operador de comparación segura frente a NULL (<=>/IS NOT DISTINCT FROM) y una de las claves es una subconsulta escalar, p. ej.,... JOIN t2 ON (SELECT x FROM t1) <=> t2.k, con el analizador antiguo (enable_analyzer = 0). Ahora, una consulta de este tipo devuelve un errorNOT_FOUND_COLUMN_IN_BLOCKnormal en lugar de un error lógico. #108123 (groeneai). - Se corrigen las excepciones
LOGICAL_ERROR(Join is supported only for pipelines with one output port) yNOT_IMPLEMENTED(MergeJoinAlgorithm is not implemented for strictness Semi) que se producían al usarjoin_algorithm = 'full_sorting_merge'en una uniónSEMI/ANTI, incluidas las uniones generadas al descorrelacionar una subconsulta correlacionadaEXISTS. Ahora,full_sorting_mergerechaza las combinaciones de estrictez/tipo que no puede ejecutar, de modo que el planificador recurre a otro algoritmo habilitado o informa de que la unión no puede ejecutarse. #108658 (groeneai). - Se corrigió un error por el cual la fila
WITH TOTALSde unJOINpodía contener valores predeterminados (como0) en lugar de los valores constantes procedentes de una subconsulta constante en uno de los lados de la unión. El resultado incorrecto solo aparecía con determinados órdenes de unión o con el ajustequery_plan_join_swap_table. #108807 (vdimir). - Se corrigió una interrupción durante el arranque (
Cannot allocate ThreadStack,EINVAL) en builds con glibc ejecutadas en CPU con un tamaño de pila de señales grande (por ejemplo, Intel Sapphire Rapids / Granite Rapids con un kernel compatible con AMX), en las que el tamaño de la pila alternativa de señales no se redondeaba al alza a un múltiplo del tamaño de página antes de llamar aaligned_alloc. #108813 (groeneai). - Se corrigió un error lógico
Block structure mismatch in JoinStep(interrupción del servidor en builds de depuración/sanitizador) cuando una subconsulta correlacionada se descorrelaciona en una unión y la relación de origen contiene un mismo nombre de columna más de una vez, p. ej.,WITH t AS (SELECT number, * FROM numbers(3)) SELECT *, (SELECT t.number WHERE t.number >= 0) FROM tconcorrelated_subqueries_default_join_kind = 'right'. #109114 (groeneai). - Se corrigió un problema por el que
CREATE USER ... HOST LIKE 'a', 'b'(y elALTER USERequivalente) conservaba silenciosamente solo el primer patrón. Ahora todos los patronesHOST LIKEespecificados se almacenan en la lista de hosts permitidos del usuario. #109187 (groeneai). - Se corrigió un resultado inesperado de
ANY JOINcon una condiciónONconstante (p. ej.,t1 ANY INNER JOIN t2 ON 1): la consulta devolvía el producto cartesiano completo en lugar del resultado de la unión ANY #109207 (vdimir). - Se corrigió un problema por el que el límite global
max_rows_in_join/max_bytes_in_joinno se aplicaba en el algoritmo de unión parallel_hash, de modo que una consulta conjoin_overflow_mode = 'throw'podía finalizar sin errores en lugar de generarSET_SIZE_LIMIT_EXCEEDED. #109488 (m-selmi). - Se corrigió una pérdida silenciosa de datos cuando un
INSERT ... VALUESdentro de un flujo de varias consultas va seguido de un comentario SQL final (por ejemplo,VALUES (1) -- comment) en la ruta de análisis de inserciones con datos en línea del lado del servidor (send_table_structure_on_insert_with_inline_data = 0). El comentario final se interpretaba como datos de fila más allá del;de terminación, lo que provocaba que las consultas siguientes del flujo se omitieran silenciosamente. #109643 (groeneai). - Se corrigió el
PREWHEREdiferido conoptimize_move_to_prewhere = 1cuandoPREWHEREse ejecuta después deFINAL: las condicionesWHEREya no se adelantan a una ROW POLICY diferida, lo que podía alterar los resultados de las consultas. #109703 (yariks5s). - Se corrigió un
LOGICAL_ERROR(query tree node does not have valid source node) que se producía cuando un CTE recursivo resolvía un identificador de un ámbito externo como columna correlacionada (conallow_experimental_correlated_subqueries = 1). Ahora estas consultas devuelven un errorUNSUPPORTED_METHODclaro. #109863 (groeneai). - Se corrigió un desbordamiento de entero con signo cuando
ORDER BY ... WITH FILLsalta un hueco muy grande en una columnaInt64/UInt64(p. ej., un paso de 2 a través de un hueco cercano a 2^63). El desbordamiento provocaba un comportamiento indefinido con sanitizadores y se truncaba silenciosamente en las builds de release. #109937 (groeneai). - Se corrigió un error lógico
Invalid number of rows in Chunkque se producía cuando el destino deINTERPOLATEes un alias de una columnaWITH FILLcon el analizador antiguo (enable_analyzer = 0). Ahora estas consultas se rechazan con un error claroINVALID_WITH_FILL_EXPRESSION. #110103 (groeneai). - Se corrige un error lógico (
Unexpected number of columns in result sample block) que se producía cuando un filtro que contiene una subconsulta correlacionada (por ejemplo,exists((SELECT ...))) se optimiza conconvert_query_to_cnfuoptimize_and_compare_chain. #110187 (alexey-milovidov). - Una subconsulta
EXISTScorrelacionada anidada que hace referencia a una columna de un ámbito situado más allá de su consulta externa inmediata (saltándose un ámbito intermedio) ahora falla con un error claroNOT_IMPLEMENTEDen lugar de un error internoNOT_FOUND_COLUMN_IN_BLOCK. #110310 (groeneai). - Se corrigieron resultados incorrectos de subconsultas escalares correlacionadas cuando la consulta externa tiene valores duplicados en la columna correlacionada y la subconsulta se descorrelaciona mediante la ruta de CROSS JOIN. Anteriormente, funciones de agregación como
count()ysum()se multiplicaban por el número de duplicados. Esto afecta a la funcionalidad experimentalallow_experimental_correlated_subqueries. #110311 (groeneai). - Se corrigió un problema por el que
ORDER BY ... WITH FILLno respetabamax_execution_timey tardaba en cancelarse al generar un rango de relleno grande (especialmente conINTERPOLATE). #110332 (alexey-milovidov). - La optimización diferida de
FINAL(query_plan_optimize_lazy_final, deshabilitada de forma predeterminada) ya no se aplica cuando la consulta lee en el orden de la clave de ordenación, ya que su plan de reemplazo no genera las filas en ese orden, mientras que el plan superior puede depender ya de él tras la optimización de lectura en orden, lo que podría dar lugar a resultados mal ordenados. Tampoco se aplica ya cuando unLIMITmenor que el número de filas a leer se aplica directamente al paso de lectura, en cuyo caso la pasada obligatoria de construcción del conjunto impediría la terminación anticipada. #110576 (KochetovNicolai). - El vaciado en segundo plano de una inserción asíncrona ahora se detiene de inmediato al terminarse con
KILL QUERY; antes, el vaciado de una carga grande almacenada temporalmente en el búfer seguía analizándose hasta el final e ignoraba la cancelación. #110652 (tiandiwonder). - Se corrigieron resultados incorrectos de
GROUP BY ... optimize_aggregation_in_orderyDISTINCT ... optimize_distinct_in_ordersituados sobre una uniónpartial_merge. La optimización de lectura en orden se propagaba a través dePartialMergeJoin, que reordena su entrada izquierda por la join key y, por tanto, no conserva el orden original del flujo izquierdo, por lo que las filas se agrupaban incorrectamente. #110671 (groeneai). - Se corrige un caso en el que, al usar alias de columna de CTE con consultas
INTERSECToEXCEPT(p. ej.,WITH t (a, b) AS (SELECT 1, 2 INTERSECT SELECT 1, 2) SELECT a, b FROM t), la consulta fallaba con el error UNKNOWN_IDENTIFIER. #110885 (yariks5s). - Se corrigió un
LOGICAL_ERROR: ReadBuffer is canceled. Can't read from it.que podía producirse en una unióngrace_hashcuando la lectura de bloques volcados a disco fallaba a mitad de proceso mientras varios hilos compartían el lector. #111056 (groeneai). - Corrige un error por el que la materialización de las columnas del lado derecho durante las *_hash JOINs utilizaba la zona horaria incorrecta. #111074 (yariks5s).
- Corrige las sentencias
CREATEcon una cláusulaCOMMENTpara que generen un error de sintaxis cuando falta el literal de cadena del comentario, en lugar de aceptar sin avisar una consulta mal analizada (p. ej.,CREATE VIEW v COMMENT AS SELECT 1ya no crea una vista sin comentario). #111159 (tiandiwonder). - Corrige un
LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) que se producía cuando una CTE materializada reutilizada (enable_materialized_cte) se leía en una rama cuya salidaWITH TOTALSoextremesse descarta, incluidas la agregación externa,INSERT ... SELECT, las operaciones de conjuntos yEXPLAIN ANALYZE. #111194 (groeneai). - Corrige que
join_algorithm = 'full_sorting_merge'rellenara las filas no unidas de unLEFT/RIGHT/FULL/ASOFJOINcon un cero literal en lugar del valor predeterminado del tipo de columna. En una columnaEnum(cuyo valor predeterminado es su primer elemento, no0), esto producía resultados incorrectos (un filtro sobre el valor de relleno descartaba las filas sin coincidencia, de modo que una unión externa se comportaba, sin avisar, como una interna) y un errorUNKNOWN_ELEMENT_OF_ENUMal seleccionar la columna. #111197 (groeneai). - Corrige resultados incorrectos de
SummingMergeTree(yCoalescingMergeTree) conFINALcuandooptimize_move_to_prewhere_if_final = 1y la cláusulaWHEREes una condición booleana implícita sobre una columna de la clave de ordenación (p. ej.,WHERE k). La columna clave se devolvía sumada entre las partes no fusionadas en lugar de conservarse intacta. #111342 (groeneai). - Corrige un error lógico (
Unexpected number of columns in result sample block) que podía producirse en unRIGHT/FULL JOINcuando el lado izquierdo contiene una columna duplicada con el mismo nombre (por ejemplo,1 AS b, 1 AS b) que persiste tras unUNION ALL. #111554 (groeneai). - Corrige un fallo del client al formatear una consulta
EXECUTE AScuyo AST tiene un hijo reemplazado (como hace el AST fuzzer).ASTExecuteAsQueryahora es propietario de sus hijostarget_userysubquery, en lugar de mantener punteros no propietarios a elementos dechildren. #111725 (groeneai). - Corrige resultados incorrectos cuando
query_plan_join_swap_tableintercambia unANY JOINconjoin_any_take_last_row = 1: ClickHouse ahora conserva el orden original de los lados de la unión para queANY JOINsiga devolviendo la última fila coincidente. #112458 (vdimir). - Corrige la excepción
Context has expiredal usargetClientHTTPHeaderdentro de una subconsulta. #112533 (alexey-milovidov). - Corrige resultados incorrectos en un
JOINcuya cláusulaONcontiene una condición mixta, es decir, una condición residual de no igualdad entre ambos lados, comoON (t1.key = t2.key) AND (t1.a * 10 < t2.a). Solo la familia de algoritmos hash evalúa este tipo de condición, perofull_sorting_merge,partial_mergey la unión directa clave-valor declaraban poder ejecutar estas uniones y luego ignoraban sin avisar la condición residual, con lo que devolvían filas de más. Ahora las rechazan y, en su lugar, se utiliza un algoritmo hash. #112831 (groeneai). - Se corrigieron resultados incorrectos en una unión por coma o
CROSScuyoWHEREcompara columnas de dos tablas mediante una expresión no determinista comorand. Una consulta de este tipo podía devolver filas que contradecían su propia cláusulaWHERE, ya que, al reescribir la unión como una uniónINNER, la expresión se trasladaba a la join key, donde se vuelve a evaluar para cada fila de cada lado. #112938 (groeneai). - Se corrigió una ralentización cuadrática al analizar una consulta PromQL con una larga secuencia final de caracteres no reconocidos (p. ej., un valor
FixedStringrellenado con bytes NUL): el análisis de una entrada no válida de un megabyte mantenía ocupado un hilo durante decenas de minutos y no se podía cancelar, porque se produce durante el análisis de la consulta. Ahora el analizador se detiene en el primer error. #112944 (alexey-milovidov). - Se corrigió que
intDivsobre una columna no constante con el divisor constante -1 desbordara silenciosamente la división del número con signo mínimo (p. ej.,intDiv(-9223372036854775808, -1)) en lugar de lanzar la excepciónILLEGAL_DIVISION, como hacen las demás rutas de ejecución. Este desbordamiento silencioso también podía producir resultados incorrectos enORDER BY/DISTINCT, porque la optimización de lectura en orden trata correctamenteintDivpor una constante negativa como monótona, y el valor desbordado rompía el orden resultante. #113048 (alexey-milovidov). - Se corrigió el error
UNKNOWN_IDENTIFIERconenable_analyzer = 0cuando unWHEREhace referencia a una columna generada poruntupledentro de una subconsulta, por ejemploSELECT t.keys FROM (SELECT untuple(arrayJoin(m)) AS t FROM ...) WHERE t.values > 0. La reescritura deenable_optimize_predicate_expressiontrasladaba dicho predicado a la subconsulta como unHAVING, donde el nombre todavía no existe. #113760 (groeneai). - Se corrigieron resultados incorrectos en
JOINconjoin_algorithm = 'partial_merge'cuando el lado derecho incluye totales: el lado derecho podía quedar sin fusionar, de modo que las unionesLEFTsustituían coincidencias reales por valores predeterminados y las unionesINNER/RIGHTno devolvían ninguna fila. En la ruta de filas no unidas deRIGHT/FULL, ese mismo estado desreferenciaba un puntero nulo, lo que provocaba la caída del servidor. #113936 (groeneai). - Se corrigieron resultados incorrectos en
SELECT DISTINCTcon unLIMITque debe leer toda su entrada:LIMIT n WITH TIESdescartaba filas empatadas,exact_rows_before_limit = 1devolvía unrows_before_limit_at_leasttruncado yGROUP BY ... WITH TOTALScalculaba la fila de totales a partir de solo una parte inicial del flujo. #114025 (groeneai). - Se corrigió un
LOGICAL_ERROR(«Unexpected number of kept output positions after removing unused columns fromReadFromMergeTree») que generaba unSELECT ... FINALcuyoPREWHEREusa una columna queFINALnecesita para la fusión (ver,is_deleted,sign) sin seleccionar dicha columna. #114746 (groeneai). - Se corrigió un problema de duración de vida en el vaciado de INSERT asíncronos, el procesamiento de vistas materializadas y
EXPLAIN ANALYZEque podía provocar el acceso a un estado de seguimiento de consultas ya expirado. #114940 (azat). - Se corrigió que
CREATE QUOTAyALTER QUOTAdescartaran silenciosamente todos los bloquesFOR INTERVALsalvo el último cuando se omitía la coma que separa los intervalos. La sentencia se ejecutaba sin errores, pero no aplicaba ninguno de los límites anteriores. Ahora los intervalos vuelven a acumularse, como ocurría antes de 2020. #115320 (groeneai). - Se corrigió que
randConstantdevolviera dos valores distintos en una misma consulta cuando sus llamadas tenían alias diferentes. Según la documentación,randConstantmantiene un único valor durante toda la consulta, ySELECT randConstant() = randConstant()ya devolvía1, pero al añadir alias, como enSELECT randConstant() AS a, randConstant() AS b, se obtenían dos valores sin relación entre sí. #115384 (alexey-milovidov). - Se corrigió que
SELECT count()no terminara nunca, o devolviera un número de filas inventado, al leer un archivoMsgPackoProtobufListcorrupto. La ruta optimizada deoptimize_count_from_filescontaba filas sin exigir que la posición de lectura avanzara, de modo que un archivoProtobufListde dos bytes generaba miles de millones de filas y la consulta nunca terminaba. Ahora este tipo de entrada se rechaza con el mismo error que produce la ruta de lectura ordinaria. #115884 (groeneai). - Se corrigió que
broken_data_filesensystem.distribution_queuey la métricaBrokenDistributedFilesToInsertindicaran siempre0: al escanear la cola de inserción asíncrona durante el inicio,DistributedAsyncInsertDirectoryQueue::initializeFilesFromDiskcontabilizaba los bytes dañados, pero nunca incrementaba el contador de archivos dañados. #92124 (squalfof).
Otras correcciones de errores
- Las consultas secundarias ejecutadas como parte de consultas internas ahora se registran como consultas internas. #108506 (mstetsyuk).
- Se corrige que una columna DEFAULT ausente en una parte se rellenara con el valor predeterminado del tipo en lugar de con la expresión DEFAULT cuando la condición PREWHERE se dividía en varios pasos de lectura. #111795 (yariks5s).
- Las cuotas con clave
normalized_query_hashahora contabilizan todos los recursos (read_rows,read_bytes,result_rows,result_bytes,execution_time,written_bytes,errors) por patrón de consulta, igual que los contadores de número de consultas, en lugar de imputarlos a un único bucket compartido por usuario. #107681 (alexey-milovidov). - Se corrige que
connect_timeouty los tiempos de espera de lectura y escritura de MySQL no surtieran efecto: un intento de conexión a un servidor MySQL que no respondía podía quedarse bloqueado más de dos minutos incluso conconnect_timeout = 1, porque las señales periódicas del perfilador de consultas por muestreo reiniciaban una y otra vez el plazo interno de sondeo del cliente de MySQL. #109592 (tiandiwonder). - Se corrige que el tiempo de espera de bloque de las inserciones en streaming (
input_format_max_block_wait_ms) pudiera no expirar nunca mientras el perfilador de consultas estaba activo: el sondeo del descriptor de archivo se reiniciaba con el tiempo de espera completo tras cada señal del perfilador, por lo que una fuente de entrada bloqueada podía retrasar indefinidamente el vaciado del bloque parcial en lugar de vaciarlo al alcanzar el límite de espera. #109602 (tiandiwonder). - Se corrige un
LOGICAL_ERROR(std::length_error) cuando una consulta con la configuración experimentalmake_distributed_plan = 1usaba un valor muy grande dedistributed_plan_default_reader_bucket_countodistributed_plan_default_shuffle_join_bucket_count. Ahora estos valores se rechazan conINVALID_SETTING_VALUE. #109770 (groeneai). - Se corrige
distinct_overflow_mode = 'break': DISTINCT ahora devuelve el resultado parcial acumulado hasta el límite y deja de leer la fuente, tal como indica la documentación. Antes, el fragmento que superabamax_rows_in_distinct/max_bytes_in_distinctse descartaba (lo que producía resultados truncados o vacíos) y la consulta seguía leyendo e insertando en el conjunto hash hasta el final de la entrada, lo que podía acabar enMEMORY_LIMIT_EXCEEDED. #110075 (skuznetsov-clickhouse). - Se corrige que
optimize_aggregation_in_orderignorara la cancelación de consultas.AggregatingInOrderTransformahora comprueba si se ha cancelado la consulta mientras agrega un fragmento, de modo que una consulta detenida medianteKILL QUERYo pormax_execution_time(con el valor predeterminadotimeout_overflow_mode = 'throw') se detiene de inmediato en lugar de procesar el fragmento entero hasta el final. #110104 (groeneai). - Se corrige una terminación abrupta del servidor (en compilaciones de depuración y con sanitizador) cuando un valor de una fuente PostgreSQL de la familia
mysql/postgresql/sqlitese leía en un tipo declarado al que no se puede convertir (por ejemplo, una columnatextdeclarada comoInt32). Ahora esta discrepancia de tipos se notifica como un error de consulta en lugar de detener el servidor. #110264 (groeneai). - Se corrige una terminación abrupta del servidor al analizar determinadas consultas PRQL (
SET dialect = 'prql'). Un pánico dentro del compiladorprqlcabortaba el proceso en lugar de notificarse como un error de consulta. #110316 (groeneai). - Se corrige
NOT_FOUND_COLUMN_IN_BLOCKcuando una política de filas yadditional_table_filtershacen referencia a una misma columna que la consulta no selecciona por ningún otro motivo. #111099 (groeneai). - Se corrigió un bloqueo en
randChiSquared,randStudentT,randFisherFyrandBinomialcon parámetros extremos. La consulta no podía interrumpirse mediantemax_execution_timeniKILL QUERY. Ahora estos parámetros se rechazan incluso cuandomax_rand_distribution_parameteromax_rand_distribution_trialsse establece en 0, ymax_rand_distribution_trialsya no puede aumentarse por encima de su valor predeterminado de 10^9 pararandBinomial. #111909 (alexey-milovidov). - Se corrige
connection_pool_max_wait_mspara que su valor documentado y predeterminado,0, signifique un tiempo de espera infinito. Una consulta que encontraba lleno el grupo de conexiones reintentaba en un bucle continuo, lo que consumía CPU y registrabaNo free connections in pool. Waiting 0 ms.en cada iteración. Ahora espera hasta que se devuelva una conexión al grupo. #112380 (groeneai). - Se corrige que
replaceOne,replaceAll,replaceRegexpOneyreplaceRegexpAllignoraranmax_execution_timeyKILL QUERY. Ahora cada llamada comprueba si se ha solicitado la cancelación mientras se ejecuta, de modo que un reemplazo de larga duración sobre un valor grande o un gran número de filas se detiene en lugar de ocupar un hilo del servidor hasta finalizar. Una llamada de este tipo no tiene un resultado parcial que devolver, por lo que contimeout_overflow_mode = 'break'notifica el vencimiento del plazo como un error: siempre que se evalúa como constante y, en la canalización, cuando este punto de control se alcanza antes de la comprobación entre bloques del ejecutor, que sigue deteniendo la consulta de forma silenciosa. #112483 (groeneai). - Se corrigió que
countSubstrings,countSubstringsCaseInsensitiveycountSubstringsCaseInsensitiveUTF8ignoraranKILL QUERYymax_execution_time: una llamada sobre muchas filas o con muchas coincidencias podía seguir ejecutándose durante minutos después de cancelar la consulta. #113369 (groeneai). - Se corrige un posible bloqueo de la consulta (durante
receive_timeoutsegundos) cuando esta finaliza muy rápidamente en el initiator. #113551 (nickitat). - Se corrige que
countMatchesycountMatchesCaseInsensitiveignoraranmax_execution_timeyKILL QUERYal contar las coincidencias de un único valor grande, lo que mantenía en ejecución durante minutos una consulta ya cancelada. Con un argumento constante, la llamada se produce durante el análisis de la consulta, por lo que no existe ninguna canalización que pueda cancelarla. #113886 (groeneai). - Una consulta podía cancelarse hasta 1 ms antes de que transcurriera su
max_execution_timey fallaba con el mensaje contradictorioTimeout exceeded: elapsed 999.672 ms, maximum: 1000 ms. #114559 (alexey-milovidov). - Se corrigió una lectura fuera de límites en
pointInPolygoncon un polígono constante cuyo cuadro delimitador no está acotado, por ejemplo, cuando una coordenada alcanza+-DBL_MAX. Ahora estos polígonos se rechazan conBAD_ARGUMENTS, y un polígono con un anillo vacío se trata como si no tuviera interior. Anteriormente, la consulta podía devolver un resultado incorrecto o provocar la terminación abrupta del servidor en compilaciones con hardening o sanitizadores habilitados. #115035 (groeneai). - Se corrige una condición de carrera que podía hacer que una consulta
STREAM BOUNDEDdevolviera menos filas de las que se habían confirmado (committed) antes de su inicio; normalmente, ninguna. #115543 (alexey-milovidov). - Se corrige el error
Unknown identifierque se producía durante la optimización del plan de consulta conmake_distributed_plan = 1cuando la columna de ordenación de una consulta con funciones de ventana pasa por un pasoExpressionque no la menciona. #115890 (groeneai). - Se corrigió que
h3kRing,h3HexRing,h3Lineyh3ToChildrenignoraranmax_execution_timeyKILL QUERYal expandir un bloque de filas. #115893 (alexey-milovidov). - Se corrige
NOT_FOUND_COLUMN_IN_BLOCKen el lector nativo de Parquet V3 (tras una regresión previa) cuando unPREWHEREtenía conjunciones que compartían una expresión intermedia común. #107059 (groeneai). - Se corrige un bloqueo indefinido al escribir Parquet con
output_format_parquet_parallel_encodinghabilitado (el valor predeterminado) ymax_threadsmayor que 1. Si el codificador no lograba programar un thread adicional, su contador de threads activos sufría un subdesbordamiento y la escritura podía quedarse detenida de forma permanente en lugar de finalizar o informar de un error. #112959 (groeneai). - Se corrigió una asignación de memoria ilimitada al leer un archivo Parquet cuya metadata Thrift declara una longitud de contenedor o de cadena mayor que la propia metadata. Ahora dicha longitud se rechaza en lugar de reservar memoria para ella. #113212 (groeneai).
- Se corrige una excepción
std::out_of_range(Logical error: 'std::exception. Code: 1001, type: std::out_of_range', que además aborta el servidor en compilaciones de depuración y con sanitizador) en el lector de Parquet v3 cuando una columna necesaria solo para evaluar el filtro se programaba para decodificarse después de que su slot de salida ya se hubiera eliminado. #113956 (groeneai). - Se corrigen carreras de datos en los profile events y en el rastreador de memoria. #112466 (mstetsyuk).
- Se corrige una posible carrera de datos en los profile events al usar la configuración
trace_profile_events_listpara escribir stack traces de determinados profile events ensystem.trace_log. #113553 (mstetsyuk). - Se corrigió que
intDivOrNull,moduloOrNullypositiveModuloOrNulldevolvieran0en lugar deNULL, y queintDivOrNulleintDivOrZerolanzaran una excepción en lugar de devolverNULL/0, cuando la división provoca una excepción de coma flotante (división por cero oINT_MIN / -1), también con argumentos mixtos con signo/sin signo. #101976 (yariks5s). - Se corrigió
IS DISTINCT FROMpara valoresArrayyMapcomparados conNULL. #103162 (ylw510). - Se corrigió
groupConcatcuando se combinan las sintaxis paramétrica y de dos argumentos, por ejemplogroupConcat(',', 2)(x, '/'): el parámetro de límite de filas se descartaba silenciosamente, por lo que se devolvían todas las filas en lugar del número solicitado; ahora el delimitador del segundo argumento sobrescribe correctamente el parámetro. #104882 (yariks5s). - Se corrigen errores al usar CAST de unidades de intervalo menores a mayores. #105058 (yariks5s).
- Se corrigió un error lógico (
Assertion 'row < chunk.getNumRows()' failed) en consultasLIMIT ... WITH TIESque se ejecutan con la canalización de lectura en orden (optimize_read_in_order = 1yread_in_order_use_virtual_row_per_block = 1). #105102 (groeneai). - Se corrigió
Logical error: 'Pipeline stuck'en consultas que usanenable_sharding_aggregator = 1junto con unUNION ALLy unmax_streams_for_union_stepmenor que el ancho de la canalización.BufferedShardByHashTransformahora finaliza los puertos de salida con la cola vacía en cuanto se agota su entrada, y sigue extrayendo datos de entrada cuando un puerto vacío solicitado no tiene nada que drenar, aunque una cola hermana haya alcanzado el límite de contrapresión. #106251 (groeneai). - Se corrigió que
removeDirectoryen discos de almacenamiento de objetosplain(comos3_plain) eliminara todos los archivos de un directorio no vacío como si se tratara de una eliminación recursiva. Ahora, intentar eliminar un directorio no vacío falla conCANNOT_RMDIR, y la eliminación recursiva gestiona el contenido de forma explícita. #106281 (RinChanNOWWW). - Se corrigió que las funciones definidas por el usuario
executable_poolconfiguradas con<lifetime>no detectaran los cambios en el script subyacente. Anteriormente, soloSYSTEM RELOAD FUNCTIONSvolvía a leer un script modificado; las recargas periódicas de<lifetime>seguían ejecutando la versión anterior. #107087 (groeneai). - Se corrigió una carrera de datos en el colector de trazas global del servidor entre un hilo de trabajo que iniciaba su profiler y el apagado del servidor. #107307 (groeneai).
- Se corrigió una interrupción poco frecuente del servidor durante el apagado (
std::future_error, “The associated promise has been destructed prior to the associated state becoming ready”) que se producía cuando una tarea programada mediantethreadPoolCallbackRunnerUnsafese descartaba de la cola del pool de hilos antes de ejecutarse. #107383 (groeneai). - Se corrigió un error lógico de
FileLog(Last stored last_written_position in meta file ... is bigger than current last_written_pos) que podía producirse cuando un archivo supervisado se eliminaba y se volvía a crear reutilizando el mismo inodo. #107617 (groeneai). - Se corrigió que
toTime64yCAST(... AS Time64)no ajustaran los valores fuera de rango al rango deTime64en los modos de desbordamientosaturateeignore, lo que podía dar lugar a valores que se mostraban igual pero que, al compararse, resultaban distintos. #108028 (alexey-milovidov). - Se corrigió el tratamiento incorrecto de las aserciones de ancho cero (
\b,^,$) en las funciones de expresión regular de tipo “match all”extractAll,extractAllGroupsVertical,extractAllGroupsHorizontal,countMatchesysplitByRegexp. Por ejemplo,extractAll('new york is the greatest', '\b(\w)')ahora devuelve correctamente la primera letra de cada palabra en lugar de todas las letras. #108047 (alexey-milovidov). - Se corrigieron resultados incorrectos al usar
hasTokenen índices de texto con un tokenizador distinto desplitByNonAlpha. #108066 (rschu1ze). - Se corrigió que
toStartOfIntervalydateTruncdevolvieran un valor redondeado en lugar del inicio del intervalo que lo contiene cuando la entrada tiene una precisión mayor que la unidad del intervalo; por ejemplo,toStartOfInterval(toDateTime64('2023-10-09 10:11:12.000999', 6), INTERVAL 1 millisecond)devolvía10:11:12.001en lugar de10:11:12.000. La sobrecarga con un origen explícito también se veía afectada. #108186 (yariks5s). - Se corrigieron
replaceRegexpOneyreplaceRegexpAllpara que.coincida con caracteres de nueva línea de forma predeterminada, en coherencia con otras funciones de expresiones regulares. #108265 (linjiayu1025-collab). - Se corrige que las condiciones de las operaciones ligeras UPDATE/DELETE se evaluaran dos veces. #108323 (ofeliacode).
- Se corrige
arrayPartialSort()con un argumento de límite no constante. #108327 (vitlibar). - Se corrigió que las funciones de expresiones regulares (
match,extract,extractAll,replaceRegexpOne,replaceRegexpAll, etc.) devolvieran resultados incorrectos sin avisar cuando el patrón contenía un byte NUL (\0). Ahora el NUL se trata como un byte literal ordinario, en coherencia con RE2. #108427 (alexey-milovidov). - Se corrige que
changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecondsobre un argumentoDateTime64(N)crearan la columna de resultado con la escala predeterminada fija (3) en lugar deN. Los valores se calculaban con escalaN, pero el objeto de columna declaraba escala 3, lo que lo dejaba estructuralmente incoherente con su tipo. #108551 (groeneai). - Se corrige un
LOGICAL_ERROR(“Trying to extract chunk from ChunkBuffer before all inputs are finished”) cuando una operación de conjuntos (INTERSECT/UNION ALL/EXCEPT) combina ramas que usan subconsultas correlacionadas ycorrelated_subqueries_default_join_kind = 'left'. #108554 (groeneai). - Se corrigieron errores de
DateTime64enchangeYear,changeMonth,changeDay,changeHour,changeMinuteychangeSecond: las entradas con precisión de nanosegundos (escala 9) ya no lanzanDECIMAL_OVERFLOW, y las entradas con fracciones de segundo anteriores a la época Unix ahora devuelven el segundo de calendario correcto. #108681 (takumihara). - Se evita una salida excesiva en el log del servidor y un mensaje de error desmesurado al compilar una expresión regular muy grande (por ejemplo, un patrón
LIKEomatchcon cientos de miles de comodines); ahora estos patrones fallan con un errorCANNOT_COMPILE_REGEXPclaro. #108821 (Algunenano). - Se corrige que
reinterpret(x, 'Decimal128(scale)')(y los tipos de destinoDecimal32/Decimal64/Decimal256/DateTime64) produjera una columna de resultado cuya escala interna era la de origen en lugar de la escala de destino solicitada cuando el origen y el destino tenían el mismo tipo físico. Los valores eran correctos, pero el objeto de columna era estructuralmente incoherente con su tipo declarado. #108878 (groeneai). - Se corrigió un comportamiento no definido al convertir a cadena un tipo de paquete de protocolo fuera de rango (p. ej., en los mensajes de error “Unexpected packet from server” / “Received … packet”) en una conexión desincronizada o sometida a fuzzing. #108885 (groeneai).
- Se corrige que
changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecondsobreDateTime64(N)construyeran la columna de resultado con la escala predeterminada fija de 3 en lugar deN, y quetimeSlotssobreDateTime64ignorara la escala del argumento opcionalSizeen su tipo de retorno declarado. En ambos casos se producía una columna cuya escala física no coincidía con su tipo declarado, lo que provocaba unLOGICAL_ERROR(writeSlice expects same column types) cuando el resultado se pasaba aarrayPushBack/arrayPushFront/arrayConcat; además,timeSlotscon la escala máxima enSizedevolvía marcas de tiempo incorrectas. #108994 (groeneai). - Se corrigen los incrementos no monótonos de ProfileEvents #109180 (azat).
- Se corrige que las proporciones de
SAMPLEcon un exponente cuya magnitud desbordaInt32(p. ej.,SAMPLE 1e-3000000000) se trataran silenciosamente comoSAMPLE 1. #109197 (Algunenano). - Se corrigieron dos errores en la ruta
DateTime64detoUTCTimestamp/fromUTCTimestamp(y sus aliasto_utc_timestamp/from_utc_timestamp) y detoTime64. El primero, un desbordamiento de entero con signo cerca del límite deInt64(ahora se calcula enInt128y se acota al rango representable). El segundo, un resultado incorrecto para valores fraccionarios negativos cerca de un límite de desplazamiento de zona horaria: la separación de los segundos truncaba hacia cero, por lo quetimezoneOffset()examinaba el segundo siguiente y podía situarse en el lado equivocado de un cambio de horario de verano o de desplazamiento. #109738 (groeneai). - Se corrigió un error lógico (
column->size() == num_rows) cuando la expresión de filtro de una política de filas usaarrayJoin; ahora estos filtros se rechazan. #109753 (Algunenano). - Se corrigió que
generateRandomStructure()generara ocasionalmente una cadena de estructura no válida con dos tipos de datos concatenados (por ejemplo,Decimal32(7)IPv4) cuando el anidamiento de tipos superaba el límite interno de profundidad, lo que impedía analizar el resultado. #109928 (groeneai). - Se corrigió la propagación de la configuración de la consulta en
accurateCastOrDefaulty la conservación de losNULLde origen codificados porDynamicyVariant. #109946 (Avogar). #114912 (alexey-milovidov). - Se corrigen
max_bytes_in_distinctymax_bytes_in_set: las claves de tipo cadena se almacenan en un arena que no se contabilizaba en las comprobaciones de límites, por lo que DISTINCT / IN sobre claves de tipo cadena podía retener memoria que superaba el límite de bytes en todo el volumen de las claves (sin cota en función de la longitud de la clave). Ahora los límites tienen en cuenta el arena, tal como indica su documentación; las consultas con claves de tipo cadena cercanas a un límite de bytes pueden alcanzarlo antes (como corresponde). #110120 (skuznetsov-clickhouse). - Se corrigió la lectura de archivos Npy con dimensiones internas de tamaño cero para que las filas materializadas y los resultados de
count()optimizados y no optimizados coincidan. #110146 (qiuyanjun888). - Se corrige un error lógico (aborto del servidor en builds de depuración/sanitizer) cuando las funciones
indexHint/ignore/isZeroOrNullreciben un argumento cuyo tipo se resuelve comoNothing, p. ej., dentro de expresiones comoindexHint(assumeNotNull(materialize(NULL))). #110192 (groeneai). - Se corrige la lectura de archivos en discos
plain_rewritabledespués de que una ruta existente se reescribiera con contenido de distinto tamaño: los metadatos en memoria conservaban el tamaño de archivo obsoleto, lo que podía hacer fallar las lecturas conUNEXPECTED_END_OF_FILE. #110304 (thevar1able). - Se rechazan los valores de
vector_search_index_fetch_multiplierinferiores a 1.0 para evitar resultados vacíos en búsquedas ANN cuando el número calculado de elementos a recuperar se trunca a cero. #110452 (tamish560). - Se corrige un error esporádico
Cannot parse string ... as UInt64 ... While executing ValuesBlockInputFormatque podía producirse al insertar valores cuyas expresiones contienen una conversión numérica comoinitializeAggregation('sumState', 0::UInt64). #110637 (groeneai). - Se corrige que
readWKTrechazara cadenas WKT con espacios en blanco iniciales (p. ej.,readWKT(' POINT(1 2)')), que sí aceptan los lectores tipadosreadWKTPoint/readWKTPolygon/… y la gramática WKT. #110706 (groeneai). - Se corrige un fallo del servidor (división entera por cero) al consumir una cuota con un intervalo de duración cero (por ejemplo, CREATE QUOTA q FOR INTERVAL 0 SECOND MAX queries = 1000). Ahora, al crear la cuota, se rechazan las duraciones de intervalo no positivas. #110846 (PedroTadim).
- Se corrige un fallo en builds FIPS al usar una clave SSH Ed25519 (
CREATE USER ... IDENTIFIED WITH ssh_key ... TYPE 'ssh-ed25519', o una clave de este tipo enusers.xml). Ed25519 no está aprobado por FIPS, por lo que ahora estas claves se rechazan con un errorLIBSSH_ERRORexplícito. #110891 (thevar1able). - Las funciones de distancia transpuestas sobre
QBit(cosineDistanceTransposed,L2DistanceTransposed,dotProductTransposed) ahora usan una reconstrucción acotada de baja precisión de un valor truncado aprecisionplanos de bits, en lugar de reconstruirlo en la arista inferior de la celda gruesa (con los bits descartados rellenados con ceros). El relleno con ceros sesgaba todos los valores reconstruidos hacia cero y resultaba degenerado con baja precisión: paraQBit(BFloat16)con precisión 1 solo se conserva el bit de signo, por lo que todos los valores se reconstruían como±0.0y la distancia era la misma constante para todas las filas, sin aportar ninguna información de ordenación. Ahora la reconstrucción depende de qué bits se descartan: los códigosInt8sin procesar se reconstruyen en el centro de su celda (en línea con la reconstrucciónLloyd-Maxque ya usaba la ruta...TransposedQuantized); un valor de coma flotante con precisión 1 se convierte en una cuantización de signo propiamente dicha; un valor de coma flotante que conserva todo su exponente y descarta solo bits de la mantisa se reconstruye en el punto medio acotado dentro de su propia binada (mientras que un cero real o±0.0se mantiene exactamente en cero y la celda no finita se trata aparte para que±infsiga siendo exactamente infinito; véase la nota siguiente sobre la celda ambigua deNaN); y mientras aún se truncan bits del exponente se mantiene la arista inferior acotada, de modo que unaprecisionmenor sacrifica exactitud a cambio de velocidad sin inflar una magnitud en varios órdenes. Los resultados de precisión completa no cambian. #110911 (alexey-milovidov). - Se corrige una lectura fuera de rango en el lector ORC nativo durante la inferencia de esquema de un archivo ORC corrupto cuyo árbol de tipos declara más columnas que codificaciones de columna hay en el pie de la franja. Ahora se rechaza con
CANNOT_EXTRACT_TABLE_STRUCTUREen lugar de abortar el servidor en builds de depuración o con sanitizador. #110967 (groeneai). - Ahora cada clave SSH cuenta de forma individual para el límite
max_authentication_methods_per_user, de modo que el límite se aplica de forma coherente independientemente de la sintaxis. Anteriormente, varias claves en un único métodossh_keycontaban como una sola. #111181 (TheMC47). - Los catálogos REST de Iceberg ahora notifican las credenciales caducadas junto con el error subyacente, en lugar de devolver silenciosamente
UNKNOWN_TABLE. #111379 (alesapin). - Se corrige que
readWKTPoint/readWKTdevolvieran coordenadas sin inicializar (escalar) o de la fila anterior (vectorizado) para un punto vacío con etiqueta de dimensión, comoPOINT M EMPTY. Estas entradas ahora se rechazan conCANNOT_PARSE_TEXT, de forma coherente conPOINT EMPTY. #111517 (groeneai). - La creación de estadísticas
minmaxahora emite una advertencia en lugar de lanzar una excepción. #111785 (hanfei1991). randBinomialsigue pudiendo usarse con las probabilidades degeneradas0y1para cualquier número de ensayos. #112021 (alexey-milovidov).- Se corrige que
system.s3_queue_settingsmostrara valores incorrectos parabucketing_mode,partitioning_mode,partition_regexypartition_component. #112300 (bharatnc). - Ahora se indica la posición correcta de los errores en las consultas PromQL. #112494 (fallintoplace).
SYSTEM DISABLE FAILPOINTahora rechaza los nombres de fail point inexistentes y generaBAD_ARGUMENTS, como ya hacíaSYSTEM ENABLE FAILPOINT. Anteriormente, un nombre mal escrito devolvía un resultado correcto pero dejaba habilitado el fail point en cuestión, sin ninguna indicación de que no se había deshabilitado nada. #112680 (groeneai).- Se corrige una lectura con tipo incorrecto de una subcolumna de elemento
Nestedcuya columna se había eliminado y vuelto a añadir. Al seleccionar dicha subcolumna junto con su propia columna principal, se devolvía el elemento completo en la posición de la subcolumna mientras el bloque seguía declarando el tipo del elemento, lo que producía valores arbitrarios en las builds de release y un error lógico en las builds de depuración y con sanitizador. #112769 (groeneai). - Se rechazan las duraciones de PromQL cuyas unidades están repetidas o no están ordenadas de mayor a menor. #112954 (fallintoplace).
- Se corrige un comportamiento no definido (puntero nulo pasado a
memcpy) enreplaceRegexpOne/replaceRegexpAllcuando la cadena de reemplazo sustituye un grupo de captura que no participó en la coincidencia, p. ej.,replaceRegexpAll('abc', '(a)|(b)', '\\2'). #113012 (alexey-milovidov). - Se corrige una incompatibilidad por la que los índices de texto creados en ClickHouse 26.3 con el tokenizador
unicode_wordno podían cargarse en versiones posteriores #113061 (rschu1ze). - Se rechazan los puntos de código sustitutos de Unicode no válidos en las secuencias de escape de cadenas de PromQL. #113203 (fallintoplace).
- Se rechazan las secuencias de escape entre delimitadores no válidas en las cadenas de PromQL. #113587 (fallintoplace).
- Se corrige
theilsUsobre una trama de ventana, que devolvía un valor arbitrario en lugar de 0 cuando el primer argumento era constante dentro de la trama. #113691 (alexey-milovidov). - Se corrigió el código de error notificado para algunas columnas mal formadas serializadas con
Replicatedy recibidas a través del protocolo nativo: ahora se rechazan conINCORRECT_DATAen lugar deLOGICAL_ERROR(que abortaba el servidor en compilaciones de depuración y con sanitizador). #114186 (Avogar). - Se corrigen los literales
Time64y las constantes de listasINincorrectos, a menudo con el signo invertido, que se generaban cuando el reescalado de unDecimal64de menor escala desbordabaInt64. Ahora dicha conversión notificaDECIMAL_OVERFLOW, en consonancia con la rama deDateTime64y conCASTexplícito. #114546 (groeneai). - Se admiten nombres de métricas y etiquetas entre comillas en los selectores de PromQL. #114551 (fallintoplace).
- Se corrigió un problema por el que las tablas
ReplicatedMergeTreepermanecían indefinidamente en modo de solo lectura tras un intento fallido de inicio ejecutado a través del hilo de adjunción. El reintento de reinicio ahora se programa correctamente, lo que restablece la recuperación automática y sus comprobaciones de sesión. #114802 (azat). timeSeriesRangeytimeSeriesFromGridlanzaban un falsoDECIMAL_OVERFLOWpara marcas de tiempo anteriores a 1970 porque las marcas de tiempo de inicio y fin se leían como valores sin signo. Además, para marcas de tiempoDateTime/UInt32, el paso se truncaba silenciosamente a sus 32 bits inferiores. Ahora todos los cálculos se realizan enInt64. #114815 (vitlibar).- Se corrigió una posible excepción en las inserciones asíncronas después de que una consulta fallara con
MEMORY_LIMIT_EXCEEDED, y se corrigióasync_insert_queue_flush_on_shutdownpara que las inserciones en cola se vacíen durante el apagado del servidor. #114839 (azat). - Se corrigió una excepción
out_of_rangelanzada como error internoCode: 1001cuando un patrón desequenceMatch,sequenceCountosequenceMatchEventscontenía el número de evento0, por ejemplosequenceMatch('(?0)'). Ahora dicho patrón se rechaza conBAD_ARGUMENTS. Una condición temporal que contenía únicamente un signo, comosequenceMatch('(?1)(?t>+)(?2)'), se trataba silenciosamente como(?t>0)y ahora se rechaza conSYNTAX_ERROR. #115056 (groeneai). - Se corrigió el mensaje de error de
geoToH3, que indicaba una posición de argumento y un tipo incorrectos cuando una coordenada no eraFloat64. Con el valor predeterminadogeotoh3_argument_order = 'lat_lon', el mensaje hacía referencia al otro argumento y mostraba el tipo de este. #115503 (groeneai). - Se corrigen caracteres de escape con barra invertida no válidos en los índices text, tokenbf_v1 y ngrambf_v1. #115634 (ahmadov).
- Se corrige un problema por el que el servidor no podía iniciarse cuando la variable de entorno
TZestaba vacía. #68921 (ardenwick).