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

歡迎訪問 生活随笔!

生活随笔

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

数据库

MySQL数据库:索引的实现原理

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

一、什么是索引:

索引就是一種的數據結構,通過縮小一張表中需要查詢的數據來加快搜索的速度。如果沒有索引,數據庫不得不進行全表掃描。好比書的目錄,讓你更快的找到內容。??

1、索引的優點:?

(1)大大減少查詢需要檢索的行數,加快查詢速度,避免進行全表掃描,這也是創建索引的最主要的原因。

(2)如果索引的數據結構是B+樹,在使用分組和排序時,可以顯著減少查詢中分組和排序的時間。

(3)通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。

2、索引的缺點:

(1)當對表中的數據進行增加、刪除和修改時,索引也要進行更新,維護的耗時隨著數據量的增加而增加。

(2)索引需要占用物理空間,如果要建立聚簇索引,那么需要的空間就會更大。

3、索引的使用場景:

(1)在哪些列上面創建索引:

  • WHERE子句中經常出現的列上面創建索引,加快條件的判斷速度。
  • 按范圍存取的列或者在group by或order by中使用的列,因為索引已經排序,這樣可以利用索引加快排序查詢時間。
  • 經常用于連接的列上,這些列主要是一些外鍵,可以加快連接的速度;
  • 作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;

(2)不在哪些列建索引?

只有很少數據值的列不應該增加索引。由于這些列的取值很少,例如性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。

在查詢中很少的列不應該創建索引。由于這些列很少使用到,但增加了索引,反而降低了系統的維護速度和增大了空間需求。

當添加索引造成修改成本的提高 遠遠大于 檢索性能的提高時,不應該創建索引。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。

定義為text, image和bit數據類型的列不應該增加索引。這些列的數據量要么相當大,要么取值很少。

二、常見索引類型:

常見的索引類型有:普通索引、唯一索引、主鍵索引、全文索引、組合索引。

1、普通索引:

最基本的索引,沒有任何限制。

--直接創建索引: CREATE?INDEX?index_name?ON?table(column(length);--修改表結構的方式添加索引: ALTER TABLE table_name ADD INDEX index_name ON (column(length));--創建表的時候同時創建索引: CREATE TABLE ‘table’(?? ID INT NOT NULL,? ? username VARCHAR(16) NOT NULL,?? INDEX [indexName] (username(length))?? );??

2、唯一索引:

與普通索引類似,但索引列的值必須唯一,允許有空值,可以有多個NULL值。如果是組合索引,則列值的組合必須唯一,創建方法和普通索引類似。

--創建唯一性索引: CREATE UNIQUE INDEX indexName ON mytable(username(length));--修改表結構: ALTER TABLE table_name ADD UNIQUE indexName ON (column(length));--創建表的時候指定: CREATE TABLE mytable(?? ID INT NOT NULL,? ? username VARCHAR(16) NOT NULL,?? UNIQUE [indexName] (username(length)) );??

3、主鍵索引:

可以理解為一種特殊的唯一索引,不允許有空值。

--創建表的時候創建,當把某個列設為主鍵的時候,數據庫會自動的創建一個以主鍵作為名稱的主鍵索引。 CREATE TABLE table( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(32) NOT NULL) );--修改表結構: ALTER TABLE `table_name` ADD?PRIMARY KEY?( `col` );

4、全文索引:

全文索引僅可用于 MyISAM 表,并只支持從CHAR、VARCHAR或TEXT類型,用于替代效率較低的like 模糊匹配操作,而且可以通過多字段組合的全文索引一次性全模糊匹配多個字段。對于大容量的數據表,生成全文索引是一個非常消耗時間和硬盤空間的做法。對于較大的數據集,將你的數據輸入一個沒有FULLTEXT索引的表中,然后創建索引,其速度比把數據輸入現有FULLTEXT索引的速度更為快。

全文索引使用B樹存放索引數據,但使用的是特定的算法,將字段數據分割后再進行索引(一般每4個字節一次分割),索引文件存儲的是分割前的索引字符串集合,與分割后的索引信息,對應Btree結構的節點存儲的是分割后的詞信息以及它在分割前的索引字符串集合中的位置。

–創建表的適合添加全文索引 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), FULLTEXT (content) );–修改表結構添加全文索引 ALTER TABLE article ADD FULLTEXT index_content(content);–直接創建索引 CREATE FULLTEXT INDEX index_content ON article(content);

5、組合索引:(最左前綴)

為了更多的提高mysql效率可建立組合索引。創建組合索引時應該將最常用(頻率)作限制條件的列放在最左邊,依次遞減。

--創建組合索引: ALTER TABLE `table_name` ADD?INDEX index_name?(col1(length), col2(length), col3(length));

6、顯示索引信息:

可以使用 SHOW INDEX 命令來列出表中的相關的索引信息??梢酝ㄟ^添加 \G 來格式化輸出信息。

SHOW INDEX FROM table_name; \G........

7、刪除索引:

DROP INDEX [indexName] ON mytable; --第一種方式 ALTER TABLE testalter_tbl DROP INDEX c; --第二種方式

三、聚簇索引與非聚簇索引:

如果按照表中 數據存儲的物理順序與索引值的順序分類,可以將索引分為聚簇索引與非聚簇索引兩類。

1、聚簇索引(cluster):

聚簇索引要求表中數據存儲的物理順序與索引值的順序一致,一個基本表最多只能有一個聚簇索引,更新聚簇索引列上的數據時,往往導致表中記錄的物理順序的變更,代價較大,因此對于經常更新的列不宜建立聚簇索引

聚簇索引一般在下面場景使用:

(1)主鍵列,InnoDB存儲引擎中,默認為表的主鍵建立一個聚簇索引。

(2)按范圍存取的列或者在group by或order by中使用的列。在聚簇索引下,因為表中數據存儲的物理順序與索引的邏輯順序一致,所以在包含范圍檢查(between、<、<=、>、>=)或使用group by或order by的查詢時,一旦找到具有范圍中第一個鍵值的行,具有后續索引值的行保證物理上毗連在一起而不必進一步搜索,避免了大范圍掃描,可以大大提高查詢速度。

(3)在連接操作中使用的列。

(4)不經常修改的列。因為碼值修改后,數據行必須移動到新的位置。

2、非聚簇索引:

表中記錄的物理順序與索引值的順序不一致的索引組織,一個基本表可以有多個聚簇索引。

四、MySQL索引的數據結構:

常見的索引的數據結構有:B+Tree、Hash索引。

1、Hash索引:

MySQL中,只有Memory存儲引擎支持hash索引,是Memory表的默認索引類型。hash索引把數據以hash值形式組織起來,因此檢索效率非常高,可以一次定位。

hash索引的缺點:

(1)Hash索引僅能滿足等值的查詢,不能滿足范圍查詢、排序。因為數據在經過Hash算法后,其大小關系就可能發生變化。

(2)當創建組合索引時,不能只適用組合索引的部分列進行查詢。因為hash索引是把多個列數據合并后再計算Hash值,所以對單獨列數據計算Hash值是沒有意義的。

(3)當發生Hash碰撞時,Hash索引不能避免表數據的掃描。因為僅僅比較Hash值是不夠的,需要比較實際的值以判定是否符合要求。

2、B+Tree索引:

B+Tree是mysql使用最頻繁的一個索引數據結構,是Innodb和Myisam存儲引擎模式的索引類型。相對Hash索引,B+Tree索引在查找時需要從根節點到葉節點進行多次IO操作,在查詢速度比不上Hash索引,但是更適合排序等操作。

B+Tree索引的優點(也是為什么使用B+Tree索引的主要原因):

(1)帶順序訪問指針的B+Tree:B+Tree所有索引數據都存儲在葉子結點上,并且增加了順序訪問指針,每個葉子節點都有指向相鄰葉子節點的指針。這樣做是為了提高區間查詢效率,例如查詢key為從18到49的所有數據記錄,當找到18后,只需順著節點和指針順序遍歷就可以一次性訪問到所有數據節點。

(2)大大減少磁盤I/O讀取次數。(詳細看本博客第二部分)

五、為什么使用B+Tree作為索引:

一般來說,索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。這樣的話,索引查找過程中就要產生磁盤I/O消耗,相對于內存存取,I/O存取的消耗要高幾個數量級,所以評價一個數據結構作為索引的優劣最重要的指標就是在查找過程中磁盤I/O操作次數的漸進復雜度。換句話說,索引的數據結構要盡量減少查找過程中磁盤I/O的存取次數。

下面先介紹內存和磁盤存取原理,然后再結合這些原理分析B+Tree作為索引的效率。

1、局部性原理與磁盤預讀:

????????由于存儲介質的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分之一,因此為了提高效率,要盡量減少磁盤I/O。為了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向后讀取一定長度的數據放入內存。這樣做的理論依據是計算機科學中著名的局部性原理:當一個數據被用到時,其附近的數據也通常會馬上被使用。程序運行期間所需要的數據通常比較集中。

????????由于磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對于具有局部性的程序來說,預讀可以提高I/O效率。預讀的長度一般為頁的整倍數。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置并向后連續讀取一頁或幾頁載入內存中,然后異常返回,程序繼續運行。

????????頁是計算機管理存儲器的邏輯塊,硬件及操作系統往往將主存和磁盤存儲區分割為連續的大小相等的塊,每個存儲塊稱為一頁(在許多操作系統中,頁得大小通常為4k),主存和磁盤以頁為單位交換數據。

2、B+Tree索引的性能分析:

????????上文說過一般使用磁盤I/O次數評價索引結構的優劣。

????????先從B樹分析,B樹檢索一次最多需要訪問h個節點,同時,數據庫巧妙利用了磁盤預讀原理,將一個節點的大小設為等于一個頁(InnoDB 頁的大小默認是16k),即每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點在物理上也存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,這樣就實現了每個節點只需要一次I/O就可以完全載入。B樹中一次檢索最多需要h-1次I/O(根節點常駐內存),時間復雜度為O(h)=O(logdN)。一般實際應用中,出度d是非常大的數字,通常超過100,因此h非常小。

????????綜上所述,用B-Tree作為索引結構效率是非常高的。而紅黑樹這種結構,雖然時間復雜度也為O(h),但是h明顯要深的多,并且由于邏輯上很近的節點,在物理上可能很遠,無法利用局部性,所以IO效率明顯比B樹差很多。

????????另外,B+Tree更適合作為索引的數據結構,原因和內節點出度d有關。從上面分析可以看到,d越大索引的性能越好,而出度d的上限取決于節點內key和data的大小,由于B+Tree內節點去掉了data域,因此可以擁有更大的出度,磁盤IO的次數也就更少了。

3、B-Tree與B+Tree的對比:

????????根據B-Tree 和 B+Tree的結構,我們可以發現B+樹相比于B樹,在文件系統或者數據庫系統當中,更有優勢,原因如下:

(1)B+樹有利于對數據庫的掃描:B樹在提高了磁盤IO性能的同時并沒有解決元素遍歷的效率低下的問題,而B+樹只需要遍歷葉子節點就可以解決對全部關鍵字信息的掃描,所以范圍查詢、排序等操作,B+樹有著更高的性能。

(2)B+樹的磁盤IO代價更低:B+樹的內部結點的data域并沒有存儲數據,因此其內部結點相對于B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多,相對來說I/O讀寫次數也就降低了。

(3)B+樹的查詢效率更加穩定:由于B+樹的內部結點只是葉子結點中關鍵字的索引,并不存儲數據。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

六、MySQL索引的實現:

在MySQL中,索引屬于存儲引擎級別的概念,不同存儲引擎對索引的實現方式是不同的,本部分主要討論MyISAM和InnoDB兩個存儲引擎的索引實現方式。

?1、MyISAM索引的實現:

(1)主鍵索引:MyISAM引擎使用B+Tree作為索引結構,葉子節點的data域存放的是數據記錄的地址。下圖是MyISAM索引的原理圖:

里設表一共有三列,假設我們以Col1為主鍵,則上圖是一個MyISAM表的主鍵索引(Primary key)示意??梢钥闯鯩yISAM的索引文件僅僅保存數據記錄的地址。

(2)輔助索引:

在MyISAM中,主鍵索引和輔助索引在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。如果我們在Col2上建立一個輔助索引,則此索引的結構如下圖所示:?

同樣也是一棵B+Tree,data域保存數據記錄的地址。

因此,MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址,讀取相應數據記錄。

MyISAM的索引方式也叫做“非聚集”的,之所以這么稱呼是為了與InnoDB的聚集索引區分。

2、InnoDB索引的實現:

雖然InnoDB也使用B+Tree作為索引結構,但具體實現方式與MyISAM卻不相同。

(1)主鍵索引:

與MyISAM第一個重大區別是InnoDB的數據文件本身就是索引文件。從上文知道,MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

上圖是InnoDB主索引(同時也是數據文件)的示意圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引,因為InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵,這個字段長度為6個字節,類型為長整形。

(2)輔助索引:

第二個與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。例如,下圖為定義在Col3上的一個輔助索引:

這里以英文字符的ASCII碼作為比較準則。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。不過由于輔助索引會包含主鍵列,所以,如果主鍵使用過長的字段,將會導致其他輔助索變得更大。所以爭取盡量把主鍵定義得小一些

?InnoDB 表是基于聚簇索引建立的。

3、小結:

(1)InnoDB索引和MyISAM索引的區別:

MyISAM和InnoDB都是使用B+樹索引,MyISAM的主鍵索引和輔助索引的Data域都是保存行的地址,但是InnoDB的主鍵索引保存的不是行的地址,而是保存該行的所有所有數據,而輔助索引的Data域保存的則是主索引的值。

(2)了解不同存儲引擎的索引實現方式對于正確使用和優化索引都非常有幫助,例如知道了InnoDB的索引實現后,就很容易明白為什么不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段作為主鍵在InnoDB中不是個好主意,因為InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。

相關博客:

https://blog.csdn.net/zhangliangzi/article/details/51366345

https://blog.csdn.net/Debug_zhang/article/details/52168552

https://blog.csdn.net/kennyrose/article/details/7532032

總結

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

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