Análise do MySQL Milhões de ideias de otimização de paginação de profundidade de dados

Cena de negócios

Geralmente, no desenvolvimento do projeto, haverá muitos dados estatísticos que precisam ser relatados e analisados. Geralmente, após a análise, eles serão exibidos em segundo plano para que as operações e produtos sejam visualizados nas páginas. O mais comum é filtrar por data . Esse tipo de dado estatístico aumentará gradualmente de tamanho ao longo do tempo, e é apenas uma questão de tempo até atingir milhões ou dezenas de milhões de dados.

reprodução gargalo

Criou uma tabela de usuário e adicionou um índice ao campo create_time . E adicionou 100w de dados à tabela.

Aqui, usamos o método de paginação de limite para consultar a diferença no tempo de consulta entre os primeiros 5 dados e os últimos 5 dados.

Consultar os primeiros 10 itens basicamente não consome muito tempo

Quando buscamos dados de 50w+, a consulta leva 1 segundo .

A palavra-chave SQL_NO_CACHE
é para evitar que as consultas SQL sejam armazenadas em cache.

A mesma instrução SQL, diferentes condições de paginação e a lacuna de desempenho entre os dois são tão grandes que, à medida que a quantidade de dados aumenta, o tempo gasto na consulta de páginas subsequentes aumentará logicamente.

analise de problemas

formulário de devolução

Geralmente criamos índices para campos com alta frequência de consulta. Os índices melhorarão nossa eficiência de consulta. Nossa instrução acima usa SELECT * FROM user , mas nem todos os nossos campos são indexados. Depois que os dados qualificados são consultados no arquivo de índice , também é necessário consultar os campos que não foram indexados no arquivo de dados . Em seguida, esse processo é chamado de volta à tabela .

índice de cobertura

如果查询的字段正好创建了索引了,比如 SELECT create_time FROM user,我们查询的字段是我们创建的索引,那么这个时候就不需要再去数据文件里面查询,也就不需要回表。这种情况我们称之为覆盖索引

IO

回表操作通常是IO操作,因为需要根据索引查找到数据行后,再根据数据行的主键或唯一索引去聚簇索引中查找具体的数据行。聚簇索引一般是存储在磁盘上的数据文件,因此在执行回表操作时需要从磁盘读取数据,而磁盘IO是相对较慢的操作。

LIMTI 2000,10 ?

你有木有想过LIMIT 2000,10会不会扫描1-2000行,你之前有没有跟我一样,觉得数据是直接从2000行开始取的,前面的根本没扫描或者不回表。其实这样的写法,一个完整的流程是查询数据,如果不能覆盖索引,那么也是要回表查询数据的。

现在你知道为什么越到后面查询越慢了吧!

问题总结

我们现在知道了LIMIT 遇到后面查询的性能越差,性能差的原因是因为要回表,既然已经找到了问题那么我们只需要减少回表的次数就可以提升查询性能了。

解决方案

既然覆盖索引可以防止数据回表,那么我们可以先查出来主键id(主键索引),然后将查出来的数据作为临时表然后 JOIN 原表就可以了,这样只需要对查询出来的5条结果进行数据回表,大幅减少了IO操作。

优化前后性能对比

我们看下执行效果:

  • 优化前:1.4s

  • 优化后:0.2s

查询耗时性能大幅提升。这样如果分页数据很大的话,也不会像普通的limit查询那样慢。

更多优秀的内容请关注公众号:一个程序员的成长

Acho que você gosta

Origin juejin.im/post/7230979300828151865
Recomendado
Clasificación