背景
- 前两天做项目需要讲数据从MySQL 同步到ES中,由于索引结构经常发生变化,需要时不时就跑一个全量的索引。
- 数据库MySQL5.7
- 开始方案没有选好,图省事,用的select * from table limit x,10000进行全量读取(现在已经改成用id扫描方式了。。),开始速度还可以,越到后面越慢。
自己测试
在自己的电脑上面做了一个一个测试,主要是优化一下limit查询,有一定提升,但是这个尽量还是别用的好,全量还是用id扫描最快。
配置如下:
- 16款MacPro,16G内存 4Core i7 2.2G,SSD硬盘
- MySQL 5.7.22
- 表很简单一列主键id,一列guid,guid没有加索引,InnoDB引擎
- 数据量24589792(自己select insert 进去的)
- 没有做任何特殊优化,只是标准安装(- -自己水平有限)
测试结果如下:
- 语句1:
SELECT * FROM token LIMIT 24589790,1
- 结果:
- OK, Time: 5.920000s
- OK, Time: 5.872000s
- OK, Time: 5.821000s
- OK, Time: 5.819000s
- OK, Time: 5.880000s
- 语句2:
SELECT * FROM token INNER JOIN (SELECT id FROM token LIMIT 24589790,1) t USING (id)
- 结果:
- OK, Time: 4.897000s
- OK, Time: 4.962000s
- OK, Time: 4.897000s
- OK, Time: 4.889000s
- OK, Time: 4.910000s
- 语句1:
其实还是挺明显的,接近1秒的差别
原理
- 从《高性能MySQL》中看到的,摘抄一下
- LIMIT和OFFSET,尤其是OFFSET 会导致MySQL扫描大量的不需要的行,然后抛弃掉,这个也是查询慢的根本原因。
- 语句2提升查询效率是因为他可以让MySQL扫描尽可能少的页面,获取到需要访问的记录后再根据关联列去原表找到所需要的列。
高效的最终方案
- 就是上面提到的通过Id扫描的方式进行查询,速度杠杠的
- SELECT * FROM token WHERE id>4589790 LIMIT 1
- 花费时间(hmmm……显示是OK, Time: 0.000000s)