Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

mysql:SELECT id muito simples ORDER BY LIMIT não usará INDEX como esperado (?!)


As pesquisas de índice são por valor , não por posição . Um índice pode pesquisar um valor 2955900, mas você não está pedindo isso. Você está solicitando que a consulta comece em um deslocamento da linha 2955900 na tabela.

O otimizador não pode presumir que todos os valores de chave primária sejam consecutivos. Portanto, é bastante provável que a linha 2955900 tenha um valor muito maior que isso.

Mesmo que os valores da chave primária sejam consecutivos, você pode ter uma condição WHERE que corresponda apenas, por exemplo, a 45% das linhas. Nesse caso, o valor do id na linha 2955900 seria way passado o valor de ID 2955900.

Em outras palavras, uma pesquisa de índice do valor de id 2955900 não entregará a linha 2955900.

Portanto, o MySQL não pode usar o índice para o deslocamento de um limite. Ele deve escaneie as linhas para contá-las até atingir as linhas de deslocamento+limite.

O MySQL tem otimizações relacionadas a LIMIT , mas trata-se mais de interromper uma verificação de tabela assim que atingir o número de linhas a serem retornadas. O otimizador ainda pode relatar em um plano EXPLAIN que ele espera poder tem que escanear toda a mesa.

Um mal-entendido frequente sobre FORCE INDEX é que força o uso de um índice. :-)Na verdade, se a consulta não puder usar um índice (ou se os índices disponíveis não tiverem nenhum benefício para esta consulta), FORCE INDEX não terá efeito.

Re seu comentário:

A paginação é uma ruína frequente de aplicativos da Web orientados a dados. Apesar do quão comum esse recurso é, não é fácil de otimizar. Aqui estão algumas dicas:

  • Por que você está consultando com o deslocamento 2955900? Você realmente espera que os usuários vasculhem tantas páginas? A maioria dos usuários desiste depois de algumas páginas (exatamente quantas depende do tipo de aplicativo e dos dados).

  • Reduza o número de consultas. Sua função de paginação pode buscar as primeiras 5-10 páginas, mesmo que mostre apenas a primeira página para o usuário. Armazene em cache as outras páginas, com a suposição de que o usuário avançará por algumas páginas. Somente se eles avançarem além do conjunto de páginas em cache, seu aplicativo precisará fazer outra consulta. Você pode até mesmo armazenar em cache todas as 10 páginas em Javascript no navegador do cliente, então clicar em "Avançar" é instantâneo para eles (pelo menos para as primeiras páginas).

  • Não coloque um botão "Último" em nenhuma interface de usuário, porque as pessoas clicarão nele por curiosidade. Observe que o Google tem um botão "Próximo", mas não um botão "Último". Portanto, a própria interface do usuário desencoraja as pessoas a executar consultas ineficientes com altos deslocamentos.

  • Se o usuário estiver avançando uma página por vez, use o valor de id mais alto retornado na página anterior na cláusula WHERE da consulta da próxima página. Ou seja o seguinte faz use o índice, mesmo sem a dica FORCE INDEX:
    SELECT * FROM thistable WHERE id > 544 LIMIT 20