我有两个桌子。它们都具有相同的结构,除了table2具有附加的列。我目前使用存储的proc将数据从table1复制到table2,如下所示。但是,由于记录数量庞大(超过2000万),并且存储的proc的结构也很复杂,因此目前需要花费几个小时来运行。有没有人对如何优化代码有任何建议?谢谢!
CREATE PROCEDURE dbo.insert_period @period INT AS
DECLARE @batchsize INT
DECLARE @start INT
DECLARE @numberofrows INT
SELECT @numberofrows = COUNT(*) from daily_table
SET @batchsize = 150000
SET @start = 1
WHILE @start < @numberofrows
BEGIN
INSERT INTO dbo.main_table WITH (TABLOCK) (
col1,
col2,
....,
col26,
time_period
)
SELECT *, @period FROM dbo.daily_table
ORDER BY id
OFFSET @start ROWS
FETCH NEXT @batchsize ROWS ONLY
SET @start += @batchsize + 1
END
我在这里使用的ID不是唯一的。该表本身没有任何键或唯一的ID。
首先,我要指出的是,您插入内容中的逻辑有缺陷。
使用@start从1开始,您总是跳过源表的第一行。然后在循环末尾添加1会导致它在循环的每次后续运行中跳过另一行。
如果您打算使用批量插入,我建议您阅读一下如何在MSSQLTips上使用它。
为了帮助您提高性能,建议您查看以下内容:
SELECT *
删除SELECT *
,并替换为列名。这将帮助优化器为您提供更好的查询计划。在此SELECT *
中可以找到有关SO Question为何不好的更多信息。
[ORDER BY
ORDER BY
可能会使您减速。但是,如果没有看到您的查询计划,我们将无法确定。每次循环执行时,它都会查询源表,并且必须对所有这些记录进行排序。对20多次铣削记录进行排序要花费很多时间。请看下面我的简化示例。
CREATE TABLE #Test (Id INT);
INSERT INTO #Test VALUES (1), (2), (3), (4), (5);
DECLARE @batchsize INT;
DECLARE @start INT;
DECLARE @numberofrows INT;
SELECT @numberofrows = COUNT(*) FROM #Test;
SET @batchsize = 2;
SET @start = 0;
WHILE @start < @numberofrows
BEGIN
SELECT
*
, 10
FROM
#Test
ORDER BY
Id OFFSET @start ROWS FETCH NEXT @batchsize ROWS ONLY;
SET @start += @batchsize;
END;
下面是该示例生成的查询计划的一部分。注意,排序操作以黄色突出显示。其费用占该查询计划的78%。
如果添加在源表的ID列上已排序的索引,则可以消除排序。现在,当循环运行时,它无需进行任何排序。
CREATE INDEX ix_Test ON #Test (Id)
其他研究方案
您逐行复制表格,这就是为什么要花这么长时间的原因。实现所需目标的最简单方法是将“ INSERT”与“ SELECT”语句结合使用。这样,您可以批量插入数据。
CREATE TABLE dbo.daily_table (id INT PRIMARY KEY IDENTITY,
value1 NVARCHAR(100) NULL,
value2 NVARCHAR(100) NULL);
GO
CREATE TABLE dbo.main_table (id INT PRIMARY KEY IDENTITY,
value1 NVARCHAR(100) NULL,
value2 NVARCHAR(100) NULL,
value3 NVARCHAR(100) NULL);
GO
INSERT INTO dbo.daily_table (value1, value2)
VALUES('1', '2');
-- Insert with Select
INSERT INTO dbo.main_table (value1, value2)
SELECT value1, value2
FROM dbo.daily_table;
此外,最好不要在'SELECT'语句中使用星号,因为结果可能无法预测。