我有一个大型报告表(大约 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;
首先尝试将索引创建移动到批量插入之后:
这将大大降低 tempdb 压力。
如果 tempdb 仍在爆炸,请尝试以较小的块加载数据。如何对数据进行分区并不重要,但它应该基于现有聚集索引的前导列(唯一与否)。块应该足够小以加载,但又足够大以避免过多的“增量行组”(列存储索引:数据加载指南)。
作为起点,目标是 10-20 个相同大小的块。如果基表是 2 TB,那么这些将是 100-200 GB。向上或向下调整,直到你让它工作。
例如,如果 column1 是日期时间,则尝试按年、季度或月加载。