随着业务发展越来越快,原来的数据库数据从几万突破到几百万,分页的查询策略是否需要调整一下?
order_history
unsigned int id
,tinyint(4) int type
37
个字段,不包含 text
等大型数据,最大为 varchar(500)
,id
字段为索引,且为递增5709294
MySQL
版本:5.7.16
对于一般最基本的分页查询会使用
select * from orders_history where type=8 limit 1000,10;
limit
查询不同的数据记录条数测试select * from orders_history where type=8 limit 10000,1;
select * from orders_history where type=8 limit 10000,10;
select * from orders_history where type=8 limit 10000,100;
select * from orders_history where type=8 limit 10000,1000;
select * from orders_history where type=8 limit 10000,10000;
三次查询耗时时间如下:
1
条记录:3072ms 3092ms 3002ms
10
条记录:3081ms 3077ms 3032ms
100
条记录:3118ms 3200ms 3128ms
1000
条记录:3412ms 3468ms 3394ms
10000
条记录:3749ms 3802ms 3696ms
结论:在查询记录数量低于 100
时,查询耗时时间基本没有差距,随着查询记录数量越来越大,所花费的时间也会越来越多
limit
查询不同的数据偏移量测试select * from orders_history where type=8 limit 100,100;
select * from orders_history where type=8 limit 1000,100;
select * from orders_history where type=8 limit 10000,100;
select * from orders_history where type=8 limit 100000,100;
select * from orders_history where type=8 limit 1000000,100;
三次查询耗时时间如下:
100
偏移:25ms 24ms 24ms
1000
偏移:78ms 76ms 77ms
10000
偏移:3092ms 3212ms 3128ms
100000
偏移:3878ms 3812ms 3798ms
1000000
偏移:14608ms 14062ms 14700ms
结论:随着查询偏移量的增大,尤其查询偏移大于 10
万以后,查询时间急剧增加。这种分页查询方式会从数据库第一条记录开始扫描,所以越往后,查询速度越慢,而且查询的数据越多,也会拖慢总查询速度
这种方式适用于主键 id
递增的情况
select * from orders_history where type=8 limit 100000,1;
select id from orders_history where type=8 limit 100000,1;
select * from orders_history where type=8 and id>=(select id from orders_history where type=8 limit 100000,1) limit 100;
select * from orders_history where type=8 limit 100000,100;
四条语句的查询时间如下:
1
条语句:3674ms
2
条语句:1315ms
3
条语句:1327ms
4
条语句:3710ms
原因分析:通过使用覆盖索引查询返回需要的主键,再根据主键获取原表需要的数据
这种方式假设数据表的 id
是连续递增的,则根据查询的页数和查询的记录数可以算出推查询的 id
的范围,可以使用 between and
来查询
select * from orders_history where type=2 and id between 1000000 and 1000100 limit 100;
这种查询方式能够极大地优化查询速度,基本能够在几十毫秒之内完成。限制是只能使用于明确知道 id
的情况,不过一般建立表的时候,都会添加基本的 id
字段,这为分页查询带来很多便利
select * from orders_history where id >= 1000001 limit 100;
当然还可以使用 in
的方式来进行查询,这种方式经常用在多表关联的时候进行查询,使用其他表查询的 id
集合,来进行查询
select * from orders_history where id in (select order_id from trade_2 where goods = 'pen') limit 100;
id
主键字段,这样方便查询id
作为唯一标识,而应该使用分布式的高并发唯一 id
生成器来生成,并在数据表中使用另外的字段来存储这个唯一标识要提高数据库查询的效率,关键就是利用索引树,而索引又分为普通索引和主键索引。最佳的查询效率就是要使用主键索引;而使用了普通索引又增加了一次回表查询。在大数据量的分页查询中,核心就是利用好主键索引而已
关于 mysql
索引的文章:https://blog.csdn.net/weixin_38192427/article/details/111872683