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

歡迎訪問 生活随笔!

生活随笔

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

数据库

数据库索引详解

發布時間:2024/8/1 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库索引详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、什么是索引?為什么要用索引?

1.1、索引的含義
數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢,更新數據庫中表的數據。索引的實現通常使用B樹和變種的B+樹(MySQL常用的索引就是B+樹)。除了數據之外,數據庫系統還維護為滿足特定查找算法的數據結構,這些數據結構以某種方式引用數據,這種數據結構就是索引。簡言之,索引就類似于書本,字典的目錄。
1.2、為什么用索引?
打個比方,如果正確合理設計使用索引的MySQL是一輛蘭博基尼的話,那么沒有設計和使用索引的MySQL就是一個人力三輪車。對于沒有索引的表,單表查詢可能幾十萬數據就是瓶頸,二通常大型網站單日就可能產生幾十萬甚至幾百萬的數據,沒有索引查詢會變得非常緩慢。一言以蔽之,合理使用索引,可以加快數據庫的查詢效率和提升程序性能

索引的作用與缺點

2.1、作用

  • 通過創建索引,可以再查詢的過程中,提高系統的性能
  • 通過創建唯一性索引,可以保持數據庫表中每一行數據的唯一性
  • 在使用分組和排序子句進行數據檢索時,可以減少查詢中分組和排序的時間
    2.2、缺點
  • 創建索引和維護索引要耗費時間,而且時間隨著數據量的增加而增大
  • 索引需要占用物理空間,如果要建立聚簇索引,所需要的空間會更大
  • 在對表中的數據進行增刪改時需要耗費較多的時間,因為索引也要動態地維護
  • 3、索引的使用場景

    3.1、應創建索引的場景

  • 經常需要搜索的列上
  • 作為主鍵的列上
  • 經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度
  • 經常需要根據范圍進行搜索的列上
  • 經常需要排序的列上
  • 經常使用在where子句上面的列上
  • 3.2、不應該創建索引的場景

  • 查詢中很少用到的列
  • 對于那些具有很少數據值的列,比如數據表中的性別列,bit數據類型的列
  • 對于那些定義為text,image的列,因為這些列的數據量相當大
  • 當對修改性能的要求遠遠大于搜索性能時,因為當增加索引時,會提高搜索性能,但是會降低修改性能
  • 4、索引的分類與說明

    4.1、主鍵索引
    設定為主鍵后數據庫會自動建立索引,innodb為聚簇索引

    #隨表一起建索引: CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),PRIMARY KEY(id) ); #使用AUTO_INCREMENT關鍵字的列必須有索引(只要有索引就行)。 CREATE TABLE customer2 (id INT(10) UNSIGNED,customer_no VARCHAR(200),customer_name VARCHAR(200),PRIMARY KEY(id) ); #單獨建主鍵索引: ALTER TABLE customer add PRIMARY KEY customer(customer_no); #刪除建主鍵索引: ALTER TABLE customer drop PRIMARY KEY ; #修改建主鍵索引: #必須先刪除掉(drop)原索引,再新建(add)索引

    4.2、單列索引
    一個索引只包含單個列,一個表可以有多個單列索引

    #隨表一起建索引: CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),PRIMARY KEY(id),KEY (customer_name) ); #隨表一起建立的索引 索引名同 列名(customer_name) #單獨建單值索引: CREATE INDEX idx_customer_name ON customer(customer_name); #刪除索引: DROP INDEX idx_customer_name ;

    4.3、唯一索引
    索引列的值必須唯一,但允許有空值

    #隨表一起建索引: CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),PRIMARY KEY(id),KEY (customer_name),UNIQUE (customer_no) ); #建立 唯一索引時必須保證所有的值是唯一的(除了null),若有重復數據,會報錯。 #單獨建唯一索引: CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no); #刪除索引: DROP INDEX idx_customer_no on customer ;

    4.4、復合索引
    一個索引包含多個列,在數據庫操作期間,復合索引比單值索引所需要的開銷更小(對于相同的多個列建索引)
    如果一個表中的數據在查詢時有多個字段總是同時出現則這些字段就可以作為復合索引,形成索引覆蓋可以提高查詢的效率!

    #隨表一起建索引: CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),PRIMARY KEY(id),KEY (customer_name),UNIQUE (customer_name),KEY (customer_no,customer_name) ); #單獨建索引: CREATE INDEX idx_no_name ON customer(customer_no,customer_name); #刪除索引: DROP INDEX idx_no_name on customer ;

    4.5、聚集索引與非聚集索引
    4.5.1、聚集索引
    聚集索引:指索引項的排序方式和表中數據記錄排序方式一致的索引。它會根據聚集索引鍵的順序來存儲表中的數據,即對表的數據按索引鍵的順序進行排序,然后重新存儲到磁盤上。因為數據在物理存放只能有一種排列方式,所以一個表只能有一個聚集索引。比如字典中,用拼音查漢字,就是聚集索引。因為正文中字都是按照拼音排序的。而用偏旁部首查漢字,就是非聚集索引,因為正文中的字并不是按照偏旁部首排序的,我們通過檢字表得到正文中的字在索引中的映射,然后通過映射找到所需要的字。

    聚集索引的使用場合為:
    查詢命令的回傳結果是以該字段為排序依據的;
    查詢的結果返回一個區間的值;
    查詢的結果返回某值相同的大量結果集

    聚集索引會降低insert,和update操作的性能,所以,是否使用聚集索引要全面衡量。

    4.5.2、非聚集索引
    非聚集索引:與聚集索引相反,索引順序與物理存儲順序不一致
    非聚集索引的使用場合為:
    查詢所獲數據量較少時;
    某字段中的數據的唯一性比較高時;

    非聚集索引必須是稠密索引

    4.5.3、使用及語法

    create [unique] [clustered] [nonclustered] index index_name on {tabel/view} (column[dese/asc][....n])

    住:[ unique ] [clu stered] [nonclustered]表示要創建索引的類型,以此為唯一索引,當省略unique選項時,建立非唯一索引,當省略clustered,nonclustered選項時。建立聚集索引,省略nonclusterrd選項時,建立唯一聚集索引。

    4.5.4、使用場景對比

    動作描述使用聚集索引使用非聚集索引
    列經常被分組排序使用使用
    返回某范圍內的數據使用不使用
    一個或極少不同值不使用不使用
    小數目的不同值使用不使用
    大數目的不同值不使用使用
    頻繁更新的列不使用使用
    外鍵列使用使用
    主鍵列使用使用
    頻繁修改索引列不使用使用

    4.6聚簇索引與非聚簇索引
    4.6.1、聚簇索引
    聚簇索引并不是一種單獨的索引類型,而是一種數據存儲方式。將數據存儲于索引放到了一塊,索引結構的葉子節點保存了行數據。

    聚簇索引的特點:
    1、聚簇索引具有唯一性,由于聚簇索引是將數據跟索引結構放到一塊,因此一個表僅有一個聚簇索引。
    2、表中行的物理順序和索引中行的物理順序是相同的,在創建任何非聚簇索引之前創建聚簇索引,這是因為聚簇索引改變了行的物理順序,數據行,按照一定的順序排列,并且自動維護這個順序;
    3、聚簇索引默認是主鍵,如果表中沒有定義主鍵,InnoDB會選擇一個唯一且非空的索引代替。如果沒有這樣的索引,InnoDB會隱式定義一個主鍵(類似oracle中的Rowld)來作為聚簇索引。如果已經設置了主鍵為聚簇索引又希望再單獨設置聚簇索引,必須先刪除主鍵,然后再添加我們想要的聚簇索引,隨后恢復設置主鍵即可。

    4.6.2、非聚簇索引
    不是聚簇索引的二級索引,也叫作輔助索引,都稱為非聚簇索引。將數據與索引分開存儲,索引結構的葉子節點指向了數據對應的位置。

    4.6.3、MySQL的MyIsam和InnoDB存儲引擎
    因為這兩種引擎對非聚簇索引和聚簇索引的使用,就是他們之間很大的一個區別。所以結合這兩個引擎,再對這兩種索引展開些描述就更明了了。

    在InnoDB中,在聚簇索引之上創建的索引稱之為 索引,非聚簇索引都是輔助索引,像復合索引,前綴索引,唯一索引。輔助索引葉子節點存儲的不再是行的物理位置,而是主鍵值,輔助索引訪問數據總是需要二次查找。

    1、InnoDB使用的是聚簇索引,將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用“where id = 14”這樣的條件查找主鍵,則按照B+樹的檢索算法即可查找到對應的葉節點,之后獲得行數據。
    2、若對Name列進行條件搜索,則需要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹中再執行一次B+樹檢索操作,最終到達葉子節點即可獲取整行數據。(重點在于通過其他鍵需要建立輔助索引)

    MyIsam使用的是非聚簇索引,非聚簇索引的兩顆B+樹看上去沒什么不同,節點的結構完全一致只是存儲的內容不同而已,主鍵索引B+樹的節點存儲了主鍵,輔助索引B+樹存儲了輔助鍵。表數據存儲在獨立的地方,這兩棵B+樹的葉子節點都使用一個地址指向真正的表數據,對于表數據來說,這兩個鍵沒有任何差別。由于索引樹是獨立的,通過輔助鍵索引無需訪問主鍵的索引樹。

    4.6.4、對比總結
    每次使用輔助索引檢索都要經過兩次B+熟查找,看上去聚簇索引的效率明顯低于非聚簇索引,這不是多此一舉嗎?聚簇索引的優勢在哪里?
    1、由于行數據和聚簇索引的葉子節點存儲在一起,同一頁中會有多條行數據,訪問同一數據頁不同行記錄時,已經把頁加載到了Buffer中(緩存器),再次訪問時,會在內存中完成訪問,不必訪問磁盤,這樣主鍵和行數據是一起被載入內存的,找到葉子節點就可以立即將行數據返回了,如果按照主鍵ID來組織數據,獲得數據更快。
    2、輔助索引的葉子節點,存儲主鍵值,而不是數據的存放地址。好處是當行數據發生改變時,索引樹的節點也需要分裂變化;或者是我們需要查找的數據,在上一次IO讀寫的緩存中沒有,需要發生一次新的IO操作時,可以避免對輔助索引的維護工作,只需要維護聚簇索引樹就好了,另一個好處是,因為輔助索引存放的是主鍵值,減少了輔助索引占用的存儲空間大小。
    注:我們知道一次IO讀寫,可以獲取到16K大小的資源,我們稱之為讀取到的數據區域為Page。而我們的B樹,B+樹的索引結構,葉子節點上存放好多個關鍵字(索引值)和對應的數據,都會在一次IO操作中被讀取到緩存中,所以在訪問同一個頁中的不同記錄時,會在內存里操作,而不用再次進行IO操作了。除非發生了頁的分裂,即要查詢的行數據不在上次IO操作的換襯里才會觸發新的IO操作。
    3、因為MyIsam的主索引并非聚簇索引,那么他的數據的物理地址必定是凌亂的,拿到這些物理地址,按照合適的算法進行I/O讀取,于是開始不停的尋道不停的旋轉。聚簇索引則只需一次I/O。(強烈的對比)
    4、不過,如果涉及到大數據的排序,全表掃描,count之類的操作的話,還是MyIsam占優勢些,因為索引所占空間小,這些操作是需要在內存中完成的。
    5、當使用主鍵為聚簇索引時,主鍵最好不要使用uuid,因為uuid的值太過離散,不適合排序且可能出現新增加記錄的uuid,會插入在索引樹中間的位置,導致索引樹調整復雜度變大,消耗更多的時間和資源。建議使用int類型的自增,方便排序并且默認會在索引樹的末尾增加主鍵值,對索引樹的結構影響最小。而且,主鍵值占用的存儲空間越大,輔助索引中保存的主鍵值也會跟著變大,占用存儲空間,也會影響到IO操作讀取到的數據量。

    4.7、稠密索引與稀疏索引
    在了解稠密索引和稀疏索引之前我們先來了解一下什么是聚焦索引。在一個文件中,可以有多個索引,分別基于不同的索引碼。如果包含數據記錄的文件按照某個指定的順序排列,那么該搜索碼對應的索引就是聚焦索引。

    4.7.1、稠密索引
    在稠密索引中,文件中的每個搜索碼值都對應一個索引值,也就是說,稠密索引為數據記錄文件的每一條記錄都設一個鍵-指針對。如下圖所示,索引項包括索引值以及指向搜索碼的第一條數據記錄的指針,即我們所說的鍵-指針對。

    4.7.2、稀疏索引
    在稀疏索引中,只為搜索碼的某些值建立索引項,也就是說,系數索引為數據記錄文件的每個存儲塊設一個鍵-指針對,存儲塊意味著塊內存存儲單元連續,如下圖所示:

    索引的底層原理

    拋開其他的數據庫索引實現,主講MySQL的索引底層實現,其底層是通過B+樹來實現的數據結構存儲。
    數據結構存儲,決定了數據查找和操作時的效率,包括時間復雜度和空間復雜度,而在取舍的時候,也無非就是時間換空間,空間換時間的權衡罷了,所以,這就很好的解釋了,為什么MySQL在索引的底層設計上,選用了B+樹,而沒有選用B-樹,或是紅黑樹,AVL樹等等其他數據結構。總之,就是使用B+樹作為索引的結構存儲,能在I/O性能上得到一個較大的優勢。

    那么具體優勢在哪里呢?以B-樹與B+樹的對比,來闡述具體差異和B+樹的優勢。

    5.1、B-Tree
    B-樹是一種多路自平衡的搜索樹,它類似普通的平衡二叉樹,不同的一點是B-樹允許每個節點有更多的子節點。B-Tree相對于AVLTree縮減了節點個數,使每次磁盤I/O取到內存的數據都發揮了作用,從而提高了查詢效率。
    注:B-Tree就是我們常說的B樹
    那么m階B-Tree是滿足下列條件的數據結構:
    所有鍵值分布在整棵樹中
    搜索有可能在非葉子節點結束,在關鍵字全集內做一次查找,性能逼近二分查找
    每個節點最多擁有m個子樹
    根節點至少有2個子樹
    分支節點至少擁有m/2顆子樹(除根節點和葉子節點外都是分支節點)
    所有葉子節點都在同一層,每個節點最多可以有m-1個key,并且以升序排列

    每個節點占用一個磁盤塊,一個節點上有兩個升序排序的關鍵字和三個指向子樹根節點的指針,指針存儲的是子節點所在磁盤塊的地址。兩個關鍵詞劃分成的三個范圍域對應三個指針指向的子樹的數據的范圍域。以根節點為例,關鍵字為17和35,P1指針指向的子樹的數據范圍小于17,P2指針指向的子樹的數據范圍為17~35,P3指針指向的子樹的數據范圍大于35.

    模擬查找關鍵字29的過程:
    1、根據根節點找到磁盤塊1,讀入內存。【磁盤I/O操作第1次】
    2、比較關鍵字29在區間(17,35),找到磁盤塊1的指針P2。
    3、根據P2指針找到磁盤塊3,讀入內存。【磁盤I/O操作第2次】
    4、比較關鍵字29在區間(26,30),找到磁盤塊3的指針P2。
    5、根據P2指針找到磁盤塊8,讀入內存。【磁盤I/O操作第3次】
    6、在磁盤塊8中的關鍵字列表中找到關鍵字29。
    7、分析上面過程,發現需要3次磁盤I/O操作,和3次內存查找操作。由于內存中的關鍵字是一個有序表結構,可以利用二分法查找提高效率。而3次磁盤I/O操作是影響整個B-Tree查找效率的決定因素。

    但同時B-Tree也存在問題:
    每個節點中有key,也有data,而每一個頁的存儲空間是有限的,如果data數據較大時將會導致每個節點(即一個頁)能存儲的key的數量很小。
    當存儲的數據量很大時同樣會導致B-Tree的深度較大,增大查詢時的磁盤I/O次數,進而影響查詢效率

    5.2、B+Tree
    B+Tree是在B-Tree基礎上的一種優化,InnoDB存儲引擎就是用B+Tree實現其索引結構。它帶來的變化點:
    B+樹每個節點可以包含更多的節點,這樣做有兩個原因,一個是降低樹的高度。另外一個是將數據范圍變為多個區間,區間越多,數據檢索越快
    非葉子節點存儲key,葉子節點存儲key和數據
    葉子節點兩兩指針相互鏈接(符合磁盤的預讀特性),順序查詢性能更高

    注:MySQL的InnoDB存儲引擎在設計時是將根節點常駐內存,因此力求達到樹的深度不超過3,也就是說I/O不需要超過3次。

    通常在B+Tree上有兩個頭指針,一個指向根節點,另一個指向關鍵字最小的葉子節點,而且所有葉子節點(即數據節點)之間是一種鏈式環結構,因此可以對B+Tree進行兩種查找運算:一種是對于主鍵的范圍查找的分頁查找,另一種是從根節點開始,進行隨機查找。

    5.3、B-樹和B+樹的區別
    B+樹內節點不存儲數據,所有數據存儲在葉節點導致查詢時間復雜度固定為log n
    B-樹查詢時間復雜度不固定,與Key在樹中的位置有關,最好為O(1)
    B+樹葉節點兩兩相連可大大增加區間訪問性,可使用在范圍查詢等
    B+樹更適合外部存儲(存儲磁盤數據)。由于內節點無data域,每個節點能索引的范圍更大更精確。

    總結

    以上是生活随笔為你收集整理的数据库索引详解的全部內容,希望文章能夠幫你解決所遇到的問題。

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