Uma análise do princípio de otimização de índice SQL online e erros de seleção de índice

Ocorreu um problema estranho na consulta do módulo de pedido pelo qual meu colega era responsável há dois dias. Quando as condições do filtro forem adicionadas, o problema de tempo limite da consulta ocorrerá. Não há problema ao consultar todos os pedidos. O SQL é o seguinte (os dados foram dessensibilizados e o MySql é usado):

SELECT
	a.consumer_code AS orderCode,
	a.rent_equipment_snid AS eqSn,
	a.powerbank_snid AS pbSn,
	a.rent_merchant_name AS rentMerchant,
	a.rent_merchant_address AS merchantAddress,
	a.rent_date AS rentTime,
	a.close_date AS returnTime,
	a.payment_money AS orderAmount,
	a.order_status AS orderStatus,
	a.consume_schema AS consumeSchema,
	a.transaction_status AS transStatus,
	a.rent_equipment_model AS eqModel 
FROM
	cp_consumer_order_2020_10 a 
WHERE
	a.agent_code = xxxx
	# 下面两个条件就是筛选时才会加上
	AND a.order_status = xxx 
	AND a.close_date IS NULL 
ORDER BY
	a.consumer_code desc

cp_consumer_order_2020_10 é uma tabela de pedido mensal com quase 10 milhões de dados, consumer_code é a chave primária e agent_code tem um índice normal.
Eu executei o SQL acima no banco de dados e descobri que o índice agent_code havia sumido e a eficiência da consulta estava normal. Então, excluí as condições do filtro e os resultados da execução foram os mesmos.Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

O acima é um plano de execução condicional e incondicional, você pode ver que não há diferença. Neste momento, gostaria de saber se há alguma operação demorada no
Insira a descrição da imagem aqui
código : este código não parece ter nenhuma operação particularmente demorada, getAgentOrderList é para executar esse SQL, getAgentStaffOrderList também tentou consultar muito rapidamente, por causa da paginação, o seguinte para A execução do loop não será particularmente lenta.
É possível que outro "incidente espiritual" tenha ocorrido? A essa altura, pensei subitamente se poderia ser causado por paginação.Todos sabemos que esse limite causará uma consulta lenta quando o deslocamento for muito grande, mas ainda não viramos a página, que é a primeira página, então esse não é o problema.
Além disso, eu pensei que já tinha visto o problema de erros de seleção de índice ao usar limite e ordem por antes.Por isso trouxe limit 0,30 e executei o SQL agora mesmo no banco de dados.Como esperado, apareceu SQL lento. Neste momento, vejo o plano de execução da seguinte maneira:
Insira a descrição da imagem aqui
Você pode ver que o Mysql usa o índice de chave primária neste momento, ou seja, o campo que classificamos, então sugiro que meus colegas usem índice de força para forçar o índice normal, e a consulta retorna ao normal.
Neste ponto, a otimização SQL acabou, mas por que adicionar limite fará com que o Mysql selecione o índice errado e por que é tão lento usar o índice de chave primária e o número estimado de linhas verificadas é obviamente menor? Seguindo o princípio de “saber o que se passa, mas também saber porquê”, verifiquei muitas informações, mas não consegui resolver totalmente as dúvidas do meu coração, acabei por tentar várias vezes e por fim descobri.

  • Em primeiro lugar, por que é mais rápido pegar índices normais e mais lento para índices de chave primária?
    Como meu SQL é o resultado da consulta ao índice da chave primária na ordem reversa, o índice é naturalmente ordenado e não precisa ser classificado, então vejo que o campo Extra no plano de execução não tem o uso de arquivosort, que é mais rápido do que o índice comum, mas este SQL é filtrado pelas condições de onde Sim, depois de obter os resultados solicitados, você precisa retirar o agent_code e as condições, um por um, para corresponder. Vendo isso, acredito que os leitores devam basicamente entender. Se não houver limite, então esse SQL fará uma varredura completa da tabela; e houver um limite de 0,30, ocorrerá a seguinte situação: Primeiro, os 30 registros que correspondem à condição where estão corretos Se forem os primeiros 30 itens após a classificação, então o mysql só precisa verificar 30 itens; se houver menos de 30 itens ou os registros correspondentes estiverem no final da classificação, toda a tabela será verificada. No entanto, o índice normal agent_code não tem esse problema, porque a condição do filtro é agent_code, que pode ser correspondida rapidamente.
  • Por que o índice de chave primária é usado quando o limite é adicionado?
    Porque se o índice de chave primária for usado sem limite, ele corresponderá à condição where, um por um, conforme mencionado acima, mas não há limite para o número de itens retornados, e uma verificação completa da tabela será realizada (você pode usar forçar índice (primário) + explicar para ver a linha É o número total de linhas na tabela (1000w), o Mysql pensa que é mais rápido usar índices comuns, porque o número estimado de linhas de varredura para índices comuns é menor que 1,8W; mas após adicionar o limite, o número estimado de linhas de varredura para o índice de chave primária pode ser É menor que o número estimado de linhas de varredura para índices normais, o que leva a erros de seleção de índice.

Acho que você gosta

Origin blog.csdn.net/l6108003/article/details/109382533
Recomendado
Clasificación