分頁查詢,你真的懂嗎?


 
 
  程序員代碼的編寫能力主要體現在思維的嚴謹上。有些看起來很簡單的東西,里面包含很多很細的點,你能想到嗎?
  今天我就簡單說一下一個例子,讓大家學習到新知識的同時,也養成一種思維的習慣。
 
 
問題
 
  有一張收藏表,里面存儲的是用戶和圖書ID。數據量為1億。現在要求分頁獲取所有用戶ID(不重復),寫下你的sql語句。
 
  表結構大致如下:
  
CREATE TABLE 收藏表(
     `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'primary key',
     `uid` bigint(20) unsigned NOT NULL default 0 COMMENT 'uid',
   `status` tinyint(3) unsigned NOT NULL default 0 COMMENT 'status', `book_id` bigint(20) unsigned NOT NULL default 0 COMMENT 'book Id', `create_time` int(11) unsigned not null default 0 COMMENT 'create time', PRIMARY KEY (`id`), UNIQUE KEY `uid_book_id` (`uid`, `book_id`),
    KEY `uid_status` (`uid`, `status`) )ENGINED=Innodb Auto_increment=1 default charset=gbk COMMENT '用戶收藏信息';

 

三種設計
 

  最容易想到的第一種分頁語句是(這也是我們最容易想到的語句):

    select distinct uid from 收藏表 order by uid desc limit 0, 10;
    select distinct uid from 收藏表 order by uid desc limit 11, 10;

  再高級點語句,第二種($last_min_uid表示上一次讀到的最后一個uid):

    select distinct uid from 收藏表 order by uid desc limit 10;
    select distinct uid from 收藏表 where uid < $last_min_uid order by uid desc limit 10;

  最高級的方式

    select uid from 收藏表 group by uid order by uid desc limit 10;
    select uid from 收藏表 group by uid having uid < $last_min_uid order by uid desc limit 10;

  

  

分析
 

  以上三種方式都可以實現分頁獲取到用戶ID列表,那么區別是什么?我現在就把每一種跟大家分析下。

 

  第一種在業務場景中,會出現丟數據的情況。——這是比較嚴重的情況,不予采納。

  具體的業務場景是這樣的:當你讀取第5頁的時候,前四頁的用戶id列表中,假如有一頁的用戶ID從庫中刪除掉,那么你這時讀到的第5頁(limit 51, 10),就是原來的第6頁,你會把1頁的用戶ID丟失掉。

 

  第二種的第二條語句,通過explain分析,實際並沒有命中唯一索引,而只是命中了一般索引,數據查詢范圍在7百萬級別,故explain建議我們使用group by。——這個查詢會有嚴重的性能問題

+----+--------------+---------------+-------+-------------------------------------------------------------+-------------+----------+-------+------------+------------------------------------------------------------------------+
| id   | select_type | table           | type  | possible_keys                                                      | key           | key_len | ref     | rows        | Extra                                                                               |
+----+--------------+---------------+-------+-------------------------------------------------------------+---------------------+---------+------+---------+---------------------------------------------------------------------+
| 1    | SIMPLE      | ubook_room | range | uid_book_id                                                       | uid_status  | 4          | NULL | 7066423  | Using where; Using index for group-by; Using temporary; Using filesort |
+----+--------------+---------------+-------+-------------------------------------------------------------+-------------+----------+-------+------------+------------------------------------------------------------------------+

  

  第三種explain分析,數據查詢范圍在12萬級別(跟第二種相差一個數量級),查詢性能高

+----+---------------+------------+-------+-----------------+-----------------+---------+----------+----------+-------------+
| id   | select_type  | table       | type  | possible_keys  | key               | key_len | ref       | rows      | Extra         |
+----+---------------+------------+-------+-----------------+-----------------+---------+----------+----------+-------------+
| 1    | SIMPLE       | 收藏表      | index | NULL             | uid_book_id   | 12         | NULL  | 121719   | Using index |
+----+---------------+------------+-------+-----------------+-----------------+---------+----------+----------+-------------+

 

 

  

推薦
 

  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM