日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql 隐藏中间四位_MySQL知识体系——索引

發布時間:2023/12/2 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 隐藏中间四位_MySQL知识体系——索引 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文直切主題,針對InnoDB引擎描述索引及優化策略。在開始之前,需要讀者了解:

  • 二叉查找樹(包括2-3查找樹、紅黑樹等數據結構)
  • MySQL的InnoDB引擎基礎知識
  • 索引初探

    要了解索引,當然要了解其數據結構。樹有很多應用,流行的用法之一是包括UNIX和DOS在內的許多常用操作系統中的目錄結構,二叉查找樹又是Java中兩種集合類TreeSet和TreeMap實現的基礎。那么對于數據庫,I/O是其性能瓶頸所在,減少樹的深度是直接有效的,BTree和B+Tree應運而生。

    BTree和B+Tree(Balance-Tree,多路搜索樹,非二叉)

    BTree

    BTree是一種查找樹,如同二叉查找樹,紅黑樹等,都是為提高查找效率而產生的,BTree也是如此,可以把它看做二叉查找樹的優化升級。二叉查找樹的特點是每個非葉節點都最多只有兩個子節點,但是當數據量非常大時,二叉查找樹的深度過深,搜索算法自根節點向下搜索時,需要訪問的節點也就變的相當多。如果這些節點存儲在外存儲器(磁盤)中,每訪問一個節點,相當于就是進行了一次I/O操作,隨著樹高度的增加,頻繁的I/O操作一定會降低查詢的效率。BTree改二叉為多叉,每個節點存儲更多的指針信息,以此達到減少樹的深度、降低I/O操作數。

    使用BTree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。

    定義(對于一個m階BTree)

    • 根節點至少有兩個子節點(除非根結點為葉節點)
    • 每個節點有m-1個關鍵字,并且以升序排列
    • 位于 m-1和m 關鍵字的子節點的值位于 m-1和m 關鍵字對應的值之間
    • 其它節點至少有m/2個子節點

    特性

    • 關鍵字集合分布在整棵樹中;
    • 任何一個關鍵字出現且只出現在一個節點中;
    • 搜索有可能在非葉節點結束;
    • 其搜索性能等價于在關鍵字全集內做一次二分查找;
    • 自動層次控制。

    B+Tree

    InnoDB 存儲引擎在絕大多數情況下使用B+Tree建立索引,B+Tree也是關系型數據庫中最為常用和有效的索引結構,但是B+Tree索引并不能找到一個給定鍵對應的具體值,它只能找到數據行對應的頁,然后正如上一節所提到的,數據庫把整個頁讀入到內存中,并在內存中查找具體的數據行。

    定義(其定義基本與 BTree同,除了:)

    • 所有葉節點之間都有一個鏈指針;
    • 所有關鍵字都在葉子結點出現;
    • 非葉子節點只存儲鍵值信息,數據記錄都存放在葉節點中。

    特性

    • 單節點可以存儲更多的元素,使得查詢磁盤IO次數更少,更加高效的單元素查找;
    • 所有查詢都要查找到葉子節點,查詢性能穩定;
    • 葉子節點會包含所有的關鍵字,以及指向數據記錄的指針,并且葉子節點本身是根據關鍵字的大小從小到大順序鏈接,范圍查找性能更優。

    區別

    B+Tree是BTree的一種變形樹,它與BTree的差異在于:

    • B+Tree只有達到葉子結點才命中(BTree可以在非葉子結點命中),其性能也等價于在關鍵字全集做一次二分查找;
    • BTree樹每個葉子節點都有雙向指針;
    • BTree分支節點和葉節點均保存記錄的關鍵碼和記錄的指針;B+Tree分支節點只保存記錄關鍵碼的復制,無記錄指針。所有記錄都集中在葉節點一層,并且葉節點可以構成一維線性表,便于連續訪問和范圍查詢。

    聚集索引和輔助索引

    數據庫中的 B+Tree索引可以分為聚集索引(clustered index)和輔助索引(secondary index),它們之間的最大區別就是,聚集索引中存放著一條行記錄的全部信息,而輔助索引中只包含索引列和一個用于查找對應行記錄的“書簽”。即在數據庫的聚集索引中,葉子節點直接包含衛星數據。在輔助索引(NonClustered Index)中,葉節點帶有指向衛星數據的指針。

    聚集索引

    InnoDB使用了聚集索引存儲數據。

    與非聚集索引的區別則是,聚集索引既存儲了索引,也存儲了行值。當一個表有一個聚集索引,它的數據是存儲在索引的葉子頁(leaf pages)上的。因此可以說InnoDB是基于索引的表。

    當我們使用聚集索引對表中的數據進行檢索時,可以直接獲得聚集索引所對應的整條行記錄數據所在的頁,不需要進行第二次操作。

    索引的建立規則

    • 如果一個主鍵被定義了,那么這個主鍵就是作為聚集索引
    • 如果沒有主鍵被定義,那么該表的第一個唯一非空索引被作為聚集索引
    • 如果沒有主鍵也沒有合適的唯一索引,那么InnoDB內部會生成一個隱藏的主鍵作為聚集索引,這個隱藏的主鍵是一個6個字節的列,改列的值會隨著數據的插入自增

    輔助索引

    輔助索引,也叫做非聚集索引,葉節點不包含行的全部數據。除了包含關鍵字外,還包含了一個標記,這個標記用來告訴InnoDB引擎從哪里可以找到與索引相對應的行數據。由于InnoDB引擎是索引組織表,因此,這個標記就是相應的行數據的聚集索引關鍵字。

    輔助索引的存在并不影響數據在聚集索引中的組織,因此一個表可以有多個輔助索引。

    使用輔助索引查找一條表記錄的過程:通過輔助索引查找到對應的關鍵字,最后在聚集索引中使用關鍵字獲取對應的行記錄,這也是通常情況下行記錄的查找方式。

    使用建議

    聚集索引的優先選擇列

  • 含有大量非重復值的列
  • 使用 between,>或
  • 需要經常排序的列,列順序和最常用的排序一致
  • 返回大量結果集的查詢
  • 經常被 join 的列
  • 不建議的聚集索引列

  • 修改頻繁的列
  • 低選擇性的列,如性別
  • 新增內容太過離散隨機的列
  • 規范與建議

  • 命名規則:表名_字段名
  • 需要加索引的字段,要在where條件中
  • 如果where條件中是OR關系,加索引不起作用
  • 能用小類型別用大類型字段
  • 索引 key_len 長度過大,也會影響 SQL 性能。所以盡量不默認 null,會占用字節、索引長度。
  • 常用的字段放在前面;選擇性高的字段放在前面
  • 對較長的字符數據類型的字段建索引,優先考慮前綴索引,如 index(url(64))
  • 只創建需要的索引,避免冗余索引,如:index(a,b),index(a)
  • 使用聯合索引,以避免回表,達到覆蓋索引
  • 聯合索引遵循最左原則
  • 索引不可濫用,索引會占用存儲空間并且增加數據更新操作的復雜度,降低CUD(create/update/delate)效率
  • 回表

    先了解一個概念,MySQL對 WHERE 中條件的處理,根據索引使用情況分成三種:index key, index filter, table filter

    1. index key

    用于確定SQL查詢在索引中的連續范圍(起始范圍+結束范圍)的查詢條件,被稱之為Index Key。由于一個范圍,至少包含一個起始與一個終止,因此Index Key也被拆分為Index First Key和Index Last Key,分別用于定位索引查找的起始,以及索引查詢的終止條件。

    2. index filter

    在使用 index key 確定了起始范圍和介紹范圍之后,在此范圍之內,還有一些記錄不符合 WHERE 條件,如果這些條件可以使用索引進行過濾,那么就是 index filter。

    3. table filter

    WHERE 中的條件不能使用索引進行處理的,只能訪問table,進行條件過濾了。

    從普通索引查出主鍵索引,然后查詢出數據的過程叫做回表。回表一次就會執行一次查詢,所以避免回表是減少數據庫壓力、提高效率的有效手段。在InnoDB中,使用聯合索引配合主鍵索引可以直接返回結果而不需要回表查詢。

    聯合索引(復合索引)與前綴索引(最左原則)

    Mysql從左到右的使用索引中的字段,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是(a,b,c),可以支持 a | a,b | a,b,c 3種組合進行查找,但不支持 b,c 進行查找。這是最左原則的第一層意思:聯合索引的多個字段中,只有當查詢條件為聯合索引的第一個字段時,索引才會有效。

    條件 WHERE a LIKE 'perfix%'; 索引也會有效。這是最左原則的第二層意思:根據字段值最左若干個字符進行的模糊查詢,索引有效。

    覆蓋索引

    覆蓋索引是對聯合索引的合理利用。

    比如 SELECT a, b FROM table WHERE a = 'wangnima'; ,如果我們已經創建了(a)或(a,b)的聯合索引,那么這條語句會直接從索引返回而不會發生回表。即創建索引的字段覆蓋了查詢字段。

    如果執行 SELECT c FROM table WHERE a = 'wangnima'; ,就會發生回表,因為我們的輔助索引樹中,沒有字段 c 的數據,需要拿到主鍵索引的關鍵字,去主鍵索引中回表查詢。

    但是需要注意的是,索引雖好不可濫用。

    索引下推(Index Condition Pushdown (ICP))

    結合在 回表 概念中引出的三種索引使用情況(index key, index filter, table filter),ICP 技術,就是 index filter 技術。MySQL的架構分為服務器層引擎層

    官方解釋(https://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html)

    索引條件下推(ICP)是對MySQL使用索引從表中檢索行的情況的優化。如果沒有ICP,存儲引擎將遍歷索引以定位基表中的行,并將它們返回到MySQL服務器,該服務器將計算基表行的where條件。在啟用ICP的情況下,如果部分where條件可以通過只使用索引中的列來計算,MySQL服務器會把where條件的這部分 推入 存儲引擎。然后,存儲引擎通過使用索引條目來評估所推送的索引條件,并且只有在滿足該條件時才從表中讀取行。ICP可以減少存儲引擎必須訪問基本表的次數和MySQL服務器必須訪問存儲引擎的次數。

    根據官方的指導,我們來做個驗證:

    EXPLAIN SELECT * FROM people WHERE zipcode='95054' AND lastname LIKE '%lao%' AND address LIKE '%Main Street%';

    官方解釋:

    EXPLAIN使用“索引條件下推”時,輸出顯示 Using index condition在 Extra列中。

    假設一個表包含有關人員及其地址的信息,并且該表的索引定義為 INDEX (zipcode, lastname, firstname)。如果我們知道一個人的zipcode價值但不確定姓氏,我們可以這樣搜索:

    SELECT * FROM people WHERE zipcode='95054' AND lastname LIKE '%etrunia%' AND address LIKE '%Main Street%';

    MySQL可以使用索引來掃描人 zipcode='95054'。第二部分(lastname LIKE '%etrunia%')不能用于限制必須掃描的行數,因此如果沒有Index Condition Pushdown,此查詢必須為所有擁有的人檢索完整的表行 zipcode='95054'。

    使用索引條件下推,MySQL lastname LIKE '%etrunia%'在讀取整個表行之前檢查該 部分。這樣可以避免讀取與索引元組相對應的完整行,這些行匹配 zipcode條件而不是 lastname條件。

    默認情況下啟用索引條件下推。可以optimizer_switch通過設置index_condition_pushdown標志來控制 系統變量 :

    SET optimizer_switch = 'index_condition_pushdown=off'; SET optimizer_switch = 'index_condition_pushdown=on';

    實踐

    *注意語句中的“[ ··· ]”中括號指代變量,書寫時記得去掉

    普通索引

    這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:

    1. 創建索引

    CREATE INDEX indexName ON mytable(username(length));

    如果不是字符類型的字段,如int,則不要指定length;如果是CHAR,VARCHAR類型,length可以不指定,也可以小于字段實際長度;如果是BLOB和TEXT類型,必須指定 length。

    2. 修改表結構(添加索引)

    ALTER table tableName ADD INDEX indexName(columnName)

    3. 創建表的時候直接指定

    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) );

    唯一索引

    它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:

    1. 創建索引

    CREATE UNIQUE INDEX indexName ON mytable(username(length))

    2. 修改表結構

    ALTER table mytable ADD UNIQUE [indexName] (username(length))

    3. 創建表的時候直接指定

    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) );

    刪除索引的語法

    DROP INDEX [indexName] ON mytable;

    總結

    合理利用索引對于提升數據庫的性能、減輕數據庫服務器的負擔是最直接有效的手段。

    其實,索引的本質就是通過縮小范圍、把隨機事件變成順序事件來篩選出最終結果,同時可以總是用同一種查找方式來定位數據,這樣就可以兼顧高效率和穩定性。

    總結

    以上是生活随笔為你收集整理的mysql 隐藏中间四位_MySQL知识体系——索引的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。