主要來自 how does database indexing work?
本文適用於 mongodb、mysql 等多種使用 b-tree 作為索引資料結構的資料庫。
當資料儲存到基於磁碟的儲存裝置上時,資料被儲存為資料塊。磁碟塊的結構與鍊錶一樣;都是一部分包含資料,乙個指標指向下乙個塊,並且這兩者不一定要連續儲存。
由於這些記錄只在乙個欄位上排序,我們可以說搜尋非排序字段需要線性搜尋,這平均需要訪問n/2
個塊,n
是資料表對應的磁碟塊總數目。如果那個欄位是乙個 no-key 字段(比如不包含唯一約束),那麼整個表的空間n
都需要被搜尋到。
然而對於有序字段,可以使用二叉搜尋,這只需要訪問log2 n
。
索引是一種根據多個字段排序記錄的方式。建立乙個基於表中乙個欄位的索引會建立乙個包含字段值和指向記錄對應的磁碟塊的指標的資料結構。這個索引結構然後被排序,使二叉搜尋可以作用在這上面。
索引的負面是這些索引需要額外的磁碟空間。
假設乙個資料表結構:
field name data type size on disk
id (primary key) unsigned int 4 bytes
firstname char(50) 50 bytes
lastname char(50) 50 bytes
emailaddress char(100) 100 bytes
這個資料表含有 5000000 行並且沒有被索引。
假定有r = 5000000
個記錄,每個記錄的大小是r = 204
bytes,預設的 myisam 引擎的預設塊的大小是b = 1024
bytes。則表的塊因數是bfr = (b/r) = 1024/204 = 5
個記錄,每個磁碟塊。整個資料表對應的總塊數是n = (r/bfr) = 5000000/5 = 1,000,000
。
由於 id 欄位是乙個 key field,所以線性搜尋 id 字段平均需要訪問n/2 = 500,000
個塊。但因為 id 欄位也是有序的,使用二叉搜尋後平均需要訪問log2 1000000 = 19.93 = 20
個塊。我們可以看出這是乙個很大的提公升。
由於firstname
既不是有序的也不是 key field,所以需要掃瞄整個表,塊數為n = 1,000,000
。
由於索引記錄只包含被索引的字段和乙個指向磁碟塊的指標,所以索引記錄會比它指向的多個欄位的記錄更小。所以相比原始資料表索引需要更少的磁碟塊,因此只需要更少的磁碟塊。基於firstname
欄位的索引結構:
field name data type size on disk
firstname char(50) 50 bytes
(record pointer) special 4 bytes
由於資料表有r = 5,000,000
條記錄和乙個大小為r = 54
bytes 使用b = 1,024
bytes 的索引記錄。索引的塊因數為bfr = (b/r) = 1024/54 = 18
條記錄每個磁碟塊。索引對應n = (r/bfr) = 5000000/18 = 277,778
塊。
現在可以使用索引來提高用到firstname
字段搜尋的效能。對索引使用二叉搜尋後平均需要訪問log2 277778 = 18.08 = 19
塊。為了找到真實記錄對應的位址,需要多讀取乙個塊,所以總數是19 + 1 = 20
,與未建索引前的 1,000,000 相比是很驚人的。
由於建立索引
所以建立索引前需要慎重考慮。
資料的基數也很重要。索引的大小為資料總大小 / 基數
。索引越大,消耗的磁碟空間越大。低基數會使效率退化為線性排序,並且查詢器會避免使用小於 30% 記錄數的基數,所以低基數索引純粹是浪費空間。
復合索引可以被看做乙個包含多個索引字段值的有序的列表。 -- 來自 multiple-column indexes只有復合索引的最左索引部分可以使用索引。比如你有乙個 3 列索引
(col1, col2, col3)
,你只可以使用(col1)
,(col1, col2)
, 和(col1, col2, col3)
。原因是在 b-tree 搜尋[2]中,是通過比較大小來進行搜尋,而在復合索引中, 大小由最左索引部分決定,比如(10, , ) > (9, , )
、(10, 9, 8) > (9, 100, 100)
。
復合索引的另乙個選擇,你可以引入基於其他列的資訊的雜湊列。如果這個列更短、唯一並且被索引,它可能比乙個寬的多列索引更快。在 mysql 中,可以簡單的使用這個額外列進行查詢:
select * from tbl_name
where hash_col=md5(concat(val1,val2))
and col1=val1 and col2=val2;
how does database indexing work?
binary search tree searching
資料庫 資料庫索引
索引是儲存引擎用於快速找到記錄的一種資料結構。索引以檔案的形式儲存在磁碟中。索引可以包含乙個或多個列的值。儲存引擎查詢資料的時候,先在索引中找對應值,然後根據匹配的索引記錄找到對應的資料行。1.b tree索引 2.雜湊索引 myisam和innodb儲存引擎 只支援btree索引,也就是說預設使用...
資料庫mysql索引 資料庫 mysql索引
mysql 索引 mysql索引的建立對於mysql的高效執行是很重要的,索引可以大大提高mysql的檢索速度。打個比方,如果合理的設計且使用索引的mysql是一輛蘭博基尼的話,那麼沒有設計和使用索引的mysql就是乙個人力三輪車。索引分單列索引和組合索引。單列索引,即乙個索引只包含單個列,乙個表可...
資料庫索引
索引 索引列唯一索引 主鍵索引 聚簇索引和非聚簇索引 如何建立索引 如何刪除索引 使用索引可快速訪問資料庫表中的特定資訊。索引是對資料庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓 lname 列。如果要按姓查詢特定職員,與必須搜尋表中的所有行相比,索引會幫助您更快地獲得該資...