面試官:講講MySql索引失效的幾種情況

来源:https://www.cnblogs.com/deyo/archive/2023/06/29/17514052.html
-Advertisement-
Play Games

## 索引失效 ### 準備數據: ```sql CREATE TABLE `dept` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `deptName` VARCHAR(30) DEFAULT NULL, `address` VARCHAR(40) DEFAUL ...


索引失效

準備數據:

CREATE TABLE `dept` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`deptName` VARCHAR(30) DEFAULT NULL,
	`address` VARCHAR(40) DEFAULT NULL,
	ceo INT NULL ,
	PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1;

CREATE TABLE `emp` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`empno` INT NOT NULL ,
	`name` VARCHAR(20) DEFAULT NULL,
	`age` INT(3) DEFAULT NULL,
	`deptId` INT(11) DEFAULT NULL,
	PRIMARY KEY (`id`)
	#CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1;

1、計算、函數導致索引失效

-- 顯示查詢分析
EXPLAIN SELECT * FROM emp WHERE emp.name  LIKE 'abc%';
EXPLAIN SELECT * FROM emp WHERE LEFT(emp.name,3) = 'abc'; --索引失效

image-20220710212756603

2、LIKE以%開頭索引失效

EXPLAIN SELECT * FROM emp WHERE name LIKE '%ab%'; --索引失效

image-20220710213641577

拓展:Alibaba《Java開發手冊》

【強制】頁面搜索嚴禁左模糊或者全模糊,如果需要請走搜索引擎來解決。

3、不等於(!= 或者<>)索引失效

EXPLAIN SELECT * FROM emp WHERE emp.name = 'abc' ;
EXPLAIN SELECT * FROM emp WHERE emp.name <> 'abc' ; --索引失效

image-20220710214317491

4、IS NOT NULL 和 IS NULL

EXPLAIN SELECT * FROM emp WHERE emp.name IS NULL;
EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL; --索引失效

image-20220710214840703

註意:當資料庫中的數據的索引列的NULL值達到比較高的比例的時候,即使在IS NOT NULL 的情況下 MySQL的查詢優化器會選擇使用索引,此時type的值是range(範圍查詢)

-- 將 id>20000 的數據的 name 值改為 NULL
UPDATE emp SET `name` = NULL WHERE `id` > 20000;

-- 執行查詢分析,可以發現 IS NOT NULL 使用了索引
-- 具體多少條記錄的值為NULL可以使索引在IS NOT NULL的情況下生效,由查詢優化器的演算法決定
EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL;

image-20220711175040606

測試完將name的值改回來

UPDATE emp SET `name` = rand_string(6) WHERE `id` > 20000;

5、類型轉換導致索引失效

EXPLAIN SELECT * FROM emp WHERE name='123'; 
EXPLAIN SELECT * FROM emp WHERE name= 123; --索引失效

image-20220710215217274

6、全值匹配我最愛

準備:

-- 首先刪除之前創建的索引
CALL proc_drop_index("atguigudb","emp");

問題:為以下查詢語句創建哪種索引效率最高

-- 查詢分析
EXPLAIN SELECT * FROM emp WHERE emp.age = 30 and deptid = 4 AND emp.name = 'abcd';
-- 執行SQL
SELECT * FROM emp WHERE emp.age = 30 and deptid = 4 AND emp.name = 'abcd';
-- 查看執行時間
SHOW PROFILES;

創建索引並重新執行以上測試:

-- 創建索引:分別創建以下三種索引的一種,並分別進行以上查詢分析
CREATE INDEX idx_age ON emp(age);
CREATE INDEX idx_age_deptid ON emp(age,deptid);
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,`name`);

結論:可以發現最高效的查詢應用了聯合索引 idx_age_deptid_name

image-20220711190731030

7、最佳左首碼法則

準備:

-- 首先刪除之前創建的索引
CALL proc_drop_index("atguigudb","emp");
-- 創建索引
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,`name`);

問題:以下這些SQL語句能否命中 idx_age_deptid_name 索引,可以匹配多少個索引欄位

測試:

  • 如果索引了多列,要遵守最左首碼法則。即查詢從索引的最左前列開始並且不跳過索引中的列。
  • 過濾條件要使用索引,必須按照索引建立時的順序,依次滿足,一旦跳過某個欄位,索引後面的欄位都無法被使用。
EXPLAIN SELECT * FROM emp WHERE emp.age=30 AND emp.name = 'abcd' ;
-- EXPLAIN結果:
-- key_len:5 只使用了age索引
-- 索引查找的順序為 age、deptid、name,查詢條件中不包含deptid,無法使用deptid和name索引

EXPLAIN SELECT * FROM emp WHERE emp.deptid=1 AND emp.name = 'abcd';
-- EXPLAIN結果:
-- type: ALL, 執行了全表掃描
-- key_len: NULL, 索引失效
-- 索引查找的順序為 age、deptid、name,查詢條件中不包含age,無法使用整個索引

EXPLAIN SELECT * FROM emp WHERE emp.age = 30 AND emp.deptid=1 AND emp.name = 'abcd';
-- EXPLAIN結果:
-- 索引查找的順序為 age、deptid、name,匹配所有索引欄位

EXPLAIN SELECT * FROM emp WHERE emp.deptid=1 AND emp.name = 'abcd' AND emp.age = 30;
-- EXPLAIN結果:
-- 索引查找的順序為 age、deptid、name,匹配所有索引欄位

8、索引中範圍條件右邊的列失效

準備:

-- 首先刪除之前創建的索引
CALL proc_drop_index("atguigudb","emp");

問題:為以下查詢語句創建哪種索引效率最高

EXPLAIN SELECT * FROM emp WHERE emp.age=30 AND emp.deptId>1000 AND emp.name = 'abc'; 

測試1:

-- 創建索引並執行以上SQL語句的EXPLAIN
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,`name`);
-- key_len:10, 只是用了 age 和 deptid索引,name失效

註意:當我們修改deptId的範圍條件的時候,例如deptId>100,那麼整個索引失效,MySQL的優化器基於成本計算後認為沒必要使用索引了,所以就進行了全表掃描。(註意:因為表中的數據是隨機生成的,因此實際測試中根據具體數據的不同測試的結果也會不一樣,最終是否使用索引由優化器決定)

image-20220711215826013

測試2:

-- 創建索引並執行以上SQL語句的EXPLAIN(將deptid索引的放在最後)
CREATE INDEX idx_age_name_deptid ON emp(age,`name`,deptid);
-- 使用了完整的索引

image-20220712080350120

補充:以上兩個索引都存在的時候,MySQL優化器會自動選擇最好的方案

本文來自博客園,作者:自律即自由-,轉載請註明原文鏈接:https://www.cnblogs.com/deyo/p/17514052.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、基礎數據查詢 select語句用於從表中選取數據,結果被存儲在一個結果表中(稱為結果集)。 語法:select * from 表名稱 #查詢指定表中的所有數據 *為模糊匹配所有列 例: mysql> select * from person; + + + + + + + | id | name ...
  • ![file](https://img2023.cnblogs.com/other/2685289/202306/2685289-20230629181452343-550852462.png) 作者|雲科NearFar X Lab團隊 左益、周志銀、洪守偉、陳超、武超 ## 一、導讀 無錫拈花雲科 ...
  • hive的高級分組聚合是指在聚合時使用GROUPING SETS、CUBE和ROLLUP的分組聚合。 高級分組聚合在很多資料庫類SQL中都有出現,並非hive獨有,這裡只說明hive中的情況。 使用高級分組聚合不僅可以簡化SQL語句,而且通常情況下會提升SQL語句的性能。 ## 1.Grouping ...
  • 摘要:業務應用對資料庫的數據請求分寫請求(增刪改)和讀請求(查)。當存在大量讀請求時,為避免讀請求阻塞寫請求,資料庫會提供只讀實例方案。通過主實例+N只讀實例的方式,實現讀寫分離,滿足大量的資料庫讀取需求,增加應用的吞吐量。 業務應用對資料庫的數據請求分寫請求(增刪改)和讀請求(查)。當存在大量讀請 ...
  • 摘要:本期結合示例,詳細介紹華為雲數字工廠平臺的數據分析模型和數據圖表視圖模型的配置用法。 本文分享自華為雲社區《數字工廠深入淺出系列(六):數據分析與圖表視圖模型的配置用法》,作者:雲起MAE 。 華為雲數字工廠平臺基於“數據與業務一體化”理念,提供統一的製造全域數據平臺底座,內置輕量級製造數據分 ...
  • 時下,眾多金融機構在積極推行數字化改革,以適應時代高速革新。為回應市場對信息即時生效的迫切需求,各家[券商機構](https://www.dtstack.com/solution/securities?src=szsm)都需要更具競爭力的信息服務。 本次方案結合券商場景與業務實踐,圍繞客戶實際面臨的 ...
  • 衛健行業是關乎國家和民生安全的關鍵行業。近年來,雲計算、大數據、人工智慧等技術不斷發展,並與醫療行業深入融合。同時,相關部門相繼頒發一系列政策,進一步推動醫療行業數字化、智慧化轉型,促進探索健康中國高質量發展道路。 ...
  • #其他預設調整值#MySQL Server實例配置文件# #由MySQL Server實例配置嚮導生成###安裝說明# ##在Linux上,您可以將此文件複製到/etc/my.cnf以設置全局選項,#mysql-data-dir/my.cnf設置伺服器特定選項(用於此安裝的@localstatedi ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...