Esquema de otimização de consulta de paginação MySQL para grande volume de dados

Método 1: use a instrução SQL fornecida pelo banco de dados diretamente

Estilo de instrução: no  MySQL, os seguintes métodos estão disponíveis:

SELECT * FROM 表名称 LIMIT M,N

Adaptar-se ao cenário:  adequado para situações com uma pequena quantidade de dados (tupla centenas / milhares)

Razões / desvantagens:  varredura completa da tabela, a velocidade será muito lenta e alguns conjuntos de resultados de banco de dados retornam instáveis ​​(como retornar 1, 2, 3 de uma vez e retornar 2, 1, 3 em outro momento). O limite é limitado a partir do conjunto de resultados Retire a saída N na posição M e descarte o resto.

 

Método 2: crie uma chave primária ou índice exclusivo, use o índice (assumindo 10 entradas por página)

Estilo de instrução: no  MySQL, os seguintes métodos estão disponíveis:

SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) LIMIT M

Cenários de adaptação:  adequados para situações com uma grande quantidade de dados (dezenas de milhares de tuplas)

Motivo:  varredura de índice, a velocidade será muito rápida. Um amigo sugeriu: Como a consulta de dados não é classificada de acordo com pk_id, então haverá casos de dados perdidos, apenas o método 3

 

Método 3: reordenar com base no índice

Estilo de instrução: no  MySQL, os seguintes métodos estão disponíveis:

SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) ORDER BY id_pk ASC LIMIT M

Cenários de adaptação:  adequados para situações com uma grande quantidade de dados (dezenas de milhares de tuplas). É melhor que o objeto de coluna após ORDER BY seja a chave primária ou única, de modo que a operação ORDERBY possa ser eliminada pelo índice, mas o conjunto de resultados seja estável (significado estável , Consulte o método 1)

Motivo: a  varredura de índice será muito rápida, mas a operação de classificação do MySQL é apenas ASC sem DESC (DESC é falso, DESC real será feito no futuro, esperamos ...).

 

Método 4: Use preparação com base no índice

O primeiro ponto de interrogação significa pageNum, o segundo? Indica o número de tuplas por página

Estilo de instrução: no  MySQL, os seguintes métodos estão disponíveis:

PREPARE stmt_name FROM SELECT * FROM 表名称 WHERE id_pk > (?* ?) ORDER BY id_pk ASC LIMIT M

Adapte-se ao cenário:  grande volume de dados

Razão:  varredura de índice, a velocidade será muito rápida. A instrução prepare é um pouco mais rápida do que a instrução de consulta geral.

 

Método 5: usando MySQL para suportar operações ORDER pode usar índices para localizar rapidamente algumas tuplas e evitar varreduras completas de tabela

Por exemplo: leia a tupla da 1000ª à 1019ª linha (pk é a chave primária / chave única).

SELECT * FROM your_table WHERE pk>=1000 ORDER BY pk ASC LIMIT 0,20

Método 6: Use "subconsulta / junção + índice" para localizar rapidamente a posição da tupla e, em seguida, leia a tupla.

Por exemplo (id é a chave primária / chave única, variável em fonte azul)

Exemplos de uso de subconsultas:

SELECT * FROM your_table WHERE id <=
(SELECT id FROM your_table ORDER BY id desc LIMIT ($page-1)*$pagesize ORDER BY id desc
LIMIT $pagesize 

Use o exemplo de conexão:

SELECT * FROM your_table AS t1
JOIN (SELECT id FROM your_table ORDER BY id desc LIMIT ($page-1)*$pagesize AS t2
WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize; 

O MySQL usa paginação limite para grandes volumes de dados. Conforme o número da página aumenta, a eficiência da consulta diminui.

 

Experimento de teste

1. Use diretamente as instruções de limite de início e contagem, que também são os métodos usados ​​em meu programa:

select * from product limit start, count 

Quando a página inicial é pequena, a consulta não tem problemas de desempenho.Vamos ver o tempo de execução da paginação de 10, 100, 1000, 10000 (20 entradas por página).

do seguinte modo:

select * from product limit 10, 20   --0.016秒 
select * from product limit 100, 20  -- 0.016秒
select * from product limit 1000, 20  -- 0.047秒
select * from product limit 10000, 20   --0.094秒

Vimos que à medida que o registro inicial aumenta, o tempo também aumenta. Isso mostra que o limite da instrução de paginação tem muito a ver com o número da página inicial. Em seguida, alteramos o registro inicial para 40w e olhamos para ele (ou seja, o registro Em geral)

select * from product limit 400000, 20   --3.229秒 

Veja a hora em que tiramos a última página de registros

select * from product limit 866613, 20   --37.44秒 

Obviamente, esse tipo de tempo é insuportável para a página de maior número de página desse tipo de paginação.

Disto, também podemos resumir duas coisas:

  • O tempo de consulta da declaração de limite é proporcional à posição do registro inicial

  • A instrução limit do mysql é muito conveniente, mas não é adequada para uso direto em tabelas com muitos registros.

 

2. Método de otimização de desempenho para limitar o problema de paginação

Use o índice de cobertura da tabela para acelerar as consultas de paginação

Todos nós sabemos que se apenas a coluna de índice (cobrindo o índice) for incluída na instrução que usa a consulta de índice, a consulta será muito rápida neste caso.

Como há um algoritmo otimizado para pesquisa de índice e os dados estão no índice de consulta, não há necessidade de encontrar o endereço de dados relevante, o que economiza muito tempo. Além disso, existem caches de índice relacionados no Mysql. É melhor usar o cache quando a simultaneidade é alta.

Em nosso exemplo, sabemos que o campo id é a chave primária, portanto, naturalmente contém o índice de chave primária padrão. Agora, vamos examinar o efeito da consulta usando o índice de cobertura.

Desta vez, consultamos os dados da última página (usando o índice de cobertura, que contém apenas a coluna id), da seguinte maneira:

select id from product limit 866613, 20 0.2秒 

Em comparação com 37,44 segundos para consultar todas as colunas, é cerca de 100 vezes mais rápido

Portanto, se quisermos consultar todas as colunas, existem dois métodos, um está na forma de id> = e o outro é usar junção. Observe a situação real:

SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20

O tempo de consulta é de 0,2 segundos!

 

Outra forma de escrever

SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id

O tempo de consulta também é muito curto!

3. Método de otimização de índice composto

Quão alto pode ser o desempenho do MySql? O MySql é definitivamente um banco de dados adequado para mestres de nível dba jogarem. Geralmente, você pode escrever um pequeno sistema com 10.000 artigos de notícias. O desenvolvimento rápido pode ser alcançado com o framework xx.

Mas a quantidade de dados atingiu 100.000, milhões a dezenas de milhões, seu desempenho pode ser tão alto? Um pequeno erro pode fazer com que todo o sistema seja reescrito ou até mesmo o sistema não pode operar normalmente! Ok, não tanto absurdo.

 

Fale com fatos, veja exemplos:

A tabela de dados collect (id, title, info, vtype) tem estes 4 campos, onde title usa comprimento fixo, info usa texto, id é gradual, vtype é tinyint e vtype é índice.

Este é um modelo simples de sistema básico de notícias. Agora preencha os dados para preencher 100.000 notícias. Por fim, a coleta é de 100.000 registros, e a tabela do banco de dados ocupa 1,6 GB.

OK, observe a seguinte instrução SQL:

select id,title from collect limit 1000,10;

Em breve; basicamente, está tudo bem em 0,01 segundos, então observe o seguinte

select id,title from collect limit 90000,10;

A paginação começa em 90.000, o resultado?

8-9 segundos para completar, o que há de errado com meu deus? Na verdade, para otimizar esses dados, encontre a resposta online. Observe a seguinte declaração:

select id from collect order by id limit 90000,10;

Em breve, 0,04 segundos estará OK. porque? Como a chave primária id é usada para indexação, é claro que é rápida.

A reforma online é:

select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;

Este é o resultado da indexação com id. Mas se o problema for um pouco complicado, acabou. Veja a seguinte declaração

select id from collect where vtype=1 order by id limit 90000,10; 

Muito lento, demorou 8-9 segundos!

Quando eu chegar aqui, acredito que muitas pessoas vão se sentir como se eu estivesse quebrado! O vtype está indexado? Como pode ser lento? o índice vtype é bom, você diretamente

select id from collect where vtype=1 limit 1000,10;

É muito rápido, basicamente 0,05 segundos, mas é aumentado em 90 vezes. A partir de 90.000, essa é a velocidade de 0,05 * 90 = 4,5 segundos. E o resultado do teste atingiu uma ordem de magnitude em 8-9 segundos.

 

A partir daqui, alguém apresentou a ideia de subtabela, esta é a mesma ideia de dis #cuz fórum. A ideia é a seguinte:

Crie uma tabela de índice: t (id, título, vtype) e defina-a para um comprimento fixo, faça a paginação e os resultados serão paginados para encontrar informações na coleta. Isso é viável? Com a experiência, você saberá.

100.000 registros são armazenados em t (id, título, vtype) e o tamanho da tabela de dados é de cerca de 20M. usar

select id from t where vtype=1 order by id limit 90000,10;

em breve. Basicamente, ele pode ser executado em 0,1-0,2 segundos. Porque isto é assim?

Eu acho que é porque os dados coletados são muitos, então a paginação irá percorrer um longo caminho. O limite está totalmente relacionado ao tamanho da tabela de dados. Na verdade, essa ainda é uma varredura completa da tabela, só porque a quantidade de dados é pequena, apenas 100.000 é rápido. OK, vamos fazer um experimento maluco, adicione 1 milhão para testar o desempenho. Depois de adicionar 10 vezes os dados, a tabela-t atingiu imediatamente mais de 200M e tinha comprimento fixo. Ainda é a instrução da consulta agora, o tempo é de 0,1-0,2 segundos para ser concluído! Nenhum problema com o desempenho abaixo do medidor?

errado! Porque nosso limite ainda é 90.000, muito rápido. Dê um grande, comece com 900.000

select id from t where vtype=1 order by id limit 900000,10;

Veja o resultado, o tempo é de 1 a 2 segundos! porque?

Ainda está muito tempo depois da subtabela, muito deprimente! Algumas pessoas dizem que o comprimento fixo melhorará o desempenho do limite. No começo eu pensei que, como o comprimento de um registro é fixo, o mysql deveria ser capaz de calcular a posição de 900.000, certo? Mas superestimamos a inteligência do mysql. Não é um banco de dados comercial. Acontece que o comprimento fixo e o comprimento não fixo têm pouco efeito sobre o limite? Não é à toa que algumas pessoas dizem que o discuz ficará muito lento depois de atingir 1 milhão de registros. Eu acredito que isso seja verdade. Isso está relacionado ao design do banco de dados!

O MySQL não pode quebrar o limite de 1 milhão? ? ? É realmente o limite quando chega a 1 milhão de páginas?

A resposta é: por que NÃO pode exceder 1 milhão é causado por não projetar o mysql. Vamos apresentar o método de tabela sem divisão, vamos fazer um teste louco! Uma tabela lida com 1 milhão de registros e um banco de dados 10G, como paginar rapidamente!

Ok, nosso teste retorna para a tabela de coleta e a conclusão do teste é:

300.000 dados, é viável usar o método de subtabela, e a velocidade de mais de 300.000 será mais lenta do que você pode suportar! Claro, se você usar o método subtabela + eu, é absolutamente perfeito. Mas depois de usar meu método, ele pode ser resolvido perfeitamente sem subtabela!

A resposta é: índice composto! Uma vez, ao projetar um índice mysql, descobri acidentalmente que o nome do índice pode ser escolhido à vontade e vários campos podem ser selecionados.

O início

select id from collect order by id limit 90000,10; 

É tão rápido porque o índice acabou, mas se você adicionar onde, o índice não será obtido. Eu adicionei um índice como pesquisa (vtype, id) com a ideia de tentar.

Então teste

select id from collect where vtype=1 limit 90000,10; 

muito rápido! Concluído em 0,04 segundos!

Teste novamente:

select id ,title from collect where vtype=1 limit 90000,10; 

Infelizmente, 8-9 segundos, nenhum índice de pesquisa!

Teste novamente: pesquise (id, vtype), ou selecione id esta frase, também lamentável, 0,5 segundos.

Resumindo: se você tem onde condições e deseja usar limite para o índice, você deve projetar um índice. Coloque onde primeiro e a chave primária usada por limite depois, e você só poderá selecionar a chave primária!

O problema de paginação foi resolvido perfeitamente. Se você puder retornar o id rapidamente, há esperança de otimizar o limite. De acordo com essa lógica, um limite de nível de milhão deve ser dividido em 0,0x segundos. Parece que a otimização e indexação das instruções do mysql são muito importantes!

 

Acho que você gosta

Origin blog.csdn.net/bj_chengrong/article/details/103233267
Recomendado
Clasificación