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

面試官:limit 100w,10為什么慢?如何優(yōu)化?

數(shù)據(jù)庫(kù) MySQL
在數(shù)據(jù)庫(kù)查詢中,當(dāng)使用 LIMIT x, y 分頁(yè)查詢時(shí),如果 x 值越大,查詢速度可能會(huì)變慢。這主要是因?yàn)閿?shù)據(jù)庫(kù)需要掃描和跳過(guò) x 條記錄才能返回 y 條結(jié)果。隨著 x 的增加,需要掃描和跳過(guò)的記錄數(shù)也增加,從而導(dǎo)致性能下降。

在 MySQL 中,limit X,Y 的查詢中,X 值越大,那么查詢速度也就越慢,例如以下示例:

  • limit 0,10:查詢時(shí)間大概在 20 毫秒左右。
  • limit 1000000,10:查詢時(shí)間可能是 15 秒左右(1秒等于 1000 毫秒),甚至更長(zhǎng)時(shí)間。

所以,可以看出,limit 中 X 值越大,那么查詢速度都越慢。

這個(gè)問(wèn)題呢其實(shí)就是 MySQL 中典型的深度分頁(yè)問(wèn)題。那問(wèn)題來(lái)了,為什么 limit 越往后查詢?cè)铰??如何?yōu)化查詢速度呢?

為什么limit越來(lái)越慢?

在數(shù)據(jù)庫(kù)查詢中,當(dāng)使用 LIMIT x, y 分頁(yè)查詢時(shí),如果 x 值越大,查詢速度可能會(huì)變慢。這主要是因?yàn)閿?shù)據(jù)庫(kù)需要掃描和跳過(guò) x 條記錄才能返回 y 條結(jié)果。隨著 x 的增加,需要掃描和跳過(guò)的記錄數(shù)也增加,從而導(dǎo)致性能下降。

例如 limit 1000000,10 需要掃描 1000010 行數(shù)據(jù),然后丟掉前面的 1000000 行記錄,所以查詢速度就會(huì)很慢。

優(yōu)化手段

對(duì)于 MySQL 深度分頁(yè)比較典型的優(yōu)化手段有以下兩種:

  • 起始 ID 定位法:使用最后查詢的 ID 作為起始查詢的 ID。
  • 索引覆蓋+子查詢。

1.起始ID定位法

起始 ID 定位法指的是 limit 查詢時(shí),指定起始 ID。而這個(gè)起始 ID 是上一次查詢的最后一條 ID。例如上一次查詢的最后一條數(shù)據(jù)的 ID 為 6800000,那我們就從 6800001 開(kāi)始掃描表,直接跳過(guò)前面的 6800000 條數(shù)據(jù),這樣查詢的效率就高了,具體實(shí)現(xiàn) SQL 如下:

select name, age, gender
from person
where id > 6800000 -- 核心實(shí)現(xiàn) SQL
order by id limit 10;

其中 id 字段為表的主鍵字段。

為什么起始ID查詢效率高呢?

因此這種查詢是以上一次查詢的最后 ID 作為起始 ID 進(jìn)行查詢的,而上次的 ID 已經(jīng)定位到具體的位置了,所以只需要遍歷 B+ 樹(shù)葉子節(jié)點(diǎn)的雙向鏈表(主鍵索引的底層數(shù)據(jù)結(jié)構(gòu))就可以查詢到后面的數(shù)據(jù)了,所以查詢效率就比較高,如下圖所示:

如果上次查詢結(jié)果為 9,之后再查詢時(shí),只需要從 9 之后再遍歷 N 條數(shù)據(jù)就能查詢出結(jié)果了,所以效率就很高。

優(yōu)缺點(diǎn)分析

這種查詢方式,只適合一頁(yè)一頁(yè)的數(shù)據(jù)查詢,例如手機(jī) APP 中刷新聞時(shí)那種瀑布流方式。

但如果用戶是跳著分頁(yè)的,例如查詢完第 1 頁(yè)之后,直接查詢第 250 頁(yè),那么這種實(shí)現(xiàn)方式就不行了。

2.索引覆蓋+子查詢

此時(shí)我們?yōu)榱瞬樵冃剩梢允褂盟饕采w加子查詢的方式,具體實(shí)現(xiàn)如下。

假設(shè),我們未優(yōu)化前的 SQL 如下:

select name, age, gender
from person
order by createtime desc 
limit 1000000,10;

在以上 SQL 中,createtime 字段創(chuàng)建了索引,但查詢效率依然很慢,因?yàn)樗〕?100w 完整的數(shù)據(jù),并需要讀取大量的索引頁(yè),和進(jìn)行頻繁的回表查詢,所以執(zhí)行效率會(huì)很低。

此時(shí),我們可以做以下優(yōu)化:

SELECT p1.name, p1.age, p1.gender
FROM person p1
JOIN (
    SELECT id FROM person ORDER BY createtime desc LIMIT 1000000, 10
) AS p2 ON p1.id = p2.id;

相比于優(yōu)化前的 SQL,優(yōu)化后的 SQL 將不需要頻繁回表查詢了,因?yàn)樽硬樵冎兄徊樵冎麈I ID,這時(shí)可以使用索引覆蓋來(lái)實(shí)現(xiàn)。那么子查詢就可以先查詢出一小部分主鍵 ID,再進(jìn)行查詢,這樣就可以大大提升查詢的效率了。

索引覆蓋(Index Coverage)是一種數(shù)據(jù)庫(kù)查詢優(yōu)化技術(shù),它指的是在執(zhí)行查詢時(shí),數(shù)據(jù)庫(kù)引擎可以直接從索引中獲取所有需要的數(shù)據(jù),而不需要再回表(訪問(wèn)主鍵索引或者表中的實(shí)際數(shù)據(jù)行)來(lái)獲取額外的信息。這種方式可以減少磁盤 I/O 操作,從而提高查詢性能。

責(zé)任編輯:姜華 來(lái)源: 磊哥和Java
相關(guān)推薦

2025-02-04 12:17:06

LIMIT數(shù)據(jù)性能

2025-01-22 08:29:18

索引查詢優(yōu)化

2022-11-16 17:10:25

MySQL數(shù)據(jù)事務(wù)

2022-07-06 13:48:24

RedisSentinel機(jī)制

2019-09-16 09:34:39

2024-03-08 07:53:19

LockMonitor線程

2023-12-06 09:10:28

JWT微服務(wù)

2021-06-23 06:48:42

秒殺Java電商

2020-10-24 15:50:54

Java值傳遞代碼

2021-02-19 10:02:57

HTTPSJava安全

2021-01-21 07:53:29

面試官Promis打印e

2021-12-20 10:30:33

forforEach前端

2023-12-20 14:35:37

Java虛擬線程

2015-08-13 10:29:12

面試面試官

2022-12-27 08:39:54

MySQL主鍵索引

2023-07-05 08:17:38

JDK動(dòng)態(tài)代理接口

2024-03-06 09:22:23

C#數(shù)據(jù)庫(kù)判重

2024-02-19 11:49:23

JavaBitMap類型

2022-12-22 14:32:37

JavaScript編程語(yǔ)言

2023-06-05 07:57:53

Kafka消息事務(wù)消息
點(diǎn)贊
收藏

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