偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

加了個(gè)索引,SQL性能竟然慢了十倍!

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
在事務(wù)中通過索引檢索并鎖定行時(shí),如果鎖數(shù)量過多(超過閾值),數(shù)據(jù)庫(kù)可能將鎖升級(jí)為表鎖,嚴(yán)重降低并發(fā)性能。

前言

最近星球中有小伙伴問我:加了索引,SQL查詢效率一定會(huì)提升嗎?

答案是否定的。

讓我想起了幾年前查詢訂單的場(chǎng)景。

優(yōu)化前下面這條SQL的查詢耗時(shí)是0.5s。

SELECT * FROM orders WHERE user_id = 10086;

添加了下面的索引:

CREATE INDEX idx_user ON orders(user_id);

再次執(zhí)行上面的查詢SQL語(yǔ)句,此時(shí)的耗時(shí)卻是5.2s。

出現(xiàn)了非常神奇的一幕:加了索引,SQL查詢性能反而慢了10倍。

作為一個(gè)踩過無數(shù)數(shù)據(jù)庫(kù)性能坑的老司機(jī),今天跟大家一起聊聊那些“加了索引反而更慢”的詭異場(chǎng)景。

1. 索引失效

加了索引之后,你以為它在工作,其實(shí)它在摸魚,因?yàn)樗赡芤呀?jīng)失效了。

1.1 最左前綴原則

如果查詢條件的順序不對(duì),努力白費(fèi)。

復(fù)合索引 (a, b, c) 生效的關(guān)鍵在于最左前綴匹配

用戶表創(chuàng)建了名稱、年齡和城市這三個(gè)字段的復(fù)合索引:

CREATE INDEX idx_user ON user(name, age, city);

? 有效:使用最左列 name

SELECT * FROM user WHERE name = '蘇三';

? 有效:使用最左前綴 (name, age)

SELECT * FROM user WHERE name = '蘇三' AND age = 30;

? 失效:跳過了最左列 name

SELECT * FROM user WHERE age = 30;

? 失效:未使用最左前綴

SELECT * FROM user WHERE city = '北京';

原理:復(fù)合索引的存儲(chǔ)結(jié)構(gòu)類似于電話簿(先按姓排序,再按名排序)。

如果跳過“姓”直接查“名”,索引就失效了。

1.2 函數(shù)操作

函數(shù)操作會(huì)讓索引瞬間失憶。

對(duì)索引列做計(jì)算、函數(shù)轉(zhuǎn)換或類型轉(zhuǎn)換,會(huì)導(dǎo)致索引失效:

? 失效:對(duì)索引列使用函數(shù):

SELECT * FROM user WHERE YEAR(create_time) = 2023;

? 失效:隱式類型轉(zhuǎn)換 (phone 是 varchar)

SELECT * FROM user WHERE phone = 13800138000;

? 有效:避免函數(shù)操作

SELECT * FROM user WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';

可以使用BETWEEN...AND查詢時(shí)間范圍。

原理:索引存儲(chǔ)的是列的原始值。對(duì)值進(jìn)行修改后,數(shù)據(jù)庫(kù)無法在索引樹中定位原始值。

1.3 范圍查詢

范圍查詢(><、BETWEEN)會(huì)截?cái)?/span>復(fù)合索引中后續(xù)列的匹配:

索引 (age, salary)

SELECT * FROM employee 
WHERE age > 25        -- ? age 范圍查詢
  AND salary = 10000; -- ? salary 無法使用索引

會(huì)導(dǎo)致salary的索引失效。

原理age>25 匹配到的是一系列值(非精確值),數(shù)據(jù)庫(kù)無法高效地對(duì) salary 進(jìn)行索引過濾。

2. 索引維護(hù)成本

天下沒有免費(fèi)的午餐,索引是有額外的維護(hù)成本的。

2.1 DML 操作變慢

每一次寫入都可能在負(fù)重前行。

每次 INSERT、UPDATEDELETE 操作,數(shù)據(jù)庫(kù)不僅要修改數(shù)據(jù),還要維護(hù)相關(guān)索引。

無索引表插入 100w 行:1.2 秒。

有 5 個(gè)索引的表插入 100w 行:15.8 秒 (實(shí)測(cè)差距 10 倍以上)。

場(chǎng)景:在寫多讀少的高并發(fā)場(chǎng)景下(如流水記錄),索引反而會(huì)成為性能瓶頸。

2.2 索引占用空間

索引可能會(huì)給磁盤和內(nèi)存帶來雙重壓力。

每個(gè)索引都是一棵 B+ 樹,存儲(chǔ)完整的索引列值(或組合值)。大表的索引輕松占據(jù)幾十GB空間。

MySQL中可以通過下面的SQL查看表索引大?。?/span>

SELECT 
  table_name AS `Table`,
  index_name AS `Index`,
  ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2) `Size(MB)`
FROM mysql.innodb_index_stats 
WHERE table_name = 'your_table';

后果:索引過大導(dǎo)致內(nèi)存中緩存命中率降低,物理 I/O 增加。

3. 優(yōu)化器的“錯(cuò)誤”選擇

有時(shí)候,可能會(huì)出現(xiàn)聰明反被聰明誤,加了索引可能會(huì)導(dǎo)致性能變慢。

3.1 統(tǒng)計(jì)信息過時(shí)

導(dǎo)航用了舊地圖。

優(yōu)化器依賴統(tǒng)計(jì)信息(如索引區(qū)分度、數(shù)據(jù)分布)來選擇索引。

如果統(tǒng)計(jì)信息過期,優(yōu)化器可能選擇性能更差的索引。

MySQL中我們可以通過下面的命令強(qiáng)制更新表統(tǒng)計(jì)信息:

ANALYZE TABLE user;

場(chǎng)景:當(dāng)表中數(shù)據(jù)發(fā)生劇烈變化(如大批量刪除/導(dǎo)入)后,統(tǒng)計(jì)信息未及時(shí)更新。

3.2 回表代價(jià)高昂

索引再好也怕“繞路”。

假如給user表給age創(chuàng)建了索引:

SELECT name, email FROM user 
WHERE age > 25;

即使 age 索引被使用,數(shù)據(jù)庫(kù)仍需根據(jù)索引中的主鍵 ID 回表查詢nameemail 字段。

當(dāng)符合條件的數(shù)據(jù)量很大時(shí),回表 I/O 可能遠(yuǎn)超索引掃描本身。

優(yōu)化方案:使用覆蓋索引(Covering Index),讓索引包含查詢所需的所有列。

創(chuàng)建覆蓋索引 (包含 age, name, email):

CREATE INDEX idx_age_covering ON user(age, name, email);

查詢可直接從索引獲取數(shù)據(jù),無需回表

SELECT name, email FROM user WHERE age > 25;

4. 索引過多

當(dāng)表上存在多個(gè)索引時(shí),優(yōu)化器需要評(píng)估每個(gè)索引的成本,選擇越多,決策時(shí)間越長(zhǎng)。

下面的查詢可能使用索引 A 或索引 B

SELECT * FROM orders 
WHERE user_id = 1001 
  AND status = 'completed';

優(yōu)化建議

  • 刪除重復(fù)或冗余索引
  • 合并可組合的索引
  • 使用工具分析索引使用率(如 sys.schema_unused_indexes

5. 鎖與并發(fā)

鎖的競(jìng)爭(zhēng)是一個(gè)看不見的戰(zhàn)場(chǎng)。

5.1 行鎖升級(jí)

在事務(wù)中通過索引檢索并鎖定行時(shí),如果鎖數(shù)量過多(超過閾值),數(shù)據(jù)庫(kù)可能將鎖升級(jí)為表鎖,嚴(yán)重降低并發(fā)性能。

場(chǎng)景:全表更新或刪除大量數(shù)據(jù)時(shí),索引的存在可能導(dǎo)致鎖升級(jí)。

5.2 索引分裂的阻塞

B+樹索引在插入數(shù)據(jù)時(shí)可能發(fā)生頁(yè)分裂。

這個(gè)過程需要加鎖,在高并發(fā)寫入場(chǎng)景下可能導(dǎo)致短暫阻塞。

總結(jié)

索引是把雙刃劍,用對(duì)場(chǎng)景是關(guān)鍵。

  • 理解原理:掌握最左前綴、索引失效條件、覆蓋索引等核心機(jī)制
  • 權(quán)衡成本:在寫密集場(chǎng)景謹(jǐn)慎添加索引,評(píng)估維護(hù)代價(jià)
  • 精準(zhǔn)設(shè)計(jì):按實(shí)際查詢模式設(shè)計(jì)復(fù)合索引,避免冗余
  • 關(guān)注統(tǒng)計(jì)信息:定期更新統(tǒng)計(jì)信息,確保優(yōu)化器決策準(zhǔn)確
  • 監(jiān)控分析:使用 EXPLAIN、慢查詢?nèi)罩镜裙ぞ叱掷m(xù)跟蹤索引效果

某電商平臺(tái)曾因在流水表上盲目添加索引,導(dǎo)致高峰時(shí)段寫入延遲飆升。

后經(jīng)分析,移除兩個(gè)非核心索引,寫入速度提升8倍,而相關(guān)查詢僅增加20毫秒——這正是索引取舍的藝術(shù)。

記?。?/span>索引不是越多越好,而是越準(zhǔn)越好。

真正的高手,懂得在索引的利刃上優(yōu)雅行走。

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2025-03-13 11:59:00

2023-09-07 11:29:36

API開發(fā)

2025-05-26 00:02:00

TypeScriptGo 語(yǔ)言前端

2009-12-15 21:49:05

2022-09-15 16:59:46

人工智能空調(diào)能源

2017-09-26 14:56:57

MongoDBLBS服務(wù)性能

2009-11-19 08:46:16

Windows 7系統(tǒng)驅(qū)動(dòng)

2022-10-27 07:09:34

DjangoAPIRedis

2021-09-13 10:25:35

開發(fā)技能代碼

2023-06-13 13:52:00

Java 7線程池

2019-03-27 13:45:44

MySQL優(yōu)化技巧數(shù)據(jù)庫(kù)

2025-02-24 08:10:00

C#代碼開發(fā)

2021-06-02 22:54:34

技巧 Git Clone項(xiàng)目

2020-09-16 16:07:34

Chrome插件瀏覽器

2024-04-19 14:50:00

find文件查找

2021-04-13 14:25:41

架構(gòu)運(yùn)維技術(shù)

2025-04-16 08:25:00

2021-08-30 15:41:23

代碼開源微軟

2022-10-15 07:49:18

代碼虛擬線程

2017-05-08 10:13:45

光螺旋速率信息
點(diǎn)贊
收藏

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