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

MySQL 索引失效了吧?

數(shù)據(jù)庫(kù) MySQL
MySQL 索引在優(yōu)化查詢性能中扮演著關(guān)鍵角色,尤其是有聯(lián)查或者數(shù)據(jù)量大的情況,但是,一些操作或?qū)懛〞?huì)導(dǎo)致索引失效,索引失效,等于無(wú)用功了。

前幾天一個(gè)小伙伴說(shuō)面試可能掛了,他說(shuō)面試官問(wèn)他MySQL 索引失效的原因可能有哪些時(shí),他腦袋一懵,竟然啥都沒(méi)說(shuō)出來(lái),面試官的笑容給他留下了深刻的印象。

MySQL 索引在優(yōu)化查詢性能中扮演著關(guān)鍵角色,尤其是有聯(lián)查或者數(shù)據(jù)量大的情況,但是,一些操作或?qū)懛〞?huì)導(dǎo)致索引失效,索引失效,等于無(wú)用功了。

下面說(shuō)一下 MySQL 索引失效的幾種常見(jiàn)情況。

使用函數(shù)或表達(dá)式操作索引列

如果在查詢條件中對(duì)索引列使用了函數(shù)或表達(dá)式,MySQL 無(wú)法利用索引。

例如下面的語(yǔ)句,本來(lái)name列是有索引的

SELECT * FROM users WHERE LEFT(name, 3) = 'Tom';

但是,LEFT(name, 3) 對(duì) name 列進(jìn)行了函數(shù)操作,這就導(dǎo)致 MySQL 無(wú)法直接使用索引。

解決方法

第一種就是避免在索引列上使用函數(shù),改為使用 like查詢,注意是后面加 %

SELECT * FROM users WHERE name LIKE 'Tom%';

第一種方式是針對(duì)普通索引來(lái)說(shuō)的,還有一種解決方法,那就是直接加前綴索引,例如

CREATE INDEX idx_name_prefix ON users (LEFT(name, 3));

前綴索引,一般用于長(zhǎng)文本列(用戶名、地址)、減少索引存儲(chǔ)空間、提高索引創(chuàng)建和查詢性能等場(chǎng)景。

查詢條件中使用隱式類型轉(zhuǎn)換

如果索引列和查詢條件的數(shù)據(jù)類型不一致,MySQL 會(huì)進(jìn)行隱式類型轉(zhuǎn)換,導(dǎo)致索引失效。

例如:

SELECT * FROM users WHERE phone_number = 1234567890;

如果 phone_number 列是 VARCHAR 類型,而查詢條件中的值是數(shù)字類型,MySQL 會(huì)將 phone_number 轉(zhuǎn)換為數(shù)字類型,導(dǎo)致索引失效。

解決方法 

確保查詢條件的數(shù)據(jù)類型與列類型一致:

SELECT * FROM users WHERE phone_number = '1234567890';

使用不等操作符

當(dāng)查詢條件中使用 <> 或 NOT IN,MySQL 無(wú)法高效利用索引。

例如

SELECT * FROM users WHERE age <> 30;

不等操作符會(huì)使查詢范圍不連續(xù),MySQL 通常會(huì)選擇全表掃描。

解決方法

如果可以的話,建議嘗試調(diào)整查詢邏輯,例如

-- 優(yōu)化方案1:IN 列表
SELECT * FROM users WHERE status IN (2, 3, 4);

-- 優(yōu)化方案2:邏輯重構(gòu)
SELECT * FROM users WHERE status > 1 AND status < 5;

使用 OR 條件且未對(duì)所有列加索引

當(dāng) OR 條件連接的多個(gè)列中,并非所有列都有索引時(shí),索引會(huì)失效。

例如下面語(yǔ)句,只要name和age列有至少一個(gè)沒(méi)有加索引,索引都不會(huì)被命中

SELECT * FROM users WHERE name = 'Tom' OR age = 30;

name 列有索引,而 age 列沒(méi)有索引,會(huì)導(dǎo)致全表掃描。

解決方法

確保 OR 條件的每一列都加上索引,或者改用 UNION或UNION ALL

SELECT * FROM users WHERE name = 'Tom'
UNION
SELECT * FROM users WHERE age = 30;

且 UNION和 UNION ALL也是有差別的,UNION去重,性能略低,UNION ALL不去重,性能更高

索引列在范圍查詢后再用其他條件篩選

在范圍查詢(如 <、>、BETWEEN、LIKE)后再對(duì)其他列篩選時(shí),其他列的索引可能失效。

例如:

SELECT * FROM users WHERE age > 30 AND name = 'Tom';

MySQL 使用聯(lián)合索引時(shí),范圍查詢會(huì)中斷索引的使用,后續(xù)的 name = 'Tom' 條件無(wú)法利用索引。

解決方法 調(diào)整索引順序或邏輯,確保查詢優(yōu)化。

設(shè)置聯(lián)合索引時(shí),建議將區(qū)分度最高的列放在最左側(cè),使用下列方法可以評(píng)估各個(gè)列的區(qū)分度大小

SELECT 
    COUNT(DISTINCT username) / COUNT(*) AS username_selectivity,
    COUNT(DISTINCT age) / COUNT(*) AS age_selectivity 
FROM users;

索引列的前綴未完全匹配

對(duì)于多列聯(lián)合索引,必須遵循最左前綴匹配規(guī)則,否則索引會(huì)部分或完全失效。

例如:

下面的語(yǔ)句,沒(méi)有遵守最左前綴原則,導(dǎo)致索引失效

CREATE INDEX idx_name_age ON users (name, age);
SELECT * FROM users WHERE age = 30; -- 索引失效

查詢條件未包含索引的第一列 name,無(wú)法觸發(fā)聯(lián)合索引。

解決方法

確保遵循最左前綴匹配規(guī)則:

SELECT * FROM users WHERE name = 'Tom' AND age = 30;

LIKE 模式中通配符使用不當(dāng)

前面也提到了這種情況,如果 LIKE 查詢以 % 開(kāi)頭,索引會(huì)失效。

例如:

SELECT * FROM users WHERE name LIKE '%Tom';

以 % 開(kāi)頭無(wú)法通過(guò)索引定位記錄。

解決方法

盡量避免以 % 開(kāi)頭,改為:

SELECT * FROM users WHERE name LIKE 'Tom%';

但,模糊查詢本身性能就不高,所以,如果有需要like查詢的情況,可以分析一下是否需要全文索引,也就是 FULLTEXT。

我之前修改過(guò)一個(gè)老系統(tǒng)中特別慢的接口,數(shù)據(jù)量夠大,而且在很多字段用了 like查詢,改用全文索引后,性能提升非常明顯,10倍以上。

-- 創(chuàng)建全文索引
CREATE FULLTEXT INDEX idx_fulltext ON users (username);

-- 全文搜索
SELECT * FROM users 
WHERE MATCH(username) AGAINST('張*' IN BOOLEAN MODE);

查詢結(jié)果集太小,優(yōu)化器選擇全表掃描

MySQL 的查詢優(yōu)化器會(huì)根據(jù)查詢成本決定是否使用索引。如果查詢結(jié)果集較小,MySQL 可能選擇全表掃描。

例如:

SELECT * FROM users WHERE is_active = 1;

如果 is_active = 1 的記錄占比非常高,MySQL 會(huì)認(rèn)為全表掃描更高效。

解決方法

這種情況下,索引可能無(wú)法優(yōu)化查詢性能。

索引統(tǒng)計(jì)信息不準(zhǔn)確

MySQL 會(huì)根據(jù)統(tǒng)計(jì)信息決定索引使用與否。如果統(tǒng)計(jì)信息不準(zhǔn)確,可能導(dǎo)致索引失效。

索引的統(tǒng)計(jì)信息過(guò)期,影響查詢優(yōu)化器的決策。

解決方法

定期執(zhí)行 ANALYZE TABLE,調(diào)整 innodb_stats_persistent,以保持統(tǒng)計(jì)信息準(zhǔn)確。 手動(dòng)更新統(tǒng)計(jì)信息:

ANALYZE TABLE users;

IS NULL 和 IS NOT NULL 操作

在某些 MySQL 版本中,IS NULL 和 IS NOT NULL 條件會(huì)導(dǎo)致索引失效。

例如:

SELECT * FROM users WHERE age IS NOT NULL;

MySQL 無(wú)法直接通過(guò)索引處理 NULL 值。

解決方法

盡量避免大量 NULL 值,或改用其他標(biāo)識(shí)。

你學(xué)廢了了嗎?

責(zé)任編輯:武曉燕 來(lái)源: 古時(shí)的風(fēng)箏
相關(guān)推薦

2020-12-08 09:45:07

MySQL數(shù)據(jù)庫(kù)索引

2025-04-02 00:00:04

2024-04-19 13:57:30

索引數(shù)據(jù)庫(kù)查詢

2024-01-05 14:20:55

MySQL索引優(yōu)化器

2022-06-27 07:23:44

MySQL常量優(yōu)化

2022-06-27 09:45:22

MySQL索引

2022-10-17 00:04:30

索引SQL訂單

2020-12-09 10:10:24

MySQL數(shù)據(jù)庫(kù)算法

2022-05-26 08:23:05

MySQL索引數(shù)據(jù)庫(kù)

2024-07-03 09:15:33

MySQL表達(dá)式索引

2024-05-08 08:18:05

索引失效場(chǎng)景

2022-02-28 08:55:31

數(shù)據(jù)庫(kù)MySQL索引

2020-09-28 15:34:38

ElasticSear索引MySQL

2015-10-30 15:55:43

MySQL

2024-07-08 12:40:18

MySQL索引失效

2020-12-11 08:02:16

索引MySQL存儲(chǔ)

2020-10-16 17:20:21

索引MySQL數(shù)據(jù)庫(kù)

2011-03-31 13:51:54

MySQL索引

2024-03-29 08:10:43

索引失效SQL

2022-01-09 18:32:03

MySQL SQL 語(yǔ)句數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

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