Problemas comuns e soluções para o uso de Lindorm SQL com LindormTable (mecanismo de tabela ampla).
Todos os problemas descritos nesta página aplicam-se exclusivamente ao LindormTable.
Problemas de consulta
-
P: Como resolver ou evitar consultas ineficientes?
R: Se sua consulta retornar o erro
This query may be a full table scan and thus may have unpredictable performance, ela será considerada ineficiente.O que é uma consulta ineficiente? No LindormTable, consultas com condições de filtro que não utilizam eficazmente a chave primária ou um índice existente forçam uma varredura completa da tabela. O sistema classifica essas consultas como ineficientes e as bloqueia por padrão para proteger o desempenho e a estabilidade do banco de dados.
As regras de correspondência seguem a regra do prefixo mais à esquerda, mesma lógica usada pelo MySQL para índices compostos. O sistema compara as colunas da cláusula WHERE com as colunas da chave primária (ou chave de índice), iniciando pela coluna mais à esquerda. Se a consulta ignorar a primeira coluna, a chave não será utilizada e ocorrerá uma varredura completa da tabela.
Por exemplo, se a tabela
testtiver uma chave primária composta (p1,p2,p3) e você executar:SELECT * FROM test WHERE p2 < 30;A consulta ignora
p1, impedindo o uso da chave primária pelo LindormTable. O sistema varre toda a tabela para satisfazer a condiçãop2 < 30.Para corrigir ou evitar esse problema:
Inclua a primeira coluna da chave primária na cláusula WHERE, seguindo a regra do prefixo mais à esquerda.
Redesenhe a chave primária da tabela. Consulte Como projetar uma chave primária para uma tabela ampla.
Crie um índice secundário nas colunas consultadas. Consulte Índices secundários.
Para consultas multidimensionais em várias colunas, crie um índice de pesquisa. Consulte Índices de pesquisa.
-
Para forçar a execução da consulta ineficiente, adicione a dica
/*+ _l_allow_filtering_ */:SELECT /*+ _l_allow_filtering_ */ * FROM dt WHERE nonPK = 100;
ImportanteForçar uma varredura completa da tabela pode degradar o desempenho geral e a estabilidade do banco de dados. Utilize essa abordagem apenas após avaliar o impacto.
-
P: Por que uma consulta GROUP BY falha com o erro "subPlan groupby keys"?
R: Mensagem de erro:
The diff group keys of subPlan is over lindorm.aggregate.subplan.groupby.keys.limit=..., it may cost a lot memory so we shutdown this SubPlanA operação GROUP BY gerou grupos em excesso. Um grande número de grupos consome memória excessiva e aumenta a carga da instância, levando o LindormTable a encerrar o subplano.
Para resolver este problema:
Adicione condições de filtro para reduzir a quantidade de grupos antes da agregação.
Em cenários de agregação multidimensional, crie um índice de pesquisa para descarregar o processamento. Consulte Índices de pesquisa.
Para aumentar o limiar de contagem de grupos, entre em contato com o suporte técnico do Lindorm (ID do DingTalk: s0s3eg3).
ImportanteElevar o limiar de contagem de grupos aumenta o consumo de memória e pode afetar a estabilidade da instância. Avalie o impacto antes de fazer alterações.
-
**P: Por que o comando
SELECT *em uma tabela de colunas dinâmicas falha com o erro "Limit not set"?**R: Mensagem de erro:
Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=trueTabelas com colunas dinâmicas não possuem esquema fixo e podem conter uma quantidade grande e imprevisível de colunas. Executar
SELECT *sem limite de linhas causa alta E/S e aumenta a carga da instância; portanto, o LindormTable exige uma cláusula LIMIT nessas consultas.Adicione uma cláusula LIMIT à instrução SELECT:
SELECT * FROM test LIMIT 10; -
P: Por que uma consulta falha com "Code grows beyond 64 KB"?
R: O mecanismo Lindorm SQL utiliza compilação Just-In-Time (JIT): ele gera bytecode a partir do plano físico da consulta e o compila em tempo de execução. Esse erro indica que o bytecode de um método gerado excede o limite de 64 KB imposto pela Java Virtual Machine (JVM).
A causa mais comum é um predicado excessivamente longo ou complexo na instrução de consulta SQL, resultando em um bytecode grande demais para execução.
Simplifique as expressões de predicado na instrução SQL. Divida condições complexas em partes menores ou reescreva a lógica para reduzir o tamanho do bytecode.
-
P: Por que uma consulta falha com "The estimated memory used by the query exceeds the maximum limit"?
R: O mecanismo SQL consome muita memória ao processar conjuntos de resultados durante agregação, ordenação ou deduplicação. Como o Lindorm SQL foi projetado para cargas de trabalho online de alta concorrência, ele limita cada consulta a 8 MB de memória por padrão. Exceder esse limite aciona uma exceção de estouro de memória.
Etapa 1 — Diagnosticar antes de agir:
Verifique o plano de execução para determinar se os operadores de agregação e ordenação foram transferidos para o mecanismo de armazenamento ou se são executados no mecanismo SQL. Consulte Interpretar um plano de execução.
Se operadores pesados forem executados no mecanismo SQL, otimize a consulta (consulte Opção 1).
Se os operadores já tiverem sido transferidos e a consulta estiver otimizada, aumente o limite de memória (consulte Opção 2).
Opção 1 — Otimizar a consulta (preferencial):
Transfira a agregação e a ordenação para o mecanismo de armazenamento usando índices e restrinja as condições de filtro para reduzir a quantidade de dados processados pelo mecanismo SQL.
Opção 2 — Aumentar o limite de memória:
Se a consulta já estiver otimizada e você precisar de um limite maior, ajuste
QUERY_MAX_MEMusando ALTER SYSTEM:ALTER SYSTEM SET QUERY_MAX_MEM = 8388608;Verifique o valor atual com a instrução SHOW VARIABLES.
Se a sua versão do mecanismo SQL for anterior à 2.9.6.0, entre em contato com o suporte técnico do Lindorm (ID do DingTalk: s0s3eg3) para aumentar o limite.
ImportanteEm ambientes de alta concorrência, aumentar
QUERY_MAX_MEMeleva a pressão de memória no cluster e pode acionar um Full GC forçado, reduzindo a capacidade de resposta de todo o cluster. Avalie cuidadosamente o throughput e a concorrência das consultas antes de aumentar esse valor. -
**P: Por que não é recomendado usar muitas condições
IS NULLem uma única cláusula WHERE?**R: No LindormTable,
IS NULLprecisa lidar tanto com "a coluna existe com valor NULL" quanto com "a coluna não existe ou nunca foi escrita". Quando uma instrução SQL contém múltiplos predicadosIS NULL, o mecanismo SQL pode expandir essas condições em combinações durante a compilação. N predicadosIS NULLpodem teoricamente produzir até2^Nramificações, aumentando significativamente o tempo de compilação e o uso de memória. Em casos graves, isso pode afetar a execução da consulta e a estabilidade da instância.Recomendação: Evite combinar muitas condições
column IS NULLem uma única instrução SELECT, UPDATE ou DELETE. Considere as seguintes abordagens:Sempre que possível, restrinja o intervalo da consulta usando chaves primárias, índices secundários ou índices de pesquisa.
Se a lógica do seu negócio verifica frequentemente se os campos estão vazios ou presentes, expresse esse estado explicitamente no lado da gravação — por exemplo, com valores padrão ou colunas de status.
Para processamento em lote, divida o trabalho em várias instruções SQL com condições mais simples ou busque primeiro as chaves primárias completas e processe-as em lotes por chave primária.
-
P: Por que não é recomendado usar muitos grupos OR combinados com AND em uma cláusula WHERE?
Problema: Uma instrução SQL cuja cláusula WHERE conecta vários grupos OR entre parênteses com AND, por exemplo:
SELECT * FROM orders WHERE (status = 1 OR status = 2) AND (pay_type = 'wechat' OR pay_type = 'alipay') AND (region = 'CN' OR region = 'US') AND ...;Quanto maior o aninhamento, maior o risco. Isso se aplica igualmente a instruções SELECT, UPDATE e DELETE.
R: Antes de executar uma consulta, o otimizador deve converter a cláusula WHERE em Forma Normal Disjuntiva (DNF) — um conjunto OR de condições AND — para selecionar o caminho de acesso ao índice ideal para cada condição independente. Quando o otimizador encontra
(A OR B) AND (C OR D), ele precisa aplicar a lei distributiva para expandi-la:(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 um com 2 ramificações: 2×2 = 4 termos de combinação.
3 grupos, cada um com 2 ramificações: 2×2×2 = 8 termos de combinação.
À medida que o número de grupos e ramificações por grupo cresce, a quantidade de termos de combinação aumenta exponencialmente. Isso pode elevar significativamente o tempo de compilação do otimizador e o uso de memória e, em casos graves, afetar a execução da consulta e a estabilidade da instância.
Recomendação:
Evite combinar muitos grupos OR entre parênteses com AND em uma única instrução SQL.
Reescreva condições OR da mesma coluna com
IN— por exemplo,status IN (1, 2)— para reduzir o número de ramificações expandidas.Sempre que possível, restrinja o intervalo da consulta usando chaves primárias, índices secundários ou índices de pesquisa.
Para cenários de correspondência multidimensional, use um índice de pesquisa. Consulte Índices de pesquisa.
Se a lógica de negócios exigir condições complexas, divida o trabalho em várias instruções SQL mais simples ou busque primeiro as chaves primárias completas e processe-as em lotes por chave primária.
-
P: Como diagnosticar e resolver um erro de limite de memória para uma consulta específica?
R: Quando uma consulta falhar com o erro de limite de memória, siga estas etapas para diagnosticar a causa raiz e escolher a solução apropriada:
Etapa 1 — Verificar o plano de execução:
Execute
EXPLAINna consulta com falha para visualizar seu plano de execução. Consulte Interpretar um plano de execução para obter detalhes.No plano de execução, identifique se operadores intensivos em memória — como agregação, ordenação e deduplicação — são executados no mecanismo SQL ou transferidos para o mecanismo de armazenamento. Operadores executados no mecanismo SQL consomem memória do limite por consulta, enquanto operadores transferidos utilizam recursos do mecanismo de armazenamento.
Etapa 2 — Tentar otimizar a consulta:
Se operadores intensivos em memória forem executados no mecanismo SQL, tente as seguintes abordagens para reduzir o consumo de memória:
Para operadores de agregação (
GROUP BY,COUNT,SUM,AVG): Crie um índice secundário ou índice de pesquisa nas colunas agrupadas ou agregadas para permitir a transferência do operador para o mecanismo de armazenamento.Para operadores de ordenação (
ORDER BY): Garanta que as colunas de ordenação estejam alinhadas com um índice existente para evitar ordenação em memória. Alternativamente, adicione condiçõesWHEREmais restritivas para reduzir o tamanho do conjunto de dados antes da ordenação.Para operadores de deduplicação (
DISTINCT): Use um índice de pesquisa para consultas em colunas de alta cardinalidade ou adicione condições de filtro seletivas para reduzir o número de linhas processadas.
Etapa 3 — Aumentar o limite de memória, se necessário:
Se todos os operadores já tiverem sido transferidos e a consulta não puder ser mais otimizada, aumente o valor de
QUERY_MAX_MEMusando ALTER SYSTEM:ALTER SYSTEM SET QUERY_MAX_MEM = <new_value_in_bytes>;Verifique o valor atual com a instrução SHOW VARIABLES.
ImportanteEm ambientes de alta concorrência, um valor maior para
QUERY_MAX_MEMaumenta a pressão geral de memória no cluster e pode acionar um Full GC forçado, reduzindo a capacidade de resposta de todo o cluster. Avalie o throughput e a concorrência das suas consultas antes de alterar esse valor.
Problemas de índice e esquema
-
P: Por que a criação de um índice secundário falha com "Executing job number exceed, max job number = 8"?
R: Cada instância do Lindorm permite no máximo 8 tarefas simultâneas de construção de índice secundário. Se 8 tarefas já estiverem em execução, novas tentativas de criação de índice falharão.
Evite criar muitos índices secundários ao mesmo tempo. Se precisar criar um grande volume de índices em massa, entre em contato com o suporte técnico do Lindorm (ID do DingTalk: s0s3eg3).
-
P: Após excluir uma coluna, por que readicionar uma coluna com o mesmo nome falha com "column is under deleting"?
R: Depois que você exclui uma coluna, o LindormTable limpa assincronamente os dados dessa coluna da memória, do armazenamento quente e do armazenamento frio. O sistema impede a recriação de uma coluna com o mesmo nome até que a limpeza seja concluída para evitar dados inconsistentes causados por incompatibilidade de tipos ou colisões de dados.
A limpeza ocorre em segundo plano e pode levar muito tempo. Para acelerá-la, execute as seguintes instruções na tabela (substitua
dtpelo nome da sua tabela):-- Flush residual in-memory data to storage. ALTER TABLE dt FLUSH; -- Run compaction to merge and remove deleted data. ALTER TABLE dt COMPACT;Após a conclusão da limpeza, readicione a coluna.
ImportanteFLUSHé suportado a partir da versão 2.7.1 do mecanismo SQL. Verifique sua versão no Guia de versões SQL.Tanto
FLUSHquantoCOMPACTsão assíncronos. A execução bem-sucedida da instrução não significa que a limpeza foi concluída.Executar
COMPACTem uma tabela com grande volume de dados consome recursos significativos do sistema. Evite executá-lo durante horários de pico de negócios.
-
P: Após criar um índice secundário, por que a gravação de dados falha com um erro "User-Defined-Timestamp"?
R: Mensagem de erro:
Performing put operations with User-Defined-Timestamp in indexed column on MULTABLE_LATEST table is unsupportedAo gravar dados com um carimbo de data/hora personalizado explícito — por exemplo, usando a dica
/*+ _l_ts */em uma instrução UPSERT — tanto a tabela primária quanto a tabela de índice secundário devem ter sua mutabilidade definida comoMUTABLE_ALL. No entanto, o Lindorm define novas tabelas e índices comoMUTABLE_LATESTpor motivos de desempenho. Gravar com um carimbo de data/hora personalizado em uma tabela de índice com mutabilidadeMUTABLE_LATESTaciona esse erro.A propriedade MUTABILITY não pode ser alterada após a criação da tabela de índice. Você deve excluir o índice existente, atualizar a mutabilidade da tabela primária e, em seguida, recriar o índice.
-
Desative e remova o índice secundário 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 Excluir um índice secundário.
-
Defina a mutabilidade da tabela primária como
MUTABLE_ALL:ALTER TABLE IF EXISTS <primary_table_name> SET MUTABILITY='MUTABLE_ALL'; Crie um novo índice secundário. Consulte CREATE INDEX.
NotaPara detalhes sobre como gravar dados com um carimbo de data/hora personalizado, consulte Usar HINTs para definir carimbos de data/hora no gerenciamento de dados multiversão.
NotaPara detalhes sobre como a mutabilidade do índice secundário interage com carimbos de data/hora personalizados, consulte Atualizar um índice com um carimbo de data/hora personalizado.
-
Operações em lote
-
P: Por que atualizações em lote não são suportadas, ou por que ocorre o erro "Update's WHERE clause can only contain PK columns"?
R: Apenas atualizações de linha única são suportadas por padrão. Para obter informações sobre como ativar atualizações em lote, consulte Perguntas frequentes sobre operações em lote.
-
P: Como ativar exclusões em lote?
R: Para obter informações sobre como ativar e configurar exclusões em lote, consulte Perguntas frequentes sobre operações em lote.