分頁設計的難點問題

2021-10-25 14:39:14 字數 4384 閱讀 7969

分頁有三種樣式:普通分頁、首末分頁、跳轉分頁

google的翻頁功能的設計

所以頂部的分頁鏈結作用不大。除非是網頁一屏就顯示所有的內容,頂部的分頁鏈結才會起到作用,但這時候仍然是可有可無的。

分頁設計的兩大難點問題

1.資料重複

2.一次性載入大量資訊,載入緩慢

資料重複

傳統分頁的話,一般只考慮傳頁數和每頁資料條數這兩個引數給後端,為了方便後面描述,我們給這個傳參方式起個名字叫傳統分頁。

這種傳參方式對於靜態資料(資料不會變動)的分頁是沒問題的,因為每條資料的順序、資料的總量,都是不變的。

如果出現資料順序變動或者資料總量變動的分頁需求時,單純的傳page和limit已經不能解決了。不同的需求需要顯示的列表也不一樣。

關於列表分頁主要關係到兩個方面:

ø總量(列表頭插入了新資料)

ø排列順序

傳統分頁在總量不變,排列順序不變的列表下是沒有任何問題的,但只要這兩個要素其中乙個是變化的。

例如:總量不變,排列順序改變:排行榜

排行榜

現在有乙個積分排行榜

假定每頁顯示3條資料,在某一時刻拿第一頁資料時,得到 a、b、c三條資料。就在此時,使用者d突然增加了100積分,最新的排行榜情況變成了

傳統分頁情況下,獲取第二頁資料時,從當前排行榜第四條資料開始獲取,得到 c、e,使用者看到的資料就變成 a、b、c、c、e。

c出現了2次,而且d消失了。這就是傳統分頁用在資料排列順序會改變的列表時會出現的問題,因為列表順序改變導致出現重複資料和丟失資料。

這種總量不變,排列順序改變的分頁問題暫時有兩種方案解決:

一次性取出、

排行榜快照、通過變動記錄表拿資料。

一次性取出(針對特殊需求)

這裡說的一次性取出是針對類似「top100」這種取有限條數的需求。

排行榜主要的分頁問題是影響排名的字段的值在不斷變化導致列表順序不斷改變,我們現在可以一次性取出整個列表但是又擔心複雜的資料結構導致伺服器效能問題。

如果把整個功能拆分一下,用非同步的思想來做這個功能設計如何呢?

分兩個介面來做這個功能:獲取排行榜列表和獲取使用者排行榜資料。

獲取排行榜列表介面一次性取整個排名列表的使用者id和排名相關的字段資料,這樣就保證了整個列表的排序是不變的同時,又不增大伺服器效能。

獲取使用者排行榜資料介面 負責取排行榜要顯示的使用者的其他資料,這個介面接受多個使用者id的作為引數。

這個介面做了類似分頁的功能,前端每次從排行榜中按分頁的方式按順序取部分使用者id,然後通過這個介面獲取具體資料顯示給使用者。

下面以例子的方式來做具體說明:

這是乙個積分排行 top100

這裡的排行條件是 積分,那我們的 獲取排行榜列表介面 只需要取「使用者id」和「積分」即可,剩下的 「暱稱」、「勝率」等資料通過 獲取使用者排行榜資料介面獲取。

前端先請求列表介面,獲取到一下資料:

然後根據這個列表資料,先取前10條的使用者id:5、12、60、2、77… 請求獲取使用者排行榜資料介面,把獲得的使用者資料填充到排行榜中。

當使用者下滑載入更多資料時再去列表取在11-20的使用者id重複上面的操作。

如果是 top100 的需求,這個方案是比較推薦的,因為沒有效能和儲存空間上的額外消耗。

排行榜快照(推薦)

可以通過寫乙個定時指令碼,每5分鐘生成一次排行榜的快照資訊並存下來。介面請求時直接從快照中取資料,這一定程度上解決了列表排序一直在變化問題。

這裡之所以說只解決了一定程度,是因為在每次重新整理快照資料的時候,可能有使用者剛好卡在這個時間點之間去請求(重新整理快照前使用者請求了第一頁資料,重新整理快照後使用者請求第二頁,這就出現傳統分頁同樣的問題了)。

可以通過在快照中加上版本號來解決問題。

例如在生成快照的時候以當前時間戳作為版本號跟快照資料一起儲存,同時需要系統儲存多份快照資料以便使用者獲取舊快照資料。請求介面時預設拿最新版本的快照,如果介面傳入了版本號就拿對應版本號的快照資料。

優點:

通俗易懂,傳參方式跟傳統分頁類似。

請求處理效率高,生成快照時可以把資料進行處理再儲存(例如日期格式轉換、型別key值轉型別名字等),使得請求到來時獲取的資料可以直接返回給使用者,無需再做處理。

易於測試和排查,在生成快照那一刻已經決定了整個列表的資料展示,測試和錯誤排查很方便。

缺點:

實時性比較差,使用者拿到的資料不是最新的。

需要額外儲存空間,需要額外的地方儲存多個版本的快照資料。

需要定時器,對於本來存在定時器的系統架構,這一點不算缺點。

通過變動記錄表拿資料

每個完備的系統都會有資料變動的記錄表,用於追蹤資料變動和操作明細。記錄變記錄著資料每次變動前後的變化和變動時間,這一特性為使得資料的每次變動都有跡可循,我們就是利用這一點來做排行榜的分頁。

我們分頁出問題的地方就是因為資料在不斷變化導致排序不停改變。

上面說到每次資料變動都會有記錄,那我們只需要根據某一時刻之前使用者的資料來做排名,是不是就解決資料不斷變動這個問題。

文字表達可能不太直觀,看下面的資料演示應該能比較好理解。假定使用者 a、b、c 初始預設都是100積分

表:score_log

**中為了方便檢視,用了varchar型別表示時間,在實際應用中應該使用int型來儲存,因為需要加索引。

假定在03分的時候請求了資料,通過sql語句就可以拿到03分之前的資料排行。

得到第一頁資料:

第二頁資料:

關於這種方式的請求,前端需要記錄發起第一次請求時的時間,以後每頁的請求都帶著這個時間。

優點:

ø無需額外儲存資料,利用系統原有資料結構來解決資料變動問題,也無需做多版本控制。

ø資料相對實時,每次拿到的排行榜資料都是請求第一頁那一刻最新的資料。

缺點:

ø效率相對較差,由於資料需要實時排序和獲取,效率相比排行榜要低。而且上面例子只取了記錄表中最基礎的資料,實際需求中一般需要關聯更多的表去取資訊,所以效率將隨著需求負責度增大而降低。

ø只適用於使用者量不大的情況,由於資料變動記錄表的資料量隨著使用者量的遞增是呈倍數遞增的,所以使用者量達到一定程度的情況下,這個方式效率會變得相當低。

用傳統分頁方式,此時獲取第二頁會得到id 3、2、1,這裡id 3 就重複取出來了。

介面傳參:

先說一下不嚴謹情況下這個分頁的實現方式:

這種方式會有兩個問題:

優化:

1.分表:(固定某個表存多少數量的資料:例如:一張表存100w的資料量);

2.優化sql和建立適合的索引(復合索引);

3.使用redis快取。(redis存乙份id.然後mysql存乙份id每次插入刪除的時候同步即可。查詢的時候只需要從redis裡面找出適合的10個id,然後到mysql裡面查詢出10條記錄即可);

4.總數要單獨處理:涉及到總數操作,專門維護乙個總數。(例如:新註冊乙個會員,總數值加1,需要總數的時候直接拿這個總數,也可以在這個表上新增了觸發器並建立乙個專門用來統計總行數的表新增更新刪除該錶就會觸發,分析條件後直接把統計表的相應字段累加,查詢的時候直接讀取統計表中的相應欄位就可以了準確度沒問題,如果有條件查詢分頁,那麼分頁表的資料就發揮不了左右)。

5.可通過定時任務去批量查詢總數,例如:開啟10個執行緒去批量計算總數,然後再各自相加即可,不過這樣會導致記憶體(cpu)過高,而造成記憶體溢位。

6.修改原有介面內容,單獨去查詢總數,需要即去查詢。也可以用id建立一定的區間,比如查詢最新的記錄,每次只是查詢2w條的記錄。每次只要查最新的一條記錄,id是自增欄位,取當前的這個id值就可以大約知道總條數了(注意:專案裡並不會刪除參與記錄),但是這種不適合帶條件的查詢。

陪學網(www.pexue.com)專注於產品管理類課程的開發與製作,志在為產品經理、互動設計、平面設計、需求人員分享最新、最好的產品類課程。陪學網:陪伴學習、陪伴成長。

推薦系統的重點 難點問題

1 特徵提取問題 2 模型過擬合問題 可擴充套件性問題 推薦系統中推薦演算法無法完全掌握使用者每個方面的興趣和需求,因為使用者之前沒有對足夠多類別的物件進行評價。過擬合現象是指系統推薦給使用者的物件與使用者剛剛看過的不是太相似,就是太不相關。模型過擬合 過學習 的問題本質上來自於資料的不完備性,這在...

學習前端遇到的問題與難點

1.相容的問題.checkbox name checkboxbtn checked true 這裡的checked true,在1.6以上是不接受的 checkbox name checkboxbtn attr checked 在1.6以上,顯示checked和undifine,2.頁面座標的問題 ...

學習前端遇到的問題與難點

1.相容的問題.checkbox name checkboxbtn checked true 這裡的checked true,在1.6以上是不接受的 checkbox name checkboxbtn attr checked 在1.6以上,顯示checked和undifine,2.頁面座標的問題 ...