在上一篇文章介紹過 Clustered Index 和 Non-clustered Index後,接下來我們要依照儲存結構區分索引,這篇文章要介紹 Columnstore 索引,它不同於前一篇文章所介紹的 rowstore index。
Columnstore
Columnstore在建立時,會有以下幾個步驟:
- 先將 Data page 分成幾個 row groups
- 分成 column segment
- 每個 column segment 做壓縮,一種簡單的方法就是用字典替換成 symbol
- 最後儲存在 data page 裡,但這與上一篇文章提到的 Rowstore data page 不同,這個 data page 稱作 LOB page

Lob page (Large object page) 內部特殊之處就是 segment header,會指向在第一步驟切出的 row groups 和 第二步驟切出的 column segment,最重要的是他會指向一個 dictionary page,就是一個用字典把資料替換成 symbol 的 mapping。

Columnstore index 在 OLAP (online analytics processing) 的作業上,也就是資料分析師巨大的 SQL query 上表現得比較好,因為針對單一 column 做聚合的操作,不需要一次取得多個column,這時候一次只取得單一column出來做聚合反而是比較有效率的。
而columnstore也可以分成clustered index 和 non-clustered index,Clustered / Nonclustered 描述的是資料表與 Index 的關係,不是描述實作結構。
B-tree 世界
Clustered Index
= Table 本身重新排序建立索引
Nonclustered Index
= 額外索引
Columnstore 世界
Clustered Columnstore
= Table 本身變成 Columnstore
Nonclustered Columnstore
= Table 保持原樣但是額外建立一份 Columnstore 副本
columnstore的儲存方式不同於btree,他是完全不同的物理結構。clustered columnstore index會直接把原始的rowstore heap table給重組,舊的rowstore heap table將會不復存在,被完全取代。
但是non-clustered columnstore會保持原樣,額外建立一個columnstore副本,而且可以只選擇「column的子集」去建立non-clustered columnstore index。
注意一個特別的規則:一個 table 只能有一個 columnstore representation,也就是說無論你是哪種columnstore index,你總共就只能有一個。而且因為clustered columnstore index會把整張表改造,也不能和clustered rowstore index共存,但可以跟non-clustered rowstore index共存。
| Index 類型 | 允許數量 |
|---|---|
| Clustered Columnstore | 0 或 1 |
| Nonclustered Columnstore | 0 或 1 |
| Columnstore 總數 | 最多 1 |
| sql server會有這個機制存在是避免同時維護多個columnstore index會導致更新成本爆炸,而且優化器也會很難選擇。 |
比較 columnstore index 和 rowstore index:
- storage efficiency: columnstore因為有壓縮,因此在這點表現較好
- read / write performance: 如果把rowstore當作基準,columnstore通常在read上表現較好,但是write方面較慢,因為columnstore process比較冗長
- I/O efficiency: rowstore需要取得所有的columns而columnstore只需要取得特定的columns
- best for: rowstore適合OLTP而columnstore適合OLAP