Sql-Server

嘗試將大表轉換為列儲存時 Azure tempdb 填滿…如何緩解?

  • July 15, 2020

我有一個大型報告表(大約 6B 行),在 azure sql db 上佔用了大約 400GB 的儲存空間。我一直在嘗試使用以下命令將其轉換為列儲存表:

insert Logs(Message) values ('Creating SRR table...');
select top 0 * into temp.SRR from dbo.SRR (nolock);
create clustered columnstore index ix_SRR on temp.SRR with (online = off);
create index ix_SRR_JobId on temp.SRR (JobId);
insert Logs(Message) values('Populating SRR table...');
insert into temp.SRR with (tablock) select * from dbo.SRR (nolock);
insert Logs(Message) values ('Switching out SRR table...');
alter schema old transfer dbo.SRR;
alter schema dbo transfer temp.SRR;
insert Logs(Message) values ('SRR table converted.');
if (select count_big(*) from old.SRR (nolock)) = (select count_big(*) from dbo.SRR (nolock)) begin
   drop table old.SRR;
   insert Logs(Message) values('Deleted old SRR table.');
end else begin
   insert Logs(Message) values('Row counts between old.SRR and dbo.SRR do not match; retaining old.SRR.');
end

這對我們所有其他大型報告表都有效,但是這個(經過 30 小時的 DTU 時間)始終失敗並顯示以下消息:

Msg 40544, Level 17, State 2, Line 195
The database 'tempdb' has reached its size quota. Partition or delete data, drop indexes, or consult the documentation for possible resolutions.

我能做些什麼來完成這項工作?

批量插入 CLUSTERED COLUMNSTORE 索引本身不應該炸毀 tempdb。行被讀取並以 100 萬個塊的形式放入壓縮行組中,沒有理由長期使用 tempdb。

我認為問題在於 temp.SRR (JobId) 上的非聚集索引 ix_SRR_JobId;

首先嘗試將索引創建移動到批量插入之後:

insert Logs(Message) values('Populating SRR table...');
insert into temp.SRR with (tablock) select * from dbo.SRR (nolock);
create index ix_SRR_JobId on temp.SRR (JobId) WITH (SORT_IN_TEMPDB = OFF);

這將大大降低 tempdb 壓力。

如果 tempdb 仍在爆炸,請嘗試以較小的塊載入數據。如何對數據進行分區並不重要,但它應該基於現有聚集索引的前導列(唯一與否)。塊應該足夠小以載入,但又足夠大以避免過多的“增量行組”(列儲存索引:數據載入指南)。

作為起點,目標是 10-20 個相同大小的塊。如果基表是 2 TB,那麼這些將是 100-200 GB。向上或向下調整,直到你讓它工作。

例如,如果 column1 是日期時間,則嘗試按年、季度或月載入。

引用自:https://dba.stackexchange.com/questions/270986