mysql快速分页-索引性能分析-索引-order by-limit-offset-covering-index

* 我们经常会碰到以下的场景
  mysql中的用户数据(以下例子中以邮件为例)达到上百万级别,单个用户的邮件上万,
  当进行用户邮件记录查询时需要支持按照时间,按照标题,和按照收件人进行排序,
  排序之后还要分页显示(用户邮件可能会分上千页),当用户选择3000 页,5000页,
  或者是尾页的时候,性能很差


* 构造测试数据模型
  表结构
    create table user_mail
    (
          id int(9) NOT NULL auto_increment,
          user_id int(9) NOT NULL,
          subject varchar(128),
          creating_time datetime,
          from_addr varchar(128),
          detail varchar(1024),
          PRIMARY KEY(id)
    );
    数据库为MyISAM, 字符集Latin-1
    生成测试数据的程序,代码如下, 产生300万条数据, 对应1000个用户,数据300万条(每个人3000条左右浮动)

为了测试较差的情况,特别让其中一个用户关联大量记录, 执行下面的语句
    update user_mail set user_id=900 where user_id>900;
    数据统计,编号0 ~ 899的用户的邮件数目在3000左右浮动,900号用户的数据为30万( 下面的测试均针对900号用户进行查询 ),数据一共300万

  • 试验环境

使用本机 mysql (5.0.21), 本机配置 , IBM think pad T61, 双核 1.8G, 2G 内存

  •     查询要求,分页查询某人的邮件,按照subject进行排序
  • 普通做法

    创建索引
    create index i_user_mail_subject on user_mail(user_id,subject);
   
    下面是执行的查询
    select * from user_mail where user_id=900 order by subject limit 100 offset ???
   
    offset 执行时间
    100        0.01秒
    1000    0.03秒
    10000    0.25秒
    100000    1.63秒
   
    最差情况的这个用户,当我选择尾页邮件的时候,数据库的负载极高,而且耗时超过2秒

  • 优化做法   

    创建索引
    create index i_user_mail_subject1 on user_mail(user_id,subject,id);
   
    下面是执行的查询
    select * from user_mail um
    inner join (
        select id from user_mail where user_id=900 order by subject limit 100 offset ???
    ) page on page.id=um.id;

    offset 执行时间
    100        0.01秒
    1000    0.02秒
    10000    0.03秒
    100000    0.24秒
   
    优化做法的sql语句和普通做法的sql是等价的,但是速度相差8倍左右
    可以看到当查询offset 10000时,只用了30ms,性能杠杠的

  • 优化原理

    covering index
    查询的所有字段在索引里都可以找到,这样查询的时候只用找索引就可以了
    这就是为什么优化算法中建立索引是三列主键
    select id from user_mail where user_id=900 order by subject limit 100 offset 10000
    上面的sql会很快,因为id, user_id, subject都能应用索引
    如果写成
    select * from user_mail where user_id=900 order by subject limit 100 offset 10000
    就会慢很多
   
    所以优化算法中先查询出小结果集(100条)的id, 然后再进行join查询,查询其他字段的值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章