上一篇文章介紹過 Clustered Index 和 Non-clustered Index後,接下來我們要依照儲存結構區分索引,這篇文章要介紹 Columnstore 索引,它不同於前一篇文章所介紹的 rowstore index。

Columnstore

Columnstore在建立時,會有以下幾個步驟:

  1. 先將 Data page 分成幾個 row groups
  2. 分成 column segment
  3. 每個 column segment 做壓縮,一種簡單的方法就是用字典替換成 symbol
  4. 最後儲存在 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 Columnstore0 或 1
Nonclustered Columnstore0 或 1
Columnstore 總數最多 1
sql server會有這個機制存在是避免同時維護多個columnstore index會導致更新成本爆炸,而且優化器也會很難選擇。

比較 columnstore index 和 rowstore index:

  1. storage efficiency: columnstore因為有壓縮,因此在這點表現較好
  2. read / write performance: 如果把rowstore當作基準,columnstore通常在read上表現較好,但是write方面較慢,因為columnstore process比較冗長
  3. I/O efficiency: rowstore需要取得所有的columns而columnstore只需要取得特定的columns
  4. best for: rowstore適合OLTP而columnstore適合OLAP