MySQL分页查询越来越慢,如何优化?

分页语法

SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT ...

比如一张订单表

CREATE TABLE `t_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`order_no` varchar(32) NOT NULL COMMENT '订单号',
`user_id` varchar(20) NOT NULL COMMENT '用户ID',
`amount` decimal(18,2) NOT NULL COMMENT '订单金额',
`order_status` tinyint(4) NOT NULL COMMENT '订单状态:0新建 1处理中 2成功 3失败',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_order_no` (`order_no`) USING BTREE COMMENT '订单号唯一索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

参照网络数据1000w数据的分页查询:

select * from t_order order by id limit 0, 10;
select * from t_order order by id limit 10000, 10;
select * from t_order order by id limit 100000, 10;
select * from t_order order by id limit 1000000, 10;
select * from t_order order by id limit 10000000, 10;

时间消耗:

-- 0.002
-- 0.045
-- 0.069
-- 0.517
-- 4.134

查询原因:

这是因为查询时 MySQL 并不是跳过 OFFSET 行,而是取 OFFSET+N 行,然后放弃前 OFFSET 行,最后返回 N 行,当 OFFSET 特别大的时候,效率就非常的低下。

拿 limit 10000, 10 这条语句来说明一下, MySQL在执行这条查询的时候,需要查询 10010 (10000 + 10) 条记录,然后只返回最后 10 条,并将前面的 10000 条记录抛弃,这样当翻页越靠后时,代价就变得越来越高。

优化一:记录位置,避免使用 OFFSET

select * from t_order where id > 1000 limit 10;

优化二:计算边界值,转换为已知位置的查询

select * from t_order where id between 10000000 and 10000010;

优化三:使用索引覆盖+子查询优化

select * from t_order where id >= (select id from t_order order by id limit 1000000, 1) order by id limit 10;

优化四:使用索引覆盖+连接查询优化

select * from t_order a Join (select id from t_order order by id limit 1000000, 10) b ON a.id = b.id;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值