自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

別再用OFFSET和LIMIT分頁了!

大數(shù)據(jù) 數(shù)據(jù)分析
本文主要去理解 offset 為什么會在大數(shù)據(jù)量下的查詢帶來性能問題?思考完后,可以在思考下,如果分庫分表,你會這么去分頁呢?

 [[404581]]

圖片來自 Pexels

不需要擔(dān)心數(shù)據(jù)庫性能優(yōu)化問題的日子已經(jīng)一去不復(fù)返了。

隨著時(shí)代的進(jìn)步,隨著野心勃勃的企業(yè)想要變成下一個(gè) Facebook,隨著為機(jī)器學(xué)習(xí)預(yù)測收集盡可能多數(shù)據(jù)的想法的出現(xiàn)。

作為開發(fā)人員,我們要不斷地打磨我們的 API,讓它們提供可靠和有效的端點(diǎn),從而毫不費(fèi)力地瀏覽海量數(shù)據(jù)。

如果你做過后臺開發(fā)或數(shù)據(jù)庫架構(gòu),你可能是這么分頁的:

如果你真的是這么分頁,那么我不得不抱歉地說,你這樣做是錯(cuò)的。

你不以為然?沒關(guān)系。Slack、Shopify 和 Mixmax 這些公司都在用,我們今天將要討論的方式進(jìn)行分頁。

我想你很難找出一個(gè)不使用 OFFSET 和 LIMIT 進(jìn)行數(shù)據(jù)庫分頁的人。對于簡單的小型應(yīng)用程序和數(shù)據(jù)量不是很大的場景,這種方式還是能夠“應(yīng)付”的。

如果你想從頭開始構(gòu)建一個(gè)可靠且高效的系統(tǒng),在一開始就要把它做好。

今天我們將探討已經(jīng)被廣泛使用的分頁方式存在的問題,以及如何實(shí)現(xiàn)高性能分頁。

OFFSET 和 LIMIT 有什么問題?

正如前面段落所說的那樣,OFFSET 和 LIMIT 對于數(shù)據(jù)量少的項(xiàng)目來說是沒有問題的。

但是,當(dāng)數(shù)據(jù)庫里的數(shù)據(jù)量超過服務(wù)器內(nèi)存能夠存儲的能力,并且需要對所有數(shù)據(jù)進(jìn)行分頁,問題就會出現(xiàn)。

為了實(shí)現(xiàn)分頁,每次收到分頁請求時(shí),數(shù)據(jù)庫都需要進(jìn)行低效的全表掃描。

什么是全表掃描?全表掃描 (又稱順序掃描) 就是在數(shù)據(jù)庫中進(jìn)行逐行掃描,順序讀取表中的每一行記錄,然后檢查各個(gè)列是否符合查詢條件。

這種掃描是已知最慢的,因?yàn)樾枰M(jìn)行大量的磁盤 I/O,而且從磁盤到內(nèi)存的傳輸開銷也很大。

這意味著,如果你有 1 億個(gè)用戶,OFFSET 是 5 千萬,那么它需要獲取所有這些記錄 (包括那么多根本不需要的數(shù)據(jù)),將它們放入內(nèi)存,然后獲取 LIMIT 指定的 20 條結(jié)果。

也就是說,為了獲取一頁的數(shù)據(jù):

10萬行中的第5萬行到第5萬零20行

需要先獲取 5 萬行。這么做是多么低效?如果你不相信,可以看看這個(gè)例子:

https://www.db-fiddle.com/f/3JSpBxVgcqL3W2AzfRNCyq/1?ref=hackernoon.com

左邊的 Schema SQL 將插入 10 萬行數(shù)據(jù),右邊有一個(gè)性能很差的查詢和一個(gè)較好的解決方案。

只需單擊頂部的 Run,就可以比較它們的執(zhí)行時(shí)間。第一個(gè)查詢的運(yùn)行時(shí)間至少是第二個(gè)查詢的 30 倍。

數(shù)據(jù)越多,情況就越糟??纯次覍?10 萬行數(shù)據(jù)進(jìn)行的 PoC:

https://github.com/IvoPereira/Efficient-Pagination-SQL-PoC?ref=hackernoon.com

現(xiàn)在你應(yīng)該知道這背后都發(fā)生了什么:OFFSET 越高,查詢時(shí)間就越長。

替代方案

你應(yīng)該這樣做:

這是一種基于指針的分頁。

你要在本地保存上一次接收到的主鍵 (通常是一個(gè) ID) 和 LIMIT,而不是 OFFSET 和 LIMIT,那么每一次的查詢可能都與此類似。

為什么?因?yàn)橥ㄟ^顯式告知數(shù)據(jù)庫最新行,數(shù)據(jù)庫就確切地知道從哪里開始搜索(基于有效的索引),而不需要考慮目標(biāo)范圍之外的記錄。

比較這個(gè)查詢:

和優(yōu)化的版本:

返回同樣的結(jié)果,第一個(gè)查詢使用了 12.80 秒,而第二個(gè)僅用了 0.01 秒。

要使用這種基于游標(biāo)的分頁,需要有一個(gè)惟一的序列字段 (或多個(gè)),比如惟一的整數(shù) ID 或時(shí)間戳,但在某些特定情況下可能無法滿足這個(gè)條件。

我的建議是,不管怎樣都要考慮每種解決方案的優(yōu)缺點(diǎn),以及需要執(zhí)行哪種查詢。

如果需要基于大量數(shù)據(jù)做查詢操作,Rick James 的文章提供了更深入的指導(dǎo):

http://mysql.rjweb.org/doc.php/lists

如果我們的表沒有主鍵,比如是具有多對多關(guān)系的表,那么就使用傳統(tǒng)的 OFFSET/LIMIT 方式,只是這樣做存在潛在的慢查詢問題。

我建議在需要分頁的表中使用自動遞增的主鍵,即使只是為了分頁。

作者:極客小智

編輯:陶家龍

出處:toutiao.com/i6860655404431442444

 

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2022-10-27 21:34:28

數(shù)據(jù)庫機(jī)器學(xué)習(xí)架構(gòu)

2020-12-15 08:06:45

waitnotifyCondition

2022-09-07 07:37:06

LIMITOFFSET分頁

2020-12-04 10:05:00

Pythonprint代碼

2020-12-02 11:18:50

print調(diào)試代碼Python

2023-10-26 16:33:59

float 布局前段CSS

2021-05-25 09:30:44

kill -9Linux kill -9 pid

2021-01-29 11:05:50

PrintPython代碼

2020-12-03 09:05:38

SQL代碼方案

2020-09-18 07:01:38

分頁offsetlimit

2024-12-26 07:47:20

2022-01-27 07:48:37

虛擬項(xiàng)目Django

2020-07-17 07:15:38

數(shù)據(jù)庫ID代碼

2022-03-10 10:12:04

自動化腳本Bash

2024-06-12 13:54:37

編程語言字符串代碼

2019-03-12 14:48:29

路由器XBOXPS4

2023-06-26 08:20:02

openapi格式注解

2023-09-08 08:35:42

層疊樣式表CSS

2023-09-14 12:03:30

空指針判空

2023-04-10 08:07:48

MySQLlimitoffset
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號