登录后台

页面导航

本文编写于 2012 天前,最后修改于 1259 天前,其中某些信息可能已经过时。

假设有一个千万量级的表,取1到10条数据;

select * from table limit 0,10;

select * from table limit 1000,10;

这两条语句查询时间应该在毫秒级完成;

select * from table limit 3000000,10;

你可能没想到,这条语句执行之间在5s左右;

为什么相差这么大?

可能 mysql 并没有你想的那么智能,比如你要查询 300w 开始后面10条数据;mysql 会读取 300w 加 10 条这么多的数据,只不过 过滤后返回最后 10 条而已!!!

那么如果解决这个问题呢;这里总结三种常用方法;

不允许查看这么靠后的数据

第一种简单粗暴,就是不允许查看这么靠后的数据,比如百度就是这样的

title=

最多翻到76页就不让你翻了,这种方式就是从业务上解决;

使用参数过滤数据

第二种方法,在查询下一页时把上一页的行id作为参数传递给客户端程序,然后 sql 就改成了

select * from table where id>3000000 limit 10;

这条语句执行也是在毫秒级完成的,id>300w 其实就是让 mysql 直接跳到这里了,不用依次在扫描全面所有的行

如果你的 table 的主键 id 是自增的,并且中间没有删除和断点,那么还有一种方式,比如 100 页的 10 条数据

select * from table where id>100*10 limit 10;

延迟关联

最后第三种方法:延迟关联

我们在来分析一下这条语句为什么慢,慢在哪里。

select * from table limit 3000000,10;

玄机就处在这个 * 里面,这个表除了id主键肯定还有其他字段 比如 name age 之类的,因为 select * 所以 mysql 在沿着 id 主键走的时候要回行拿数据,走一下拿一下数据;

如果把语句改成

select id from table limit 3000000,10;

你会发现时间缩短了一半;然后我们在拿 id 分别去取 10 条数据就行了;

语句就改成这样了:

select table.* from table inner join ( select id from table limit 3000000,10 ) as tmp on tmp.id=table.id;

这三种方法最先考虑第一种 其次第二种,第三种是别无选择