建立二級索引 InnoDB索引

2021-10-14 17:48:07 字數 3472 閱讀 8058

聚簇索引

二級索引

聯合索引

innodb的b+數索引的注意事項

索引的一些結論

索引的代價

覆蓋索引

如何挑選索引?

主鍵插入順序

b+樹索引在空間和時間上都有代價,不要亂建索引!

b+樹索引適用於下邊這些情況:

b+樹索引不能用下邊這些情況:

asc、desc混用:不能高效地利用索引

where子句**現非排序使用到的索引列

排序列包含非同乙個索引的列

排序列使用了複雜的表示式

在行記錄中有兩個屬性對索引至關重要——record_type(代表記錄型別,0代表普通記錄,1代表索引記錄,2代表最小記錄,3代表最大記錄)和next_record(到下一條記錄的位址偏移)。在頁中還有乙個叫做頁面目錄的元素,我們可以根據主鍵的大小,使用二分快速的定位到目標記錄所在的槽即可找到指定的記錄。

為了節省篇幅,我們可以這樣來表示頁裡面的記錄:

那麼如果我們要在很多頁,甚至不使用主鍵查詢的時候呢?如果沒有乙個合理的方案我們只能遍歷所有的記錄,這無疑是效率非常低下的。

為了讓頁之間的資料有規律,能讓我們使用特定的演算法(如二分)定位到指定頁。我們規定:

下乙個資料頁中使用者記錄的主鍵值必須大於上乙個頁中使用者記錄的主鍵值。如果乙個頁中的記錄超過一定值,我們就新增乙個頁,然後將原來頁中的一部分記錄移動到新增頁。因為頁與頁之間是雙鏈表的結構,因此新增和刪除都很簡單。

給所有頁都建立乙個目錄項。

目錄項和記錄頁是差不多的,只不過目錄項的兩個列是主鍵和頁號。innodb的設計者使用record_type為1的頁代表目錄項記錄。這些目錄項可以放在乙個專門記錄目錄項的頁當中:

一般還會有乙個更高階的目錄儲存著目錄項記錄的頁:

目錄項的record_type是1,而普通使用者記錄的record_type是0。

目錄項記錄只有主鍵值和頁的編號兩個列,而普通的使用者記錄可能包含自己定義很多列,另外還有隱藏列

只要在儲存目錄項的頁中的主鍵值最小的目錄項記錄min_rec_mask的值為1,其他的都是0.

上面的b+數本身就是乙個目錄,或者說本身就是乙個索引,它有兩個特點:

使用記錄主鍵值的大小進行記錄和頁的排序,這包括三個方面的含義

b+樹的葉子節點儲存的是完整的使用者記錄

我們將具有這兩個特點的b+樹稱為聚簇索引,所有完整的使用者記錄都放在這個聚簇索引的葉子節點。聚簇索引不需要我們在mysql語句中顯式的使用index語句去建立,innodb會自動為我們建立聚簇索引,聚簇索引也是資料的儲存方式。

加入我們以別的列作為搜尋條件時,可以多建幾顆b+樹,不同的b+樹的資料採用不同的排序規則。這種b+樹與上面的聚簇索引有些許不同:

使用記錄指定列的大小進行記錄和頁的排序;

b+樹的葉子節點儲存的並不是完整的使用者記錄,而只是指定列+主鍵兩個列的值

目錄項記錄中不再是主鍵+頁號的搭配,而是指定列+頁號的搭配

也就是如果我們使用別的列作為搜尋條件,還需要先找到對應主鍵,然後再從聚簇索引中查詢到完整的使用者記錄。我們也將這個過程稱為回表

我們可以同時以多個列作為排序規則,也就是同時為多個列建立索引,比方說我們想讓b+數按照c2和c3列的大小進行排序,這樣包含了兩條排序規則:

先把各個記錄和頁按照c2進行排序

在記錄的c2列相同的情況下,採用c3列進行排序

每當乙個表建立了乙個b+樹索引之後,都會為這個索引建立乙個根節點頁面。最開始表中沒有資料的時候,每個b+樹索引對應的根節點中既沒有使用者記錄,也沒有目錄項記錄。

向表中插入使用者記錄的時候,先把使用者記錄儲存到這個根節點中,當根節點中的可用空間用完時繼續插入記錄,此時會將根節點中所有記錄複製到乙個新分配的頁,然後對這個新頁進行**操作,得到另外乙個新頁,然後根節點公升級成儲存目錄項記錄的頁

在b+樹中的同一層內節點的目錄項記錄除頁號這個字段以外是唯一的。因為新插入記錄必須能找到自己在哪個頁。

保證效率

空間代價:每個索引都對應一顆b+樹。

時間代價:插入一條記錄要對所有的b+樹進行維護,降低效能。

為了告別回表操作帶來的效能損耗,最好在查詢列表裡只包含索引列。因此不建議使用萬用字元*作為查詢列表,最好把要查詢的列一次註明。

也就是說只為出現在where子句的列、連線子句的連線列、或者出現再order by或group by的子句中的列建立索引

基數是指某一列中不重複資料的個數。最好為基數大的列建立索引,例如當基數為1的時候,為該列建立索引是沒用的,無法合理的利用索引。

索引占用空間小

索引比較快

假設我們字串很長,那麼儲存乙個字串就需要占用很大得儲存空間,在我們需要為這個字串列建立索引時,會出現索引占用空間大和字串比較占用時間長兩個問題。所以可以考慮使用字串得前幾個字元進行索引。

key idx_name_birthday_phone_number (name(10)), birthday, phone_number

where my_col * 2 where my_col
只有第二個表示式能用到索引

如果索引列在比較表示式中不是以單獨列的形式出現,而是以某個表示式,或者函式呼叫形式出現的話,是用不到索引的。

如果主鍵隨機插入,根據我們上文所講,聚簇索引的列是根據主鍵來排序的,這樣會使資料頻繁地複製到新增頁,使得效能降低,所以推薦使用主鍵自增。

innodb中索引即資料,也就是聚簇索引的那顆b+樹的葉子節點中已經把所有完整的使用者記錄都包含了,但myisam卻將索引和資料分開儲存:

將表中的記錄按照記錄的插入順序單獨儲存在乙個檔案中,稱為資料檔案,可以通過行號而快速訪問到一條記錄

使用myisam儲存引擎的表會把索引資訊另外儲存到乙個稱為索引檔案的檔案中,不過這裡是主鍵+行號的組合,myisam中建立的索引相當於全部都是二級索引!

如果記錄占用空間是固定的,就可以輕鬆算出記錄在資料檔案中的位址偏移量,如果採用的是變長記錄格式myisam將在索引葉子節點儲存資料檔案中的位址偏移量

建立二級索引 索引 一 Mysql建立索引

假如,乙個 薄裡面包含了乙個城市的所有人的姓名和 號碼。那麼,想找到bob cat的 號碼,另外我們知道 簿中名字是按照字母順序排列的,所以首先要查詢姓氏為cat的頁面,然後在這個頁面下查詢名字為bob的 號碼。那如果在 薄中的名字沒有按照字母排列,就需要去瀏覽所有的頁,然後在裡面查詢每個姓名直到找...

Phoenix二級索引建立

全域性索引是phoenix的重要特性,合理的使用二級索引能降低查詢延時,讓集群資源得以充分利用。本文將講述如何高效的設計和使用索引。全域性索引的根本是通過單獨的hbase表來儲存資料表的索引資料。我們通過如下示例看索引資料和主表資料的關係。建立資料表create table data table a...

聚集索引和二級索引

每個innodb的表都有個特殊的索引來存放資料 聚集索引。當在表上指定主鍵後,innodb使用它來作為聚集索引。如果沒有定義主鍵,會找非空唯一索引來作為clustered index 如果上面2個都沒有,那麼會在內部生成乙個隱藏的clustered index 通過乙個clustered index...