數據庫分頁注意點

當我們需要操作一個數據量很大表的時候,往往可以使用分頁的方法,對數據量進行一部分一部分處理,直到對所有的數據完成操作。但是當我們進行分頁的時候,要非常注意對數據條件的選擇問題。

1.首先我們創建一個測試表,插入幾條數據。

CREATE TABLE `t_table` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `value` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2.連續執行好幾條

insert t_table(value) values('a');

3.然後需要把表的數據展示出來,並進行分頁。一般我們會獲取相應的頁數和每頁的大小來獲取數據完成分頁的功能。這裏我們使用mysql的limit來進行對數據的分頁。

通過分頁查詢,查詢了前三頁的數據。

select * from `t_table` LIMIT 0,5;
select * from `t_table` LIMIT 5,5;
select * from `t_table` LIMIT 10,5;

4.由於業務的需求,要求從新到舊,或者取出value爲a的數據等等的查詢條件,然後對這些數據進行不同的處理,等等。

select * from `t_table` order by create_time desc LIMIT 0,5;
//處理

初略一看結果是沒有問題,在自己調用和測試的時候結果完全符合自己的預期,但是當真正上線的時候就可能產生問題。

1.比如用戶實時操作很頻繁,數據增加量很快。當我們分頁取數據時,先從最新的數據取每次取5條(假設原先有20條),我們要求第一頁爲20-15,第二頁15-10…..但是可能會出現第一次取爲20-15,然後中間用戶插入了5條數據,第二頁取數據就會出現還是20-15,然後用戶又插入5條,第三頁還是20-15….當用戶數據增加很迅速的時候,很有可能永遠取不出最早的幾條數據。

2.當我們對分頁的數據操作的時候,最好不要把會改變的值當做查詢條件。例如我們需要改變數據中id爲偶數的value從a,變成b。

select * from `t_table` where value='a' order by create_time asc LIMIT 0,5;

這裏寫圖片描述
這裏寫圖片描述

我們可能會從數據庫中依次分別取出value爲a的數據,然後改變a的值,再查詢第二條,會發現數據id並不是我們期望的id。

select * from `t_table` where value='a' order by create_time asc LIMIT 5,5;

這裏寫圖片描述


產生上訴問題的原因是數據庫的改變。sql執行select的時候,是先進行where篩選在order by排序。因此當數據改變後,我們查詢的數據列表已經改變了,查詢出來的數據就會’亂’。

所以我們要用分頁的方法來處理一批數據的時候,一定要確定我們的sql語句分頁查詢出來的數據是不會改變的。例如1中的問題,我們可以採用升序的方法,前面產生的數據順序就不會改變。2的解決方法是可以去掉where判斷條件,取出數據後,在代碼裏對value的值進行判斷改變。或者先對數據進行排序取出,再篩選value的值。

select * from (select * from `t_table` order by create_time asc  LIMIT 0,5) t where value='a' ;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章