获取数百万条记录太慢了
Posted
技术标签:
【中文标题】获取数百万条记录太慢了【英文标题】:Fetching Millions Records going too slow 【发布时间】:2018-07-30 10:47:29 【问题描述】:我正在尝试使用带有 Fetching 的聚集索引复制其他表中的 6000 万条记录。但是在 2000 万张唱片之后,它变得太慢了。我不知道我该怎么做。任何人都可以帮助我吗?这是我的计时。
1000000 百万分钟:1 2000000 百万分钟:0 3000000 百万分钟:0 40000 亿分钟:2 5000000 百万分钟:2 6000000 百万分钟:1 7000000 百万分钟:0 8000000 百万分钟:1 9000000 百万分钟:0 10000000 百万分钟:1 11000000 百万分钟:0 12000000 百万分钟:1 13000000 百万分钟:1 14000000 百万分钟:0 15000000 百万分钟:1 16000000 百万分钟:1 17000000 百万分钟:1 18000000 百万分钟:0 19000000 百万分钟:1 20000000 百万分钟:3 21000000 百万分钟:3 22000000 百万分钟:4 23000000 百万分钟:5 24000000 百万分钟:4 25000000 百万分钟:4 26000000 百万分钟:4 27000000 百万分钟:4 28000000 百万分钟:5 29000000 百万分钟:5 30000000 百万分钟:5 31000000 百万分钟:6 32000000 百万分钟:7 33000000 百万分钟:7 34000000 百万分钟:8 35000000 百万分钟:8 36000000 百万分钟:9 37000000 百万分钟:8 38000000 百万分钟:10 39000000 百万分钟:10 40000000 百万分钟:11 41000000 百万分钟:11 42000000 百万分钟:11 43000000 百万分钟:12 44000000 百万分钟:11 45000000 百万分钟:12 46000000 百万分钟:12 47000000 百万分钟:14 48000000 百万分钟:13 49000000 百万分钟:13 50000000 百万分钟:14 51000000 百万分钟:15 52000000 百万分钟:14 53000000 百万分钟:16 54000000 百万分钟:18 55000000 百万分钟:18 56000000 百万分钟:20 57000000 百万分钟:19 58000000 百万分钟:21 59000000 百万分钟:19
declare
@RecNo Int
, @RecCount Int
, @RecordST nvarchar(max)
, @str_date datetime
, @end_date datetime;
Set @RecNo = 0
select @RecCount = 1000000
While 1 = 1
Begin
set @str_date = getdate();
Insert Into dbo.test2(
ap_id
,lipt_id
,li_cntr
)
select
ap_id
,lipt_id
,li_cntr
from dbo.test
order by ap_id, lipt_id, li_cntr
offset @RecNo rows
fetch next @RecCount rows only;
if @@ROWCOUNT = 0
break
Set @RecNo += 1000000;
set @end_date = GETDATE() ;
set @RecordST = cast(@RecNo as nvarchar(max)) + ' Million Min:'+cast(DATEDIFF(MINUTE,@str_date,@end_date) as nvarchar(max))
RAISERROR(@RecordST,0,0) WITH NOWAIT
end
【问题讨论】:
如何在复制之前删除索引,然后在复制之后再次创建它? 由于使用了偏移量,偏移量越高,插入的方法就会越慢。您可能想阅读this old SO answer。如果源表的主键是数字,那么使用该方法的速度将比通过偏移量更一致。OFFSET
和 FETCH
将逐渐变慢,因为每次迭代都必须重新计算偏移量。如果您按聚集索引键的范围而不是行号分页进行批处理,您将获得线性性能。
感谢您的回答。如何按聚集索引键的范围而不是行号分页进行批处理?你能解释一下吗?
TOP(@RecCount) ... WHERE plip_ap_id > @LastValueProcessed ORDER BY plip_ap_id
每次都应该具有相同的性能特征。这要求您的表具有可以从中查找的唯一键。对于复合键,它变得更加烦人。
【参考方案1】:
首先,您需要删除所有约束,例如唯一性、PK 等。这是现有表中每个插入的瓶颈。
其次,如果您向表中插入的记录比现在多得多,那么您可以使用SELECT INTO
语句而不是INSERT
来提高性能。但请记住,SELECT INTO
创建了一个新表,因此您需要考虑如何附加以前存在的记录。
最后但并非最不重要的一点是,您可以使用循环并批量插入 1M 记录。
【讨论】:
我想使用SELECT INTO
语句,但我不知道该语句是否使用Tempdb?因为我的硬盘没有足够的空间来存储 60M 记录。
如果我在插入后定义约束有什么问题吗?
这取决于约束,但在很多情况下您不会遇到问题以上是关于获取数百万条记录太慢了的主要内容,如果未能解决你的问题,请参考以下文章