MySQL分页Limit的优化过程实战
前言
在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能。
SELECT*FROMtableLIMIT[offset,]rows|rowsOFFSEToffset
LIMIT子句可以被用于强制SELECT语句返回指定的记录数。LIMIT接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是0(而不是1):为了与PostgreSQL兼容,MySQL也支持句法:LIMIT#OFFSET#。
所以通常在查询数据的时候,我们都会用到limit分页,因为这样避免了全表查询,会提高查询效率。但是在一个表的数据量多了之后,分页查询会明细的变慢,下面来一起看看详细的介绍吧
MySQL分页Limit优化
创建测试表card2000万数据
mysql>selectcount(*)fromcard; +----------+ |count(*)| +----------+ |20000000| +----------+ 1rowinset(0.00sec)
-首先测试前1000行查询速度
mysql>select*fromcardlimit1000,10; +---------+--------------------------------------+ |card_id|card_number| +---------+--------------------------------------+ |1001|13fc90a6-2e3b-11e8-ae62-9c5c8e6e37cf| |1002|13fc923e-2e3b-11e8-ae62-9c5c8e6e37cf| |1003|13fc93d5-2e3b-11e8-ae62-9c5c8e6e37cf| |1004|13fc956a-2e3b-11e8-ae62-9c5c8e6e37cf| |1005|13fc9702-2e3b-11e8-ae62-9c5c8e6e37cf| |1006|13fc9899-2e3b-11e8-ae62-9c5c8e6e37cf| |1007|13fc9a31-2e3b-11e8-ae62-9c5c8e6e37cf| |1008|13fc9bc6-2e3b-11e8-ae62-9c5c8e6e37cf| |1009|13fc9d5e-2e3b-11e8-ae62-9c5c8e6e37cf| |1010|13fc9ef5-2e3b-11e8-ae62-9c5c8e6e37cf| +---------+--------------------------------------+ 10rowsinset(0.00sec)
-测试100万之后的查询
mysql>select*fromcardlimit1000000,10; +---------+--------------------------------------+ |card_id|card_number| +---------+--------------------------------------+ |1000001|2d87021a-2e3b-11e8-ae62-9c5c8e6e37cf| |1000002|2d8703ac-2e3b-11e8-ae62-9c5c8e6e37cf| |1000003|2d87053b-2e3b-11e8-ae62-9c5c8e6e37cf| |1000004|2d8706cd-2e3b-11e8-ae62-9c5c8e6e37cf| |1000005|2d87085f-2e3b-11e8-ae62-9c5c8e6e37cf| |1000006|2d8709f1-2e3b-11e8-ae62-9c5c8e6e37cf| |1000007|2d870b83-2e3b-11e8-ae62-9c5c8e6e37cf| |1000008|2d870d18-2e3b-11e8-ae62-9c5c8e6e37cf| |1000009|2d870eaa-2e3b-11e8-ae62-9c5c8e6e37cf| |1000010|2d871039-2e3b-11e8-ae62-9c5c8e6e37cf| +---------+--------------------------------------+ 10rowsinset(0.18sec)
-测试1000万之后的查询
mysql>select*fromcardlimit10000000,10; +----------+--------------------------------------+ |card_id|card_number| +----------+--------------------------------------+ |10000001|b11ad76c-2e49-11e8-ae62-9c5c8e6e37cf| |10000002|b11aefd5-2e49-11e8-ae62-9c5c8e6e37cf| |10000003|b11af868-2e49-11e8-ae62-9c5c8e6e37cf| |10000004|b11b0031-2e49-11e8-ae62-9c5c8e6e37cf| |10000005|b11b07ad-2e49-11e8-ae62-9c5c8e6e37cf| |10000006|b11b0f0f-2e49-11e8-ae62-9c5c8e6e37cf| |10000007|b11b1669-2e49-11e8-ae62-9c5c8e6e37cf| |10000008|b11b1db2-2e49-11e8-ae62-9c5c8e6e37cf| |10000009|b11b24fa-2e49-11e8-ae62-9c5c8e6e37cf| |10000010|b11b2c37-2e49-11e8-ae62-9c5c8e6e37cf| +----------+--------------------------------------+ 10rowsinset(1.29sec)
可以看到越到后面查询效率会越低。因为在查询100万之后的数据的时候,mysql会首先查询100万零10条数据,然后截取后面的十条数据。这些就造成的性能的降低。
那么怎么去避免这个扫描100万条数据呢。我们可以明确的知道,100万之后的主键是大于100万的。所以我们可以将sql改写,让其用到索引,降低扫描的行数
mysql>select*fromcardwherecard_id>=1000000limit10; +---------+--------------------------------------+ |card_id|card_number| +---------+--------------------------------------+ |1000000|2d870088-2e3b-11e8-ae62-9c5c8e6e37cf| |1000001|2d87021a-2e3b-11e8-ae62-9c5c8e6e37cf| |1000002|2d8703ac-2e3b-11e8-ae62-9c5c8e6e37cf| |1000003|2d87053b-2e3b-11e8-ae62-9c5c8e6e37cf| |1000004|2d8706cd-2e3b-11e8-ae62-9c5c8e6e37cf| |1000005|2d87085f-2e3b-11e8-ae62-9c5c8e6e37cf| |1000006|2d8709f1-2e3b-11e8-ae62-9c5c8e6e37cf| |1000007|2d870b83-2e3b-11e8-ae62-9c5c8e6e37cf| |1000008|2d870d18-2e3b-11e8-ae62-9c5c8e6e37cf| |1000009|2d870eaa-2e3b-11e8-ae62-9c5c8e6e37cf| +---------+--------------------------------------+ 10rowsinset(0.00sec)
这样就可以很大的提高查询效率
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。