1. 程式人生 > >關於大資料分頁查詢的問題

關於大資料分頁查詢的問題

1、問題背景:

(1)待查詢表中的資料超過4000萬條;
(2)已經對sql的進行過優化,對錶結構等進行優化,並且已經對sql中的查詢條件都添加了索引;
(3)前端分頁需要的資料格式如下:

{
    "total": 0,
    "data": []
}

2、問題描述:

  • 在進行分頁時,由於前端需要知道總的條數(total)。這裡有兩個普遍的解決辦法:一是,在查詢資料時,只執行一個sql,相當於查詢所有,然後在程式中進行分頁;二是執行兩個sql,第一次查詢分頁的資料,第二次執行count()操作。
  • 但是無論使用哪種方式,對於前端查詢而言都會特別慢。

3、解決方案:

(1)方法一:

  • 不告訴前端總的資料量,不傳total值。讓使用者一直點選“下一頁”,當點選後返回資料為空,即表示已經到了最後一頁。此時按鈕變為不可用狀態。這種做法的好處是,只執行一個分頁的sql,效率比較高。
    如下:
{
    "data": []
}

(2)方法2:

  • 但是為了不影響(或者降低)使用者體驗,增加一個引數,“isStill,表示是否還有下一頁”。該引數為true表示有,false表示無。此時,後端需要執行兩個分頁的sql,每次查詢都多執行後一次的分頁。這種效率比count()的效率要高很多。
{
    isStill:
true, "data": [] }

(3)方法3:

  • 把查詢總條數和查詢源資料分為兩個介面。每次查詢時,只是分頁的第一頁需要同時查兩個介面。並且當查詢條件改變時,需要同時查兩個介面。由前端判斷查詢條件是否改變了。注意,在查詢總條數時,務必對sql進行簡化,越簡單越好。
    (該方案,其實還有一種實現,就是由後端對總條數進行快取,由後端判斷查詢條件是否改變。但是我建議使用前端判斷的方法)
    在這裡插入圖片描述

  • 方法一:
    缺點是,使用者不知道下一頁是否還有資料,只有當點選了下一頁按鈕後才會知道;
    優點是,效率高;

  • 方法二:
    缺點是,多執行了一個分頁的sql,效率較低;
    優點是,使用者體驗好一些;

  • 方法三:
    個人推薦!


在執行count()查總條數的sql時,使用最簡單的sql進行(比如,去掉排序,去掉多餘的表聯合,使用count(1)代替count(*)等);
但是,如果連第一次count()都慢的查不出來時,那就沒辦法了,要不做分表分庫,要不使用方法二。


慢查詢一是,會嚴重降低資料庫效能,如果有多個應用程式都需要操作資料庫的話,會導致所有應用都無法使用(我在生產環境就遇到了這個問題,非常嚴重的問題,生產環境中整個系統無法使用,原因就是mysql卡死);二是,資料查詢非常慢,使用者等待時間過長,使用者體驗非常差,而且還可能造成前端請求超時。