叢集索引一張表只有一個,非叢集索引是另一份帶 pointer 的結構
| 叢集索引(clustered) | 非叢集索引(non-clustered) | |
|---|---|---|
| 數量 | 每張表只有一個(unique index) | 可以有多個 |
| 通常是誰 | 該表的 primary key | 其他欄位或多欄位組合 |
| 內容 | — | 索引的組成欄位 + 一個指向原始資料的 pointer |
非叢集索引本身就是「多個欄位組合成的一份資料結構」,它不存整列資料,只存索引欄位和一個「回去拿資料」的憑據——所以用它查完之後,還要再走一趟把原始資料撈回來,也就是 全表掃描和索引掃描的適用場景是相反的 裡索引掃描的第二步。
「pointer」這個說法要分資料庫
上表說的 pointer 對 PostgreSQL 成立,對 MySQL 不成立:
- PostgreSQL:索引存的是 CTID(物理位置),確實是指標,二級索引直接指向 Heap
- MySQL (InnoDB):二級索引存的是主鍵值,不是位址——所以要先回主鍵索引再走一次,這叫回表
兩邊的差別與後果見 加上二級索引之後,主鍵查詢的快慢反過來;為什麼 InnoDB 能這樣放見 MySQL 把資料放在主鍵索引的葉子,PostgreSQL 放在獨立的 Heap。
索引為什麼用 B+ tree 見 B-tree 靠一個節點放多個鍵把樹壓矮,換到更少的讀取次數。