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查詢,查詢其他字段的值

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