将100000条记录插入SQL Server的最快方法

时间:2014-09-11 07:03:13

标签: sql sql-server sql-server-2008

我使用以下脚本将100,000条记录插入表中。基本上插入从500,001到600,000的int。我正在将整数转换为字符串并插入coz,这就是我想要它在表中的形式(字符串形式的整数)。我正在使用合并来检查记录是否已存在。

DECLARE @first AS INT
SET @first = 500001
DECLARE @step AS INT
SET @step = 1
DECLARE @last AS INT
SET @last = 600000

BEGIN TRANSACTION
WHILE(@first <= @last)
BEGIN
MERGE dbo.Identifiers As target
USING (SELECT CAST(@first as varchar(10)) AS Identifier) AS source 
    ON (source.Identifier = target.Identifier)
WHEN NOT MATCHED THEN
INSERT (Identifier) 
VALUES (source.Identifier);
SET @first += @step
END
COMMIT TRANSACTION

加载时间超过2分钟。我正在做一些非常错误的事情,但无法追查到哪里。 注意:该表在标识符列上具有唯一的非聚集索引。

4 个答案:

答案 0 :(得分:5)

试试这个。它使用计数表。参考:http://www.sqlservercentral.com/articles/T-SQL/62867/

create table #temp_table(
    N int
)

declare @first as int
set @first = 500001
declare @step as int
set @step = 1
declare @last as int
set @last = 600000

with 
    e1 as(select 1 as N union all select 1),  --2 rows
    e2 as(select 1 as N from e1 as a, e1 as b), --4 rows
    e3 as(select 1 as N from e2 as a, e2 as b), --16 rows
    e4 as(select 1 as N from e3 as a, e3 as b), --256 rows
    e5 as(select 1 as N from e4 as a, e4 as b), --65,356 rows
    e6 as(select 1 as N from e5 as a, e1 as b), -- 131,072 rows
    tally as (select 500000 + (row_number() over(order by N) * @step) as N from e6) -- change 500000 with desired start
insert into #temp_table
select  cast(N as varchar(10))
from tally t
where
    N >= @first
    and N <=@last
    and not exists(
        select 1 from #temp_table where N = t.N
    )

drop table #temp_table

答案 1 :(得分:3)

我想知道您的程序循环和MERGE(而不是简单的INSERT)对糟糕的性能有多大贡献。我会选择这样一个严格基于集合的解决方案:

INSERT INTO dbo.Identifiers (Identifier)
SELECT n FROM dbo.GetNums(500001, 600000)
WHERE n NOT IN (SELECT Identifier FROM dbo.Identifiers);

现在,这依赖于用户定义的表值函数dbo.GetNums,该函数返回一个表,该表包含名为n的列中500,001和600,000之间的所有数字。你是怎么写这个功能的?您需要在其中动态生成一系列数字。

以下实施摘自书籍"Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions" by Itzik Ben-Gak

CREATE FUNCTION dbo.GetNums(@low AS BIGINT, @high AS BIGINT) RETURNS TABLE
AS
    RETURN
    WITH L0   AS (SELECT c FROM (VALUES(1),(1)) AS D(c)),
         L1   AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B), 
         L2   AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
         L3   AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
         L4   AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
         L5   AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
         Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rownum FROM L5)
    SELECT @low + rownum - 1 AS n
    FROM Nums
    ORDER BY rownum
    OFFSET 0 ROWS FETCH FIRST @high - @low + 1 ROWS ONLY;

(由于这是一本关于SQL Server 2012的书,它可能不适用于开箱即用的SQL Server 2008,但它应该可以适应。)

答案 2 :(得分:2)

Vinoth,下面给出的东西也可以帮助你。

Declare @tab table (id int identity(1,1),num int)
Insert  into @tab (num) Values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)

Declare @start as int
set @start = 500000 

Insert into dbo.Identifiers (Identifier) 
Select  @start + ((E.id-1)*10000) +((D.id-1)*1000) +((C.id-1)*100) + ((B.id-1) * 10) + A.id 
from    @tab A,@tab B,@tab C,@tab D,@tab E
Order by @start + ((E.id-1)*10000) +((D.id-1)*1000) +((C.id-1)*100) + ((B.id-1) * 10) + A.id 

在我的数据库中,dbo.Identifiers是一个没有任何索引的表。插入只需230 ms

答案 3 :(得分:0)

在Identifier列上创建索引,然后尝试上面的插入