欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文揭秘MySQL索引失效原因與優(yōu)化方案

 更新時間:2025年07月16日 09:56:52   作者:都叫我大帥哥  
這篇文章主要為大家詳細介紹了MySQL中出現(xiàn)索引失效的原因以及相關優(yōu)化方案,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

索引小劇場:某日,程序員小明發(fā)現(xiàn)SQL查詢突然從0.1秒暴增到5秒。索引委屈巴巴:“主人,不是我不干活,是你老給我穿小鞋?。?rdquo;

一、索引:數(shù)據(jù)庫世界的超級目錄

索引如同圖書館的圖書目錄:

  • 聚簇索引:書架按編號排序(數(shù)據(jù)即索引)
  • 二級索引:獨立目錄卡片(需回表查詢)
  • B+樹結(jié)構(gòu):多叉平衡樹,3層可存2000萬數(shù)據(jù)(假設每頁16KB)
// Java中創(chuàng)建索引示例(Spring Data JPA)
@Entity
@Table(indexes = @Index(columnList = "username,email", name = "idx_user_identity"))
public class User {
    @Id
    private Long id;
    private String username; // 索引列
    private String email;    // 索引列
    private Integer age;
    // Getter/Setter省略
}

二、索引罷工的五大罪狀(失效場景)

1.最左匹配原則

-- 創(chuàng)建聯(lián)合索引
CREATE INDEX idx_soldier ON army(squad, team, soldier);

-- 有效查詢 ?
SELECT * FROM army WHERE squad = 'A'; 
SELECT * FROM army WHERE squad = 'A' AND team = 2;

-- 索引罷工 ?
SELECT * FROM army WHERE team = 2;        -- 跳過squad
SELECT * FROM army WHERE soldier = 'Tom'; -- 跳過頭兩列

原理:聯(lián)合索引如電話簿,必須先按省→市→姓名查找,跳級查詢無效

2.隱式轉(zhuǎn)換

// Java代碼中常見的類型錯誤
@Query("SELECT u FROM User u WHERE u.username = :name") // username是varchar
User findByUsername(@Param("name") Integer name); // 傳入Integer類型!

執(zhí)行SQL:

SELECT * FROM user WHERE username = 100; 
-- 類型轉(zhuǎn)換導致:username列索引失效!

原理:MySQL被迫對索引列做類型轉(zhuǎn)換(CAST),如同要求目錄同時支持字母和數(shù)字排序

3.函數(shù)計算

-- 生日字段有索引
SELECT * FROM user WHERE YEAR(birthday) = 1990;  -- 索引失效 ?

-- 優(yōu)化方案 ?
SELECT * FROM user 
WHERE birthday BETWEEN '1990-01-01' AND '1990-12-31';

血淚案例:某電商平臺因DATE(create_time)查詢導致CPU飆升90%

4.范圍查詢阻斷連鎖反應

CREATE INDEX idx_sales ON orders(region, amount, product);

-- 索引僅用到 region 和 amount ?
SELECT * FROM orders 
WHERE region = 'East' 
  AND amount > 1000 
  AND product = 'Phone';

破解方案:調(diào)整索引順序為(region, product, amount)

5.OR引發(fā)的危機

-- 即使name和age都有獨立索引
SELECT * FROM user WHERE name = 'John' OR age = 30;
-- MySQL通常選擇全表掃描!

優(yōu)化方案:改用UNION

SELECT * FROM user WHERE name = 'John'
UNION ALL
SELECT * FROM user WHERE age = 30;

三、原理深潛:B+樹為何罷工

當發(fā)生索引失效時:

  • 優(yōu)化器計算使用索引的成本
  • 若預計掃描超過30%數(shù)據(jù)(默認閾值)
  • 選擇全表掃描作為“更優(yōu)方案”

冷知識FORCE INDEX可強制使用索引,但如同用槍逼工人干活,慎用!

四、避坑指南:四大生存法則

前綴索引策略

ALTER TABLE article ADD INDEX idx_title(title(10));

對長文本取前N個字符(需保證區(qū)分度>90%)

覆蓋索引護盾

-- 建立覆蓋索引
CREATE INDEX idx_covering ON orders(user_id, status, amount);

-- 查詢只需索引列
SELECT user_id, status FROM orders WHERE user_id = 1001;

索引下推(ICP)

MySQL 5.6+ 黑科技:

在存儲引擎層提前過濾數(shù)據(jù)

索引散兵清理

-- 每月檢查無用索引
SELECT * FROM sys.schema_unused_indexes;

五、最佳實踐:索引優(yōu)化軍規(guī)

場景錯誤做法正確方案
分頁查詢LIMIT 1000000,10WHERE id > last_id LIMIT
狀態(tài)字段索引建在gender列用枚舉值或放棄索引
JSON字段查詢WHERE json->'$.id'=10生成列+索引
模糊查詢LIKE '%關鍵字%'全文索引或ES
// 分頁優(yōu)化Java實現(xiàn)
public Page<User> getUsers(Long lastId, int limit) {
    String sql = "SELECT * FROM user WHERE id > ? ORDER BY id ASC LIMIT ?";
    return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(), lastId, limit);
}

六、面試考點區(qū)

問題1:varchar字段傳int參數(shù)為何索引失效?

:觸發(fā)隱式轉(zhuǎn)換→索引列計算→B+樹失效→全表掃描

問題2:如何判斷索引選擇性?

SELECT COUNT(DISTINCT col)/COUNT(*) FROM table

結(jié)果>0.2適合建索引

問題3:EXPLAIN中哪些信號危險?

  • type: ALL(核爆級)
  • Extra: Using filesort(排序災難)
  • rows: 1000000(預估掃描行數(shù))

七、終極總結(jié):與索引和平共處原則

設計階段

  • 優(yōu)先整數(shù)字段索引
  • 聯(lián)合索引遵循ASC排序原則

開發(fā)階段

// MyBatis防類型事故
@Param("userId") Long userId // 而非Integer

運維階段

-- 每月執(zhí)行
ANALYZE TABLE orders; 
OPTIMIZE TABLE critical_data;

最后忠告:索引不是銀彈!200萬數(shù)據(jù)以下,精心設計的索引比分布式更有效;500萬以上,考慮分庫分表+索引的組合拳。

附錄:索引健康檢查清單

- [ ] 所有SQL都通過EXPLAIN驗證
- [ ] 聯(lián)合索引列順序符合查詢模式
- [ ] 避免在WHERE子句中使用函數(shù)
- [ ] 定期清理冗余索引(工具:pt-duplicate-key-checker)
- [ ] 為慢查詢設置監(jiān)控(>0.5秒報警)

到此這篇關于一文揭秘MySQL索引失效原因與優(yōu)化方案的文章就介紹到這了,更多相關MySQL索引失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 對MySQL中字符集的相關設置操作的基本教程

    對MySQL中字符集的相關設置操作的基本教程

    這篇文章主要介紹了對MySQL中字符集的相關設置操作的基本教程,重點講解了修改MySQL字符集的方法,需要的朋友可以參考下
    2015-12-12
  • 如何利用insert?into?values插入多條數(shù)據(jù)

    如何利用insert?into?values插入多條數(shù)據(jù)

    這篇文章主要介紹了如何利用insert?into?values插入多條數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • mysql語句性能分析工具之profiling用法

    mysql語句性能分析工具之profiling用法

    這篇文章主要介紹了mysql語句性能分析工具之profiling用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • MySQL不就是多表查詢嗎

    MySQL不就是多表查詢嗎

    這篇文章主要介紹了MySQL多表查詢相關知識,今天我們學習要對多張表進行相關操作,相比較于單一的表來說,多張表操作相對復雜一些,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • MySQL查看表的最后一個ID的常見方法

    MySQL查看表的最后一個ID的常見方法

    在使用MySQL數(shù)據(jù)庫時,我們經(jīng)常會遇到需要查看表中最后一個id值的場景,無論是為了調(diào)試、數(shù)據(jù)分析還是其他用途,了解如何快速獲取最后一個id都是非常實用的技能,本文將介紹幾種常見的方法,幫助你在不同場景下輕松找到表中的最后一個id,需要的朋友可以參考下
    2025-05-05
  • mysql通配符的具體使用

    mysql通配符的具體使用

    通配符用于替換字符串中的一個或多個字符,通配符與LIKE運算符一起使用,本文就詳細的介紹了mysql通配符的使用,具有一定的參考價值,感興趣的可以了解一下
    2023-05-05
  • MySQL中的運算符使用實例展示

    MySQL中的運算符使用實例展示

    請問,什么是最好的參考文檔,我的答案是:真實可行的樣例語句。
    2010-12-12
  • MySQL 兩種恢復數(shù)據(jù)的方法

    MySQL 兩種恢復數(shù)據(jù)的方法

    這篇文章主要介紹了MySQL 兩種恢復數(shù)據(jù)的方法,幫助恢復線上數(shù)據(jù),保證數(shù)據(jù)完整,感興趣的朋友可以了解下
    2020-10-10
  • 21分鐘 MySQL 入門教程

    21分鐘 MySQL 入門教程

    這篇文章主要介紹了MySQL 入門教程,通過簡單的介紹基本上可以讓你21分鐘就可以了解下mysql
    2014-06-06
  • 詳解mysql權(quán)限和索引

    詳解mysql權(quán)限和索引

    本篇文章給大家詳細分析了mysql的權(quán)限和索引相關知識要點,有這方面需要的朋友參考學習下。
    2018-01-01

最新評論