mysql多索引結構 MySQL 索引結構詳解

2021-10-17 15:16:33 字數 2241 閱讀 8328

innodb的主鍵索引(primary key)是cluster形式的(聚簇索引)。

innodb的非主鍵索引(secondary index)是普通的b+tree索引。

兩種索引在root node和branch node是一樣的,在leaf node就不一樣了。

primary key存放的是表的實際資料,不僅包含關鍵字段的資料,還包括其它欄位的資料,整個資料以主鍵之有序排列。

secondary index存放索引鍵的相關資訊,此外還有innodb的主鍵值(當移動行或資料頁的**,這個策略降低了維護次索引的工作)。

所以innodb通過主鍵來訪問資料效率是非常高的,而通過secondary index來訪問的話要經過兩步,從secondary index的leaf node獲取主鍵值,再通過主鍵值檢索一次。

myisam的主鍵索引和非主鍵索引的差別很小(區別是主鍵必須是唯一且非空的鍵)。

其儲存結構和secondary index也基本相同,差別是leaf node存放索引鍵的相關資訊外,存放能夠直接定位到myisam資料檔案中相應資料行的資訊,而不是主鍵值。

myisam的資料布局相對簡單,在硬碟上是按照插入的順序來儲存的。

下面從網上copy過來的示意圖,一目了然^-^:

innodb中按照主鍵的順序來插入行,如果不需要特殊的聚簇,定義乙個**鍵是個好注意(最簡單的是auto_increment列),

這樣保證資料插入保持著連續順序並且對於使用主鍵連線會獲得更好的效能。所以->

關於聚簇索引使用連續順序的鍵是最好的場景:

最好避免使用隨機的聚簇鍵。比如,從效能的角度來說,使用uuid是個不好的方法:它使聚簇索引的插入是隨機的。這是最不好的場景了。並且對於資料的聚集也沒有什麼幫助;uuid作為主鍵的表不僅插入速度慢,而且索引還非常的大。一些原因是由於主鍵變大,而另一些原因不用懷疑的就是頁的**和產生的一些碎片。

因為新行的主鍵並不是必須的比前乙個主鍵值要大,因此innodb不能總是把新行放到這個索引之後。必須要為新行找到乙個合適的位置-平均位置,也就是在靠近已存在資料的中部為新的資料生成乙個空間。這就導致了一些額外的工作以及不理想的資料布局:

1.目標頁要重新整理到硬碟並且要清除快取。innodb在插入新行之前,要找到它和從硬碟中讀取它。這就導致了很多的隨機io。

2.innodb有的時候會**頁,這樣做的目的是為新行建立空間。這需要移動很多的資料。

因為頁的**,頁會變得稀疏並且不規則的填充。因此最終資料是碎片的。

在讀取許多隨機值到聚簇索引中之後,你應該使用optimize table語句重新構建表並且優化的填充頁。

聚簇資料有很多重要的優勢。

能使相關聯的資料距離很近。比如,當要實現乙個mailbox,你可以通過user_id來聚簇,因此你能通過獲取硬碟上一小部分的頁來獲得乙個單獨使用者的所有訊息。如果你不做聚簇,那麼每個訊息可能都需要各自的硬碟i/o。

資料訪問更加快速。乙個聚簇索引在b-tree上即儲存了索引也儲存了資料。因此從聚集索引獲取行一般要快於在非聚集索引中比較查詢。

使用覆蓋索引的語句可以使用包含在葉子節點的主鍵值。

如果你設計表和語句的時候好好利用它們,對效能的提高大有幫助。然而聚簇索引也有很多缺點

聚簇會大幅提高io限制(io-bound)工作量。如果資料在記憶體中的順序對資料的訪問並不是什麼問題的話,聚簇就不能帶來那麼多好處了。

插入的順序影響插入的速度。按照主鍵的速度插入行是最快的讀入資料到innodb表的方法。如果你沒有依照主鍵的順序來讀取資料,那麼在讀取很多資料之後,使用optimize table來重新組織表是個很好的主意。

更新聚簇索引的列消耗是非常高的。因為它迫使innodb把每一行移動到新的位置。

當新的一行插入或行的主鍵更新,這樣會導致聚簇索引的頁的**。當乙個行的鍵值決定了該行以及它所有的資料一定要放在一頁裡的時候,頁的**就發生了。因為儲存引擎必須把頁分為兩個來容納這個行。頁的**會導致表占用更多的空間。

聚簇的表會降低檢索整張表的速度。尤其是在由於頁的**,造成行沒有被壓縮或者沒有連續的儲存的情況下,問題就很嚴重。

非聚簇索引可能比你所想像的要大很多。因為它們的葉子節點包含了它們引用行的主鍵列。

非聚簇索引的訪問需要兩個索引的查詢。

最後的一條可能有些困惑,為什麼非聚簇索引需要兩次索引的查詢?答案就隱藏在非聚簇索引所儲存的「行指標」上。記住乙個葉子節點儲存的指標並不是引用行的實體地址,而是儲存了行的主鍵值。

字首索引兼顧索引大小和查詢速度,但是其缺點是不能用於order by和group by操作,也不能用於covering index(即當索引本身包含查詢所需全部資料時,不再訪問資料檔案本身)。‍

mysql多列索引 MySQL的多列索引

什麼是索引?索引用來快速地尋找那些具有特定值的記錄,所有mysql索引都以b 樹的形式儲存。如果沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜尋條件的列上已經建立了索引,mysql無需掃瞄任何記錄...

MySql多列索引

多列索引 多列索引就是將多個列作為乙個索引,在乙個多列b tree索引中,索引列的順序意味著索引首先按照最左列進行排序,然後第二列第三列等等。所以可以按照公升序或者降序進行掃瞄,以滿足精確符合列順序的order by,group by和distinct等子句,所以,多列索引的順序至關重要,key 列...

mysql多列索引

1,資料庫每次查詢只能使用乙個索引 2,假設資料 表t a,b,c rowid 為物理位置 rowid a b c 1 1 1 1 2 2 1 13 3 2 2 14 4 1 3 3 5 2 3 12 6 1 2 5 7 2 3 9 8 1 2 2 9 1 3 6 10 2 2 11 11 2 2 ...