Problemas comunes y sus soluciones al usar Lindorm SQL con LindormTable (motor de tablas anchas).
Todos los problemas descritos en esta página aplican únicamente a LindormTable.
Problemas de consulta
-
P: ¿Cómo resuelvo o evito las consultas ineficientes?
R: Si su consulta devuelve el error
This query may be a full table scan and thus may have unpredictable performance, se considera una consulta ineficiente.¿Qué es una consulta ineficiente? En LindormTable, una consulta cuyas condiciones de filtro no aprovechan de forma eficaz la clave principal ni un índice existente obliga al sistema a hacer un escaneo completo de la tabla. Estas consultas se consideran ineficientes. LindormTable las bloquea de manera predeterminada para proteger el rendimiento y la estabilidad de la base de datos.
Las reglas de coincidencia siguen la regla del prefijo más a la izquierda, la misma que utiliza MySQL para los índices compuestos. El sistema compara las columnas de la cláusula WHERE con las columnas de la clave principal (o del índice) comenzando por la columna situada más a la izquierda. Si la consulta omite la primera columna, no se usa la clave y se produce un escaneo completo de la tabla.
Por ejemplo, si la tabla
testtiene una clave principal compuesta (p1,p2,p3) y usted ejecuta lo siguiente:SELECT * FROM test WHERE p2 < 30;La consulta omite
p1, por lo que LindormTable no puede usar la clave principal. Se escanea toda la tabla para satisfacer la condiciónp2 < 30.Para corregir o evitar este problema:
Incluya la primera columna de la clave principal en la cláusula WHERE, siguiendo la regla del prefijo más a la izquierda.
Rediseñe la clave principal de la tabla. Consulte How to design a primary key for a wide table.
Cree un índice secundario en las columnas que consulta. Consulte Secondary indexes.
Si necesita consultas multidimensionales en varias columnas, cree un índice de búsqueda. Consulte Search indexes.
-
Para forzar la ejecución de la consulta ineficiente, agregue el hint
/*+ _l_allow_filtering_ */:SELECT /*+ _l_allow_filtering_ */ * FROM dt WHERE nonPK = 100;
ImportanteForzar un escaneo completo de la tabla puede degradar el rendimiento general y la estabilidad de la base de datos. Utilice este enfoque solo después de evaluar su impacto.
-
P: ¿Por qué falla una consulta GROUP BY con el error "subPlan groupby keys"?
R: Mensaje de error:
The diff group keys of subPlan is over lindorm.aggregate.subplan.groupby.keys.limit=..., it may cost a lot memory so we shutdown this SubPlanLa operación GROUP BY generó demasiados grupos. Una cantidad elevada de grupos consume memoria en exceso y aumenta la carga de la instancia, por lo que LindormTable detiene el subplan.
Para resolver este problema:
Agregue condiciones de filtro para reducir la cantidad de grupos antes de la agregación.
En escenarios de agregación multidimensional, cree un índice de búsqueda para delegar el trabajo. Consulte Search indexes.
Si necesita aumentar el umbral de cantidad de grupos, comuníquese con el soporte técnico de Lindorm (ID de DingTalk: s0s3eg3).
ImportanteAumentar el umbral de cantidad de grupos incrementa el consumo de memoria y puede afectar la estabilidad de la instancia. Evalúe el impacto antes de aplicar cambios.
-
**P: ¿Por qué falla
SELECT *en una tabla de columnas dinámicas con el error "Limit not set"?**R: Mensaje de error:
Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=trueLas tablas con columnas dinámicas no tienen un esquema fijo y pueden contener una cantidad grande e impredecible de columnas. Ejecutar
SELECT *sin un límite de filas provoca un alto nivel de E/S y aumenta la carga de la instancia. Por ello, LindormTable exige una cláusula LIMIT en estas consultas.Agregue una cláusula LIMIT a la instrucción SELECT:
SELECT * FROM test LIMIT 10; -
P: ¿Por qué falla una consulta con el error "Code grows beyond 64 KB"?
R: El motor Lindorm SQL utiliza compilación Just-In-Time (JIT): genera código de bytes a partir del plan físico de la consulta y lo compila en tiempo de ejecución. Este error indica que el código de bytes de un método generado supera el límite de 64 KB impuesto por la máquina virtual de Java (JVM).
La causa más común es un predicado demasiado largo o complejo en la instrucción SQL, lo que genera un código de bytes demasiado grande para ejecutarse.
Simplifique las expresiones de predicado en la instrucción SQL. Divida las condiciones complejas en partes más pequeñas o reescriba la lógica para reducir el tamaño del código de bytes.
-
P: ¿Por qué falla una consulta con el error "The estimated memory used by the query exceeds the maximum limit"?
R: El motor SQL consume mucha memoria al procesar conjuntos de resultados durante la agregación, la ordenación o la deduplicación. Como Lindorm SQL está diseñado para cargas de trabajo en línea de alta concurrencia, limita cada consulta a 8 MB de memoria de manera predeterminada. Superar este límite desencadena una excepción de desbordamiento de memoria.
Paso 1: diagnostique antes de actuar:
Revise el plan de ejecución para determinar si los operadores de agregación y ordenación se delegan al motor de almacenamiento o se ejecutan en el motor SQL. Consulte Interpret an execution plan.
Si los operadores pesados se ejecutan en el motor SQL, la solución adecuada es optimizar la consulta (consulte la Opción 1).
Si los operadores ya se delegaron y la consulta está optimizada, aumente el límite de memoria (consulte la Opción 2).
Opción 1: optimizar la consulta (recomendada):
Delegue la agregación y la ordenación al motor de almacenamiento mediante índices. Además, ajuste las condiciones de filtro para reducir la cantidad de datos que procesa el motor SQL.
Opción 2: aumentar el límite de memoria:
Si la consulta ya está optimizada y necesita un límite mayor, ajuste
QUERY_MAX_MEMcon ALTER SYSTEM:ALTER SYSTEM SET QUERY_MAX_MEM = 8388608;Consulte el valor actual con la instrucción SHOW VARIABLES.
Si su SQL engine version es anterior a la versión 2.9.6.0, comuníquese con el soporte técnico de Lindorm (ID de DingTalk: s0s3eg3) para aumentar el límite.
ImportanteEn entornos de alta concurrencia, aumentar
QUERY_MAX_MEMincrementa la presión de memoria sobre el clúster y puede provocar un Full GC forzado, lo que reduce la capacidad de respuesta de todo el clúster. Evalúe cuidadosamente el throughput y la concurrencia de las consultas antes de aumentar este valor. -
**P: ¿Por qué no se recomienda usar muchas condiciones
IS NULLen una sola cláusula WHERE?**R: En LindormTable,
IS NULLdebe manejar dos casos: "la columna existe con un valor NULL" y "la columna no existe o nunca se escribió". Cuando una instrucción SQL contiene varios predicadosIS NULL, el motor SQL puede expandir estas condiciones en combinaciones durante la compilación. N predicadosIS NULLpueden generar teóricamente hasta2^Nramas, lo que aumenta significativamente el tiempo de compilación y el uso de memoria. En casos graves, esto afecta la ejecución de la consulta y la estabilidad de la instancia.Recomendación: Evite combinar muchas condiciones
column IS NULLen una sola instrucción SELECT, UPDATE o DELETE. Considere los siguientes enfoques:Siempre que sea posible, reduzca el rango de la consulta mediante claves principales, índices secundarios o índices de búsqueda.
Si su lógica de negocio comprueba con frecuencia si los campos están vacíos o presentes, exprese ese estado de forma explícita durante la escritura; por ejemplo, con valores predeterminados o columnas de estado.
Para el procesamiento por lotes, divida el trabajo en varias instrucciones SQL con condiciones más simples. Otra opción es obtener primero todas las claves principales y procesarlas por lotes según dichas claves.
-
P: ¿Por qué no se recomienda usar muchos grupos OR combinados con AND en una cláusula WHERE?
Problema: Una instrucción SQL cuya cláusula WHERE conecta varios grupos OR entre paréntesis mediante AND. Por ejemplo:
SELECT * FROM orders WHERE (status = 1 OR status = 2) AND (pay_type = 'wechat' OR pay_type = 'alipay') AND (region = 'CN' OR region = 'US') AND ...;Cuanto mayor sea el nivel de anidamiento, mayor será el riesgo. Esto aplica tanto a las instrucciones SELECT como a las UPDATE y DELETE.
R: Antes de ejecutar una consulta, el optimizador debe convertir la cláusula WHERE a la Forma Normal Disyuntiva (DNF), es decir, un conjunto de condiciones AND unidas por OR. Así puede seleccionar la ruta de acceso óptima al índice para cada condición independiente. Cuando el optimizador encuentra
(A OR B) AND (C OR D), debe aplicar la ley distributiva para expandirla:(A∨B)∧(C∨D) ⇒ (A∧C)∨(A∧D)∨(B∧C)∨(B∧D)(A or B) and (C or D) ⇒ (A and C) or (A and D) or (B and C) or (B and D)2 grupos, cada uno con 2 ramas: 2×2 = 4 términos de combinación.
3 grupos, cada uno con 2 ramas: 2×2×2 = 8 términos de combinación.
A medida que crece la cantidad de grupos y de ramas por grupo, los términos de combinación aumentan de forma exponencial. Esto incrementa considerablemente el tiempo de compilación del optimizador y el uso de memoria. En casos graves, puede afectar la ejecución de la consulta y la estabilidad de la instancia.
Recomendación:
Evite combinar muchos grupos OR entre paréntesis con AND en una sola instrucción SQL.
Reescriba las condiciones OR de la misma columna con
IN(por ejemplo,status IN (1, 2)) para reducir la cantidad de ramas expandidas.Siempre que sea posible, reduzca el rango de la consulta mediante claves principales, índices secundarios o índices de búsqueda.
En escenarios de coincidencia multidimensional, utilice un índice de búsqueda. Consulte Search indexes.
Si la lógica de negocio requiere condiciones complejas, divida el trabajo en varias instrucciones SQL más simples. También puede obtener primero todas las claves principales y procesarlas por lotes según dichas claves.
-
P: ¿Cómo diagnostico y resuelvo un error de límite de memoria en una consulta específica?
R: Cuando una consulta falla con el error de límite de memoria, siga estos pasos para diagnosticar la causa raíz y elegir la solución adecuada:
Paso 1: revise el plan de ejecución:
Ejecute
EXPLAINen la consulta que falló para ver su plan de ejecución. Consulte Interpret an execution plan para obtener más detalles.En el plan de ejecución, identifique si los operadores que consumen mucha memoria (como agregación, ordenación y deduplicación) se ejecutan en el motor SQL o se delegan al motor de almacenamiento. Los operadores que se ejecutan en el motor SQL consumen memoria del límite asignado a cada consulta, mientras que los delegados utilizan recursos del motor de almacenamiento.
Paso 2: intente optimizar la consulta:
Si los operadores que consumen mucha memoria se ejecutan en el motor SQL, aplique los siguientes enfoques para reducir el consumo de memoria:
Para los operadores de agregación (
GROUP BY,COUNT,SUM,AVG): Cree un índice secundario o search index en las columnas agrupadas o agregadas para permitir que el operador se delegue al motor de almacenamiento.Para los operadores de ordenación (
ORDER BY): Asegúrese de que las columnas de ordenación coincidan con un índice existente para evitar la ordenación en memoria. Como alternativa, agregue condicionesWHEREmás estrictas para reducir el tamaño del conjunto de datos antes de ordenarlo.Para los operadores de deduplicación (
DISTINCT): Utilice un índice de búsqueda en consultas sobre columnas de alta cardinalidad, o agregue condiciones de filtro selectivas para reducir la cantidad de filas procesadas.
Paso 3: aumente el límite de memoria si es necesario:
Si todos los operadores ya se delegaron y la consulta no se puede optimizar más, aumente el valor de
QUERY_MAX_MEMcon ALTER SYSTEM:ALTER SYSTEM SET QUERY_MAX_MEM = <new_value_in_bytes>;Consulte el valor actual con la instrucción SHOW VARIABLES.
ImportanteEn entornos de alta concurrencia, un valor mayor de
QUERY_MAX_MEMincrementa la presión de memoria general del clúster y puede provocar un Full GC forzado, lo que reduce la capacidad de respuesta de todo el clúster. Evalúe el throughput y la concurrencia de sus consultas antes de cambiar este valor.
Problemas de índices y esquemas
-
P: ¿Por qué falla la creación de un índice secundario con el error "Executing job number exceed, max job number = 8"?
R: Cada instancia de Lindorm admite un máximo de 8 tareas simultáneas de construcción de índices secundarios. Si ya hay 8 tareas en ejecución, los nuevos intentos de creación de índices fallarán.
Evite crear muchos índices secundarios al mismo tiempo. Si necesita crear una gran cantidad de índices de forma masiva, comuníquese con el soporte técnico de Lindorm (ID de DingTalk: s0s3eg3).
-
P: Después de eliminar una columna, ¿por qué falla al volver a agregar una columna con el mismo nombre con el error "column is under deleting"?
R: Tras eliminar una columna, LindormTable limpia de forma asíncrona los datos de esa columna en la memoria, el almacenamiento activo y el almacenamiento frío. El sistema impide volver a agregar una columna con el mismo nombre hasta que finaliza la limpieza, con el fin de evitar datos inconsistentes causados por discrepancias de tipo o colisiones de datos.
La limpieza se ejecuta en segundo plano y puede tardar mucho tiempo. Para acelerarla, ejecute las siguientes instrucciones en la tabla (reemplace
dtpor el nombre de su tabla):-- Flush residual in-memory data to storage. ALTER TABLE dt FLUSH; -- Run compaction to merge and remove deleted data. ALTER TABLE dt COMPACT;Una vez completada la limpieza, vuelva a agregar la columna.
ImportanteFLUSHes compatible a partir de la versión 2.7.1 del motor SQL. Compruebe su versión en SQL version guide.Tanto
FLUSHcomoCOMPACTson operaciones asíncronas. Que la instrucción se ejecute correctamente no significa que la limpieza haya terminado.Ejecutar
COMPACTen una tabla con un gran volumen de datos consume muchos recursos del sistema. Evite ejecutarlo durante las horas pico del negocio.
-
P: Después de crear un índice secundario, ¿por qué falla la escritura de datos con un error "User-Defined-Timestamp"?
R: Mensaje de error:
Performing put operations with User-Defined-Timestamp in indexed column on MULTABLE_LATEST table is unsupportedCuando escribe datos con una marca de tiempo personalizada explícita (por ejemplo, usando el hint
/*+ _l_ts */en una instrucción UPSERT), tanto la tabla principal como la tabla del índice secundario deben tener la mutabilidad configurada enMUTABLE_ALL. Sin embargo, por motivos de rendimiento, Lindorm configura las nuevas tablas e índices enMUTABLE_LATESTde manera predeterminada. Escribir con una marca de tiempo personalizada en una tabla de índice con mutabilidadMUTABLE_LATESTdesencadena este error.La propiedad MUTABILITY no se puede modificar después de crear la tabla de índice. Debe eliminar el índice existente, actualizar la mutabilidad de la tabla principal y luego volver a crear el índice.
-
Deshabilite y elimine el índice secundario existente:
-- Disable the index. ALTER INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name> DISABLED; -- Drop the index. DROP INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name>;Consulte Delete a secondary index.
-
Establezca la mutabilidad de la tabla principal en
MUTABLE_ALL:ALTER TABLE IF EXISTS <primary_table_name> SET MUTABILITY='MUTABLE_ALL'; Cree un nuevo índice secundario. Consulte CREATE INDEX.
NotaPara obtener información sobre cómo escribir datos con una marca de tiempo personalizada, consulte Use HINTs to set timestamps for multi-version data management.
NotaPara conocer cómo interactúa la mutabilidad del índice secundario con las marcas de tiempo personalizadas, consulte Update an index with a custom timestamp.
-
Operaciones por lotes
-
P: ¿Por qué no se admiten las actualizaciones por lotes o por qué aparece el error "Update's WHERE clause can only contain PK columns"?
R: De manera predeterminada, solo se admiten las actualizaciones de una sola fila. Para saber cómo habilitar las actualizaciones por lotes, consulte Batch operations FAQ.
-
P: ¿Cómo habilito las eliminaciones por lotes?
R: Para saber cómo habilitar y configurar las eliminaciones por lotes, consulte Batch operations FAQ.