我使用以下脚本将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分钟。我正在做一些非常错误的事情,但无法追查到哪里。 注意:该表在标识符列上具有唯一的非聚集索引。
答案 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列上创建索引,然后尝试上面的插入