八股學習(三)---MySQL

一、MySQL中的回表是什么?

我的回答:

MySQL回表指的是在查詢使用非聚簇索引也就是二級索引時,葉子節點只存儲了索引列的值和主鍵Id,若要查詢其他字段,就要根據主鍵去聚簇索引查詢完整的數據。這個過程就是回表。比如用name的二級索引查age,要先通過name找到主鍵id,再用這個主鍵id查詢age。回表會增加 IO ,所以可以建立覆蓋索引來包含所需要的字段,避免回表。我練過用聯合索引包含其他字段,減少了回表,查詢快了不少~

回答重點(官方答案):

“回表” 是指在使用二級索引(非聚簇索引)作為條件進行查詢時,由于二級索引中只存儲了索引字段的值和對應的主鍵值,無法得到其它數據。如果要查詢數據行中的其它數據,需要根據主鍵去聚簇索引查找實際的數據行,這個過程被稱為回表。

二、MySQL中使用索引一定有效嗎?如何排查索引效果?

我的回答:

MySQL中使用索引不一定有效,比如索引字段上有函數運算、使用了like '%xxx'這類前綴模糊匹配查詢、類型不匹配,或者統計信息不準確等, 都可能導致索引失效。

排查索引效果,我們可以使用explain分析SQL執行計劃,重點看type字段,(如all表示全表掃描)、key字段(是否為null),以及rows估算值

再通過show status like ‘Handler%’; 查看索引使用次數,對比查詢前后的Handler_read_key和Handler_read_rnd_next等指標。之前我在練習時,發現一條SQL有索引,但是執行慢,用explain發現是因為對索引字段做了函數操作,調整后索引生效,查詢效率顯著提升,所以現在寫SQL后都會習慣性用這些方法檢驗索引效果,避免出校“有索引但不生效”的情況。

回答重點(官方答案):

索引不一定有效。
例如查詢條件中不包含索引列、低基數列索引效果不佳,或查詢條件復雜且不匹配索引的順序。
對于一些小表,MySQL 可能選擇全表掃描而非使用索引,因為全表掃描的開銷可能更小。
最終是否用上索引是根據 MySQL 成本計算決定的,評估 CPU 和 I/O 成本最終選擇用輔助索引還是全表掃描。有時候確實是全表掃描成本低所以沒用上索引。但有時候由于一些統計數據的不準確,導致成本計算誤判,而沒用上索引。

排查索引效果的方法:使用 EXPLAIN 命令,通過在查詢前加上 EXPLAIN ,可以查看 MySQL 選擇的執行計劃,了解是否使用了索引、使用了哪個索引、估算的行數等信息。
主要觀察 EXPLAIN 結果以下幾點:

  • type(訪問類型):這個屬性顯示了查詢使用的訪問方法,例如 ALL 、index 、range 等。當查詢使用索引時,這個屬性通常會顯示為 index 或 range ,表示查詢使用了索引訪問。如果這個值是 ALL ,則表示查詢執行了全表掃描,沒有使用索引。
  • key(使用的索引):這個屬性顯示了查詢使用的索引,如果查詢使用了索引,則會顯示索引的名稱。如果這個值是 NULL ,則表示查詢沒有使用索引。
  • rows(掃描的行數):這個屬性顯示了查詢掃描的行數,需要評估下掃描量。

擴展知識


確定索引真的生效了嗎?
索引失效的場景有很多,也是面試官經常喜歡問的,可以根據具體場景進行排查,典型場景可以分為以下幾點(實際索引的選擇會根據 mysql 優化器的成本評定,答案最后會提到):

  1. 使用了聯合索引卻不符合最左前綴
    舉個例子:小魚對 user 表建立了一個聯合索引為 name_age_id 的聯合索引。
    他使用以下 SQL 查詢 select * from user where age = 10 and id = 1;
    這樣的寫法恰恰不滿足最左前綴原則,索引就失效啦。

  2. 索引中使用了運算
    例如這個 SQL select * from user where id + 3 = 8 。這樣會導致全表掃描計算 id 的值再進行比較,使得索引失效。

  3. 索引上使用了函數也會失效
    例如:select * from user where LOWER (name) like 'cong%'; 。
    這樣也會導致索引失效,索引參與了函數處理,會導致去全表掃描。

  4. like 的隨意使用
    例如:select * from user where name like '% cong%'; 因為索引是從左到右來進行排序查找的,占位符直接放在了最左邊開頭,可能會導致直接全表掃描,這種情況就會導致索引失效。

  5. or 的隨意使用
    user 當前只有一個索引 name 。此時執行以下 SQL:
    select * from user where name = 'cong' or age = 18; 這可能也會導致索引失效,因為 age 沒有索引。

  6. 隨意的字段類型使用
    不小心將 varchar 類型的 name 條件匹配了 int 類型字段。SQL 是這樣的 select * from user where name = 1; ,在代碼中涉及隱式轉換!等于 select * from user where CAST (name AS signed int) = 1; ,這就變成了第三條索引上使用了函數,導致索引失效。
    除此之外還有隱式字符編碼轉換的問題,即聯表查詢的時候,如果不同表之間的關聯字段字符編碼不一致,也會導致隱式轉換編碼,等于變相用上了函數,使得索引失效。

  7. 不同的參數也會導致索引失效
    這個就是我在回答重點里面說的 “是否用上索引是根據 MySQL 成本計算決定的”。不同的參數 MySQL 評估成本不一致,有時候會選擇使用索引,有時候會選擇全表掃描,特別是在復雜查詢(聯表、子查詢、需要回表等)的情況下。

比如根據商品從訂單表查詢,收集商品對應的所有買家的訂單信息。如果傳入的商品 id 是個熱點商品,占據這家店鋪 80% 的銷量,那么本次查詢對訂單表很可能是全表查詢,如果是冷門商品,則很可能是走索引查詢。
8) 表中兩個不同字段進行比較
例如這樣的 SQL : select * from user where id > age; ,將 id 跟 age 字段做了比較,索引失效。
9) 使用了 order by
當 order by 后面跟的不是主鍵或者不是覆蓋索引會導致不走索引。
為什么索引生效了反而查詢變慢了呢?
確認是否選對了索引!MySQL 根據優化器會評估成本選擇對應的索引,但有時候 MySQL 因為估計值不準確,導致選錯了索引,因此查詢速度反而更慢。

三、在MySQL中建立索引時需要注意哪些事項?

我的回答:

我會注意:

1.按需創建索引:根據實際查詢需求,在where,join,order by等子句的字段上建索引,避免冗余。

2.會優先給唯一性高的,如id、手機號建立索引,像性別低選擇性字段建立索引意義不大。

3.若是聯合索引,遵循最左前綴原則,把選擇性高的字段放在前面,比如(a,b,c)的索引能支持a、a+b、a+b+c的查詢

4.避免失效場景,不在字段上使用函數,避免使用like %xxx、保證類型匹配,防止索引失效

5.權衡性能:索引會加快查詢,但是會降低增刪改的速度,還會占用磁盤空間,因此寫入頻繁的表要控制索引數量。

我練習的時候,給訂單表的user_id 和 create_time建立聯合索引,發現遵循最左原則的查詢能命中索引,但是加了低選擇性的status字段后反而失效,刪除后性能恢復了,這讓我明白索引設計要結合實際場景,不能盲目添加。

類型匹配解釋:

加了低選擇性的status字段,索引失效解釋:

重點回答(官方答案)

  1. 不能盲目建立索引,索引并不是越多越好,索引會占用空間,且每次修改的時候可能都需要維護索引的數據,消耗資源。

  2. 對于字段的值有大量重復的不要建立索引。比如說:性別字段,在這種重復比例很大的數據行中,建立索引也不能提高檢索速度。但是也不絕對,例如定時任務的場景,大部分任務都是成功,少部分任務狀態是失敗的,這時候通過失敗狀態去查詢任務,實際上能過濾大部分成功的任務,效率還是可以的。

  3. 對于一些長字段不應該建立索引。比如 text、longtext 這種類型字段不應該建立索引。因為占據的內存大,掃描的時候大量加載至內存中還耗時,使得提升的性能可能不明顯,甚至可能還會降低整體的性能,因為別的緩存數據可能因為它被踢出內存,下次查詢還需要從磁盤中獲取。

  4. 當數據表的修改頻率遠大于查詢頻率時,應該好好考慮是否需要建立索引。因為建立索引會減慢修改的效率,如果很少的查詢較多的修改,則得不償失。

  5. 對于需要頻繁作為條件查詢的字段應該建立索引。在 where 關鍵詞后經常查詢的字段,建立索引能提高查詢的效率,如果有多個條件經常一起查詢,則可以考慮聯合索引,減少索引數量。

  6. 對經常在 order by、group by、distinct 后面的字段建立索引。這些操作通常需要對結果進行排序、分組或者去重,而索引可以幫助加快這些操作的速度。

擴展知識

MySQL 索引的最左前綴匹配原則是什么?

回答重點


MySQL 索引的最左前綴匹配原則指的是在使用聯合索引時,

查詢條件必須從索引的最左側開始匹配。如果一個聯合索引包含多個列,查詢條件必須包含第一個列的條件,然后是第二個列,以此類推。
底層原理:因為聯合索引在 B+ 樹中的排列方式遵循 “從左到右” 的順序,例如聯合索引 (first_name, last_name, age) 會按照 (first_name, last_name, age) 的順序在 B+ 樹中進行排序。
MySQL 在查找時會優先使用 first_name 作為匹配依據,然后依次使用 last_name 和 age 。因此,組合索引能夠從左到右依次高效匹配,跳過最左側字段會導致無法利用該索引。
按照 (first_name, last_name, age) 的順序在 B+ 樹中的排列方式 (大致的示意圖) 如下

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87545.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87545.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87545.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

NeighborGeo:基于鄰居的IP地理定位(一)

NeighborGeo:基于neighbors的IP地理定位 X. Wang, D. Zhao, X. Liu, Z. Zhang, T. Zhao, NeighborGeo: IP geolocation based on neighbors, Comput. Netw. 257 (2025) 110896, Abstract IP地址定位在網絡安全、電子商務、社交媒體等領域至關重要。當前主流的圖神經網絡方法…

MySQL 8.0:窗口函數

一、基礎知識 定義 窗口函數(Window Function)對查詢結果集的子集(“窗口”)進行計算,保留原始行而非聚合為單行,適合復雜分析(如排名、累積和)。 基本語法: 函數名() OV…

AI 深度學習面試題學習

1.神經網絡 1.1各個激活函數的優缺點? 1.2為什么ReLU常用于神經網絡的激活函數? 1.在前向傳播和反向傳播過程中,ReLU相比于Sigmoid等激活函數計算量小; 2.避免梯度消失問題。對于深層網絡,Sigmoid函數反向傳播時,很容易就會出現梯度消失問題(在Sigmoid接近飽和區時,變換…

遇到該問題:kex_exchange_identification: read: Connection reset`的解決辦法

kex_exchange_identification: read: Connection reset 是一個非常常見的 SSH 連接錯誤。它表明在 SSH 客戶端和服務器建立安全連接的初始階段(密鑰交換,Key Exchange),連接就被對方(服務器)強制關閉了。 …

(論文蒸餾)語言模型中的多模態思維鏈推理

(論文總結)語言模型中的多模態思維鏈推理 論文名稱研究背景動機主要貢獻研究細節兩階段框架實驗結果促進收斂性擺脫人工標注錯誤分析與未來前景 論文名稱 Multimodal Chain-of-Thought Reasoning in Language Models http://arxiv.org/abs/2302.00923 …

React Native 接入 eCharts

React Native 圖表接入指南 概述 本文檔詳細介紹了在React Native項目中接入ECharts圖表的完整步驟,包括依賴安裝、組件配置、數據獲取、圖表渲染等各個環節。 目錄 1. 環境準備2. 依賴安裝3. 圖表組件創建4. 數據獲取Hook5. 圖表配置6. 組件集成7. 國際化支持8…

基于C#的OPCServer應用開發,引用WtOPCSvr.dll

操作流程: 1.引入WtOPCSvr.dll文件 2.注冊服務:使用UpdateRegistry方法注冊,注意關閉應用時使用UnregisterServer取消注冊。 3.初始化服務:使用InitWTOPCsvr初始化 4.使用CreateTag方法,創建標簽 5.讀寫參數使用下面三…

Java類加載器getResource行為簡單分析

今天嘗試集成一個第三方SDK,在IDE里運行正常,放到服務器上卻遇到了NPE,反編譯一看,原來在這一行:String path Test.class.getClassLoader().getResource("").getPath(); // Test.class.getClassLoader().ge…

【CodeTop】每日練習 2025.7.4

Leetcode 1143. 最長公共子序列 動態規劃解決,比較當前位置目標和實際字符串的字母,再根據不同情況計算接下來的情形。 class Solution {public int longestCommonSubsequence(String text1, String text2) {char[] t1 text1.toCharArray();char[] t2…

ES6從入門到精通:Promise與異步

Promise 基礎概念Promise 是 JavaScript 中處理異步操作的一種對象,代表一個異步操作的最終完成或失敗及其結果值。它有三種狀態:Pending(進行中)、Fulfilled(已成功)、Rejected(已失敗&#xf…

數據結構:二維數組(2D Arrays)

目錄 什么是二維數組? 二維數組的聲明方式 方式 1:靜態二維數組 方式 2:數組指針數組(數組中存放的是指針) 方式 3:雙指針 二級堆分配 💡 補充建議 如何用“第一性原理”去推導出 C 中…

HAProxy 和 Nginx的區別

HAProxy 和 Nginx 都是優秀的負載均衡工具,但它們在設計目標、適用場景和功能特性上有顯著區別。以下是兩者的詳細對比:1. 核心定位特性HAProxyNginx主要角色專業的負載均衡器/代理Web 服務器 反向代理/負載均衡設計初衷高性能流量分發高并發 HTTP 服務…

基于Java+SpringBoot的健身房管理系統

源碼編號:S586源碼名稱:基于SpringBoot的健身房管理系統用戶類型:多角色,用戶、教練、管理員數據庫表數量:13 張表主要技術:Java、Vue、ElementUl 、SpringBoot、Maven運行環境:Windows/Mac、JD…

【MySQL安裝-yum/手動安裝,卸載,問題排查處理完整文檔(linux)】

一.使用Yum倉庫自動安裝 步驟1:添加MySQL Yum倉庫 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm步驟2:安裝MySQL服務器 sudo yum install mysql-server -y步驟3:啟動并設置開機自啟 sudo systemctl start mysqld sudo systemct…

自定義線程池-實現任務0丟失的處理策略

設計一個線程池,要求如下:隊列最大容量為10(內存隊列)。當隊列滿了之后,拒絕策略將新的任務寫入數據庫。從隊列中取任務時,若該隊列為空,能夠從數據庫中加載之前被拒絕的任務模擬數據庫 (TaskDa…

【NLP入門系列四】評論文本分類入門案例

🍨 本文為🔗365天深度學習訓練營 中的學習記錄博客🍖 原作者:K同學啊 博主簡介:努力學習的22級本科生一枚 🌟?;探索AI算法,C,go語言的世界;在迷茫中尋找光芒…

Ubuntu安裝ClickHouse

注:本文章的ubuntu的版本為:ubuntu-20.04.6-live-server-amd64。 Ubuntu(在線版) 更新軟件源 sudo apt-get update 安裝apt-transport-https 允許apt工具通過https協議下載軟件包。 sudo apt-get install apt-transport-htt…

C++26 下一代C++標準

C++26 將是繼 C++23 之后的下一個 C++ 標準。這個新標準對 C++ 進行了重大改進,很可能像 C++98、C++11 或 C++20 那樣具有劃時代的意義。 一:C++標準回顧 C++ 已經有 40 多年的歷史了。過去這些年里發生了什么?這里給出一個簡化版的答案,直到即將到來的 C++26。 1. C++9…

【MySQL】十六,MySQL窗口函數

在 MySQL 8.0 及以后版本中,窗口函數(Window Functions)為數據分析和處理提供了強大的工具。窗口函數允許在查詢結果集上執行計算,而不必使用子查詢或連接,這使得某些類型的計算更加高效和簡潔。 語法結構 function_…

微型氣象儀在城市環境的應用

微型氣象儀憑借其體積小、成本低、部署靈活、數據實時性強等特點,在城市環境中得到廣泛應用,能夠為城市規劃、環境管理、公共安全、居民生活等領域提供精細化氣象數據支持。一、核心應用場景1. 城市微氣候監測與優化熱島效應研究場景:在城市不…