【笔记分享列表】
来自 creater
创建于: 11月07日
1.需求是遍历读取一张大概200w行的数据表中的数据,
  当使用下面的语句查询时前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)
    questionID是主键,这个查询的用时为毫秒级别
  这时候报了一个错误【附图1】
  Query : SELECT * from questions where questionId in (SELECT questionId FROM questions LIMIT 50 OFFSET 577990)  LIMIT 0, 1000
  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
 查询发现原因是mysql中limit和in不能同时使用
 于是优化语句得到
 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
   的执行效果是完全不一样的,后一条语句会导致全表扫描速度也是相当的慢,所以不能对主键使用除默认外的排序


Add Pagination
Add Navigation