MySQL的索引知識

来源:https://www.cnblogs.com/tomiku/archive/2018/12/01/10050373.html
-Advertisement-
Play Games

一、什麼是索引。 索引是用來加速查詢的技術的選擇之一,在通常情況下,造成查詢速度差異 的因素就是索引是否使用得當。當我們沒有對數據表的某一欄位段或者多個 欄位添加索引時,實際上執行的全表掃描操作,效率很低。而如果我們為某 些欄位添加索引, 在執行搜索時便可以通過掃描索引,然後再找出索 引對應的值,從 ...


一、什麼是索引。

索引是用來加速查詢的技術的選擇之一,在通常情況下,造成查詢速度差異 的因素就是索引是否使用得當。當我們沒有對數據表的某一欄位段或者多個 欄位添加索引時,實際上執行的全表掃描操作,效率很低。而如果我們為某 些欄位添加索引,mysql在執行搜索時便可以通過掃描索引,然後再找出索 引對應的值,從而提高效率。

二、索引的類型

實際上索引的類型不多,以下只是針對個人以前遇到的索引概念的解釋,有 可能某個索引有多種稱呼,只是取決於你用哪個角度去描述它。

  • B樹索引:採用B-trees數據結構存儲索引,比如PRIMARY KEYUNIQUEINDEX
  • Hash索引:將一個散列函數應用於每一個列值,最終的散列值都會被存入索引,用於執行查找。
  • R樹索引:採用R-trees數據結構存儲索引,比如Spatial index。(空間數據類型的索引)
  • 全文索引(FULLTEXT INDEX):一般在CHARVARCHAR或者TEXT列上創建此索引。可用來代替like ‘%xx%’實現模糊查詢。
  • 首碼索引:只對一個列或者多個列的前幾個字元或者位元組索引。
  • 唯一索引:只對一個列創建索引。
  • 多列索引:對多個列創建索引。在多列索引中必須註意最左首碼這個原則。比如對於(col1,col2,col3)這三列進行索引時,只有(col1)(col1,col2),(col1,col2,col3)才能進行索引搜索。
    註意(col1,col3)也不能進行索引。
  • 聚簇索引:每個InnoDB表都有一個特殊的索引稱為聚簇索引,一般來說,當為一個表定義一個PRIMAY KEY時,InnoDB就會使用它作為聚簇索引。如果沒有定義PRIMARY KEY時,MySQL就會查找第一個非空的 UNIQUE index作為聚簇索引。如果以上兩種情況都不滿足的話,InnoDB內部會在表的每一行產生一個隱藏的並且名為GEN_CLUST_INDEX的聚簇索引。這個聚簇索引是一個六個位元組長度的行ID欄位,ID值隨著新行的插入而單調增長。實際上,除了聚簇索引,其他索引都稱為二級索引。在InnoDB中,二級索引的每一行(將索引假設為行方便理解,實際上索引的存儲方式取決於具體的存儲引擎)中都包含著一個PRIMARY KEY列,InnoDB使用PRIMARY KEY這一列的列值在聚簇索引中查找相對應的數據(可以將聚簇 索引理解為中間值),從而最後得到最終的結果集。聚簇索引的數據分佈如下圖:(圖來自《高性能MySQL》)

    上圖中,節點頁存放是索引(對應著二級索引的PRIMARY KEY),葉子頁存放著所對應的數據,節點頁和葉子頁這個整體就稱為聚簇索引,由此可見,聚簇索引更像是一種數據存儲結構。
  • 覆蓋索引:當查詢的結果集可以通過所創建的索引查找出來時,這個索引就稱為覆蓋索引。
    下麵舉個例子:

    對於上面這個表,當執行下麵的語句時,就會使用覆蓋索引查詢。

    因為我們在創建表的時候對last_namefirst_name創建了多列索引,並且在查詢的時候只查詢這兩列的結果,因此MySQL會使用覆蓋索引查詢數據,這也意味著MySQL不會對實際的數據行進行查詢,因為所需結果已經可以從索引中查找出來了。
    另外可以看一下下麵的SQL語句:

    在上面的SQL語句中,我們想查詢idlast_name的值,而id是主鍵,last_name是多列索引中的最左索引,但是此時的查詢依舊使用覆蓋索引查詢。原因在於id實際是作為聚簇索引的,而多列索引自然就是二級索引了,上面提到,二級索引都包含著一列PRIMARY KEY列,而列值就是聚簇索引的索引值,因此此時MySQL可以直接使用覆蓋索引中查找出對應的結果集。

三、B樹索引和Hash索引的比較

  • InnoDB存儲引擎和MyISAM存儲引擎都只支持B樹索引(實際上InnoDB還支持自適應的hash索引,只是不能人為創建),MEMORY存儲引擎預設使用hash索引,但它也支持B樹索引。
  • 在使用<<==>=><>!=BETWEEN運算符,進行精確比較或者範圍比較時,使用B樹索引會帶來高效。如果匹配模式是以一個純字元串,而不是一個通配符作為開頭的,那麼B樹索引還可以用在使用like進行模式匹配的操作里。
    下麵舉個例子:


  • 對於hash索引,在使用運算符=或者<=>(安全等於的意思,當比較的值含有null值的時候,來返回一個布爾值)完成精確(這裡說精確是因為hash索引是用一個hash函數對整個列值hash,而不是某幾個字元或者位元組)匹配的比較操作里,散列索引的速度非常快。

四、索引的挑選

  • 一般對於出現在WHERE子句中的列、連接子句中的列、或者出現在ORDER BYGROUP BY子句中的列創建索引是比較好的。
  • 儘量索引短小值。應儘量選用較小的數據類型。比如值的長度不超過25個字元,那麼就不要用CHAR(200),其他數據類型同理。特別是InnoDB表來說,因為它使用的是聚簇索引,如果主鍵過長的話,會導致二級索引占用的存儲空間過大。
  • 索引字元串值的首碼。當對字元串列進行索引時,應當儘可能指定首碼長度。比如某一個列的前N個字元足夠唯一的話,那麼就可以不用為整列進行索引。

五、索引的代價

索引確實可以加快檢索速度,但是它同時也降低了索引列的插入、刪除和更新值的速度,因為寫入一個行不僅是寫入一個數據行,還要更改索引。表的索引越多,需要做出的更改就越多,平均性能下降得也就越多。並且當所創建的索引過多時,mysql查詢優化器在選擇使用哪種索引方案時,也會降低一定的效率。其次,索引也會占用磁碟空間,多個索引會占據更大的空間。與沒有索引相比,使用索引很快便達到表的大小極限。

六、創建索引

  • 使用CREATE TABLE創建索引(index_name可選)
  • 使用ALTER TABLE為已有表創建索引(index_name可選)
  • 使用CREATE INDEX創建索引(index_name不可省略)

    如果某個索引列在索引時使用了PRIMARY KEYSPATIAL,則它必須為NOT NULL的。其他索引列允許包含NULL值。
    如果想要限制某個索引,讓它只包含唯一值,那麼可以把這個索引創建為PRIMARY KEYUNIQUE索引。 這兩種索引很像,主要區別有一下兩點:
  • 每個表只能包含一個PRIMARY KEY。因為PRIMARY KEY的名字總是為PRIMARY,而同一個表不允許有兩個同名的索引。可以在一個表裡放置多個UNIQUE索引。
  • PRIMARY KEY不可以包含NULL值,而UNIQUE索引可以。如果某個UNIQUE索引包含了NULL值,那麼它就可以包含多個NULL值。因為NULL值不會與任何值相等,包括它本身。

七、刪除索引

最後,我們可以通過DROP INDEXALTER TABLE語句來刪除索引

  • 通過DROP INDEX刪除索引

  • 通過DROP INDEX刪除索引

八、[PRIMARY|UNIQUE]KEY與[UNIQUE]INDEX的關係

首先來看一下MySQL創建表的語句:(圖來自《MySQL官方文檔》,圖太大所以省略了一部分)


從上圖可以看出,實際上INDEXKEY是同義詞,之所以同時存在主要是為了與其他資料庫系統做相容,另外還有以下兩個結論。

  • PRIMARY KEYUNIQUE[INDEX|KEY]很相似,具體區別可以查看上面的內容。
  • INDEX和KEY允許出現相同的列值,但是UNIQUE[INDEX|KEY]不允許出現相同的列值。(記住NULL != NULL)

九、參考資料


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

-Advertisement-
Play Games
更多相關文章
  • 在main線程中調用 會起到只讓main線程退出,但是保留進程資源,供其他由main創建的線程使用,直至所有線程都結束,但在其他線程中不會有這種效果 "https://stackoverflow.com/questions/3559463/is it ok to call pthread exit ...
  • Linux tree命令用於以樹狀圖列出目錄的內容。 執行tree指令,它會列出指定目錄下的所有文件,包括子目錄里的文件。 當我們在Ubuntu中需要用到tree命令時,顯示Command 'tree' not found. 這是因為在Ubuntu系統中預設是沒有tree這個命令的。 通過sudo ...
  • pwd命令 作用:顯示當前工作的全名路徑名 · alias命令 作用:對於經常使用的命令,可以將命令改為自己所習慣的字母 cal命令 作用:顯示日曆,可以顯示任意一年或者任意一月的日曆 使用舉例: 直接使用 cal 不加任何選項,會顯示當前電腦所顯示的時間日曆 如果在 cal 後面加上年份,可以顯 ...
  • more命令 作用:分屏顯示文件內容 格式:more [選項] 文件名 選項:-num 一次顯示的行數 +num 從第幾行開始顯示 使用技巧:空格或f鍵進行向下翻頁 使用Enter鍵向下換行 使用q或Q退出 / 字元串 向下查找字元串 註意點:使用more命令不可以進行向上翻頁 less命令 作用: ...
  • Deepin 原名Linux Deepin,在2014年4月改名Deepin。Deepin團隊基於Qt/C++(用於前端)和Go(用於後端)開發了的全新深度桌面環境(DDE),以及音樂播放器,視頻播放器,軟體中心等一系列特色軟體。 Deepin是由武漢深之度科技有限公司開發的Linux發行版。Dee ...
  • 減少文件大小有兩個明顯的好處,一是可以減少存儲空間,二是通過網路傳輸文件時,可以減少傳輸的時間。gzip是在Linux系統中經常使用的一個對文件進行壓縮和解壓縮的命令,既方便又好用。gzip不僅可以用來壓縮大的、較少使用的文件以節省磁碟空間,還可以和tar命令一起構成Linux操作系統中比較流行的壓 ...
  • 文章摘抄自:一支小白,博客地址:http://www.cnblogs.com/startnow/p/7580865.html Centos7安裝Oracle 11gR2 - 環境:VM12+centos7 x86_64 minimal - 最小化安裝的Centos7 - 虛擬機配置- 50G硬碟 - ...
  • 一、資料庫能夠做什麼 1.存儲大量的數據。 2.保持數據信息的一致、完整。 3.共用和安全。 4.通過組合分析,產生新的有用信息。 二、資料庫的基本概念 1.資料庫就是“數據”的“倉庫”。 2.資料庫中包含表、關係以及操作對象。 3.數據存放在表中。 三、數據完整性 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...