Como faço para otimizar as consultas de MySQL com constantes?
-
10-07-2019 - |
Pergunta
NOTA:. A pergunta original é discutível, mas digitalização para o fundo para algo relevante
Eu tenho uma consulta que eu quero otimizar que é algo como isto:
select cols from tbl where col = "some run time value" limit 1;
Eu quero saber o que as chaves estão sendo usadas, mas o que eu passar para explicar, é capaz de otimizar a cláusula WHERE para nada ( "Impossible ONDE notado ..."), porque eu alimentava uma constante.
- Existe uma maneira de dizer mysql não fazer otimizações constantes em explicar?
- Am I faltando alguma coisa?
- Existe uma maneira melhor para obter a necessidade informação que eu?
Edit: EXPLAIN
parece estar dando-me o plano de consulta que irá resultar de valores constantes. Como a consulta é parte de um procedimento armazenado (e planos IIRC consulta em SPOC são gerados antes que eles são chamados), este não me faz bem porque o valor não são constantes. O que eu quero é para descobrir o que consulta planejar o otimizador irá gerar quando ele não sabe qual é o valor real será.
Am I faltando soemthing?
Edit2: Pedindo ao redor em outros lugares, parece que o MySQL sempre regenera consulta planos a menos que você sair do seu caminho para torná-lo voltar a usá-los. Mesmo em procedimentos armazenados. A partir disso, parece que a minha pergunta é discutível.
No entanto isso não faz o que eu realmente queria saber discutível: Como você otimizar uma consulta que contém valores que são constantes dentro de qualquer consulta específica, mas onde eu, o programador, não conhecido de antemão o valor será usado -? Por exemplo, dizer que o meu código do lado do cliente está gerando uma consulta com um número dentro da cláusula where
. Algumas vezes o número resultará em um cláusula impossível onde outras vezes não. Como posso usar explicar para examinar como bem otimizado a consulta é?
A melhor abordagem que eu estou vendo logo de cara seria executar EXPLAIN
nele para a matriz completa de casos exist / não existe. Realmente isso não é uma solução muito boa como seria ao mesmo tempo difícil e erro propenso a fazer à mão.
Solução
Por exemplo, dizer que o meu código do lado do cliente está gerando uma consulta com um número em que é onde cláusula.
Algumas vezes o número resultará em um impossível cláusula WHERE outras vezes não.
Como posso usar explicar para examinar como bem otimizado a consulta é?
MySQL
constrói planos de consulta diferentes para diferentes valores dos parâmetros vinculados.
Neste artigo você pode ler o lista de quando é que o otimizador MySQL
faz o:
Action When Query parse PREPARE Negation elimination PREPARE Subquery re-writes PREPARE Nested JOIN simplification First EXECUTE OUTER->INNER JOIN conversions First EXECUTE Partition pruning Every EXECUTE COUNT/MIN/MAX elimination Every EXECUTE Constant subexpression removal Every EXECUTE Equality propagation Every EXECUTE Constant table detection Every EXECUTE ref access analysis Every EXECUTE range/index_merge analysis and optimization Every EXECUTE Join optimization Every EXECUTE
Há mais uma coisa que falta nesta lista.
MySQL
pode reconstruir um plano de consulta em todas as JOIN
iteração :. Tal chamado range checking for each record
Se você tem um índice composto sobre uma mesa:
CREATE INDEX ix_table2_col1_col2 ON table2 (col1, col2)
e uma consulta como esta:
SELECT *
FROM table1 t1
JOIN table2 t2
ON t2.col1 = t1.value1
AND t2.col2 BETWEEN t1.value2_lowerbound AND t2.value2_upperbound
, MySQL
não vai usar um acesso de índice RANGE
de (t1.value1, t1.value2_lowerbound)
para (t1.value1, t1.value2_upperbound)
. Em vez disso, ele usará um acesso de índice REF
em (t1.value)
e filtro apenas os valores errados.
Mas se você reescrever a consulta como esta:
SELECT *
FROM table1 t1
JOIN table2 t2
ON t2.col1 <= t1.value1
AND t2.col1 >= t2.value1
AND t2.col2 BETWEEN t1.value2_lowerbound AND t2.value2_upperbound
, em seguida, MySQL
irá verificar novamente o acesso índice RANGE
para cada registro de table1
, e decidir se a utilização de acesso RANGE
na mosca.
Você pode ler sobre isso nestes artigos no meu blog:
- Seleção de data e hora para uma hora zona - como usar filtragem grossa para filtrar timestamps sem um fuso horário
- Emulando SKIP SCAN - como emular método de acesso
SKIP SCAN
emMySQL
- funções analíticas : otimizar LAG, CHUMBO, FIRST_VALUE, LAST_VALUE - como emular funções analíticas da Oracle em
MySQL
- Avançado amostragem linha - como selecionar registros
N
de cada grupo emMySQL
Todas essas coisas empregar RANGE CHECKING FOR EACH RECORD
Voltando à sua pergunta:. não há nenhuma maneira de saber qual plano irá MySQL
uso para cada dado constante, já que não há nenhum plano antes da constante é dado
Infelizmente, não há nenhuma maneira de forçar MySQL
usar um plano de consulta para cada valor de um parâmetro de limite.
Você pode controlar a ordem JOIN
e INDEX
'es ser escolhido usando cláusulas STRAIGHT_JOIN
e FORCE INDEX
, mas eles não vão forçar um certo caminho de acesso em um índice ou proibir a IMPOSSIBLE WHERE
.
Por outro lado, para todos da JOIN
, MySQL
emprega apenas NESTED LOOPS
. Isso significa que se você construir fim JOIN
direita ou escolher índices certas, MySQL
provavelmente beneficiar de tudo de IMPOSSIBLE WHERE
.
Outras dicas
Você está recebendo "Impossível ONDE notado" porque o valor especificado não é na coluna, não apenas porque é uma constante. Você poderia 1) use um valor que existe na coluna ou 2) apenas dizer col = col
:
explain select cols from tbl where col = col;
Como você otimizar uma consulta com os valores que são constantes apenas para a consulta, mas onde eu, o programador, não sabe de antemão o valor será usado?
Ao usar índices nas colunas específicas (ou mesmo à combinação de colunas, se você sempre consultar as colunas dadas juntos). Se você tiver índices, o planejador de consultas será potencialmente usá-los.
Em relação aos valores "impossíveis": o planejador de consulta pode-se concluir que um determinado valor não está na tabela de várias fontes:
- se existe um índice para a coluna particular, pode-se observar que o valor particular é grande ou menor do que todo o valor do índice (mínimo de valores max / ter tempo constante a partir de extracto de índices)
- se você estiver passando no tipo errado (se você está pedindo uma coluna numérica para ser igual a um texto)
PS. Em geral, a criação do plano de consulta não é caro e é melhor para re-criar do que para reutilizá-los, uma vez que as condições podem ter mudado desde o plano de consulta foi gerado e existe um melhor poder plano de consulta.