【笔记分享列表】
1.需求是遍历读取一张大概200w行的数据表中的数据,
当使用下面的语句查询时前20w行数据的读取都还比较快速,但越到后面发现性能越来越差
根据原理自己做了一个小实验对比
于是优化语句得到
更新:
实际测试中使用in语句在执行是又出现一个问题,当offset执行到110w左右时候突然卡死不能继续往下执行
于是改用inner join 等值查询,彻底解决了这个性能问题
有一个小插曲需要注意的是
当使用下面的语句查询时前20w行数据的读取都还比较快速,但越到后面发现性能越来越差
SELECT * FROM questions LIMIT 50 OFFSET 578390查询资料发现介绍该问题的文章【mysql查询时,offset过大影响性能的原因与优化方法】
根据原理自己做了一个小实验对比
SELECT * FROM questions LIMIT 50 OFFSET 578390
用时为1分钟左右
SELECT questionID FROM questions LIMIT 50 OFFSET 578390于是想到优化语句
questionID是主键,这个查询的用时为毫秒级别
SELECT * from questions where questionID in(SELECT questionID FROM questions LIMIT 50 OFFSET 578390)这时候报了一个错误【附图1】
questionID是主键,这个查询的用时为毫秒级别
Query : SELECT * from questions where questionId in (SELECT questionId FROM questions LIMIT 50 OFFSET 577990) LIMIT 0, 1000查询发现原因是mysql中limit和in不能同时使用
Error Code : 1235
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Execution Time : 00:00:00:000
Transfer Time : 00:00:00:000
Total Time : 00:00:00:000
于是优化语句得到
SELECT * FROM questions WHERE questionId IN (SELECT sc.questionId FROM (SELECT questionId FROM questions LIMIT "+limit+" OFFSET "+offset+") AS sc)
执行时间基本在1s级别
更新:
实际测试中使用in语句在执行是又出现一个问题,当offset执行到110w左右时候突然卡死不能继续往下执行
于是改用inner join 等值查询,彻底解决了这个性能问题
SELECT a.* FROM questions AS a INNER JOIN (SELECT questionId FROM questions LIMIT 50 OFFSET 2648860) AS sc ON a.questionId=sc.questionId;
有一个小插曲需要注意的是
SELECT questionId FROM questions LIMIT 50 OFFSET 2648860
和
SELECT questionId FROM questions Order By questionId DESC LIMIT 50 OFFSET 2648860
的执行效果是完全不一样的,后一条语句会导致全表扫描速度也是相当的慢,所以不能对主键使用除默认外的排序