接上文 SQL Server導入性能對比(1)——並行導入, 這次使用非聚集列存儲索引來測試性能。
環境
首先說明一下這裏使用的還是SQL 2016以上的非聚集列存儲索引,也就是可更新的列存儲索引,在2012的時候已經出現但是是不可更新的。
首先先創建測試表,然後對全部列進行索引化。注意這個時候表實際上是堆表,因爲沒有任何聚集索引在上面。
CREATE TABLE [dbo].[FactOnlineSales_NCCI](
[OnlineSalesKey] [int] NOT NULL,
[StoreKey] [int] NOT NULL,
[ProductKey] [int] NOT NULL,
[PromotionKey] [int] NOT NULL,
[CurrencyKey] [int] NOT NULL,
[CustomerKey] [int] NOT NULL,
INDEX IX_FactOnlineSales_NCCI Nonclustered Columnstore ([OnlineSalesKey],[StoreKey],[ProductKey],[PromotionKey],[CurrencyKey],[CustomerKey])
);
測試
這次我們插入400萬數據,因爲其實太多數據機器頂不住。
set statistics time, io on;
insert into [dbo].[FactOnlineSales_NCCI] WITH (TABLOCK)
(
OnlineSalesKey, StoreKey, ProductKey, PromotionKey, CurrencyKey, CustomerKey
)
select distinct top 4000000 OnlineSalesKey, store.StoreKey, sales.ProductKey, PromotionKey, CurrencyKey, CustomerKey
FROM [dbo].[FactOnlineSales] sales
inner join dbo.DimProduct prod
on sales.ProductKey = prod.ProductKey
inner join dbo.DimStore store
on sales.StoreKey = store.StoreKey
where prod.ProductSubcategoryKey >= 10
and store.StoreManager >= 30
option (recompile);
在我的機器上跑了1分32秒。從執行計劃中可以看到,除了插入數據到堆表(Table Insert)之外,還需要進行非聚集索引的insert,在沒有並行插入的情況下還是開銷很大的。
我們使用下面的命令檢查一下,注意我把數據庫的兼容級別分別改爲130和120的,也就是SQL 2016和SQL 2014,檢查它們的差異。
select *
from sys.column_store_row_groups
where object_schema_name(object_id) + '.' + object_name(object_id) = 'dbo.FactOnlineSales_NCCI'
order by row_group_id asc;
可以看出下面第一個圖是SQL 2014的,有三個行組,並且兩個是Closed一個open,意味着是使用了Delta-Store。
第二個圖也就是下面的圖,是SQL 2016的,是compressed,意味着使用了列存儲索引的特性。
總結
從這個測試看出幾個問題:
- 數據庫結構對性能的影響比較大,上一文即使是1000萬數據而這裏是400萬數據(注意環境是一樣的),時間有明顯的差異。非聚集列存儲索引的堆表插入性能不如聚集列存儲索引使用並行導入的性能。
- 兼容級別是120和130的時候,Delta-Store的使用都不一樣,另外爲了驗證我的想法,我再次提升到140也就是2017,並查看執行計劃,這次只有表更新,沒有列存儲的更新。看上去是越來越好了,而且時間上也快了10幾秒。如果你執行前面的DMV可以看到同樣使用了列存儲即compressed,沒有用到Delta-Store。
- 使用非聚集列存儲索引的堆表,在插入這一步,並沒有使用並行,不管是哪個兼容級別,可以右鍵Table Insert運算符查看屬性裏面的並行,均爲False。
下一文會演示in-memory搭配聚集列存儲索引測試性能。