2014-09-11 112 views
2

我正在使用以下腳本將100,000條記錄插入到表中。基本上int從500,001到600,000被插入。我將整型轉換爲一個字符串,然後在表格中以字符串的形式插入一個整數。我正在使用合併來檢查記錄是否已經存在。將100000條記錄插入SQL Server的最快方法

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分鐘以上的加載。我正在做一些非常錯誤的事情,但無法追查到哪裏。 注意:該表在標識符列上具有唯一的非聚簇索引。

+2

「加載時間超過2分鐘」 - 您爲什麼認爲這太多?我們不知道您的硬件設置。 – 2014-09-11 07:05:35

+0

它是我們應用程序中加載過程的一部分。我讀了數百萬條記錄的快速插入,這是10萬條記錄。我假設我做了一些錯誤的事情,所以想澄清一下。 i7處理器與8 GB的RAM 64位操作系統是我的系統配置 – Vinoth 2014-09-11 07:10:16

回答

3

我想知道有多少你的程序循環和MERGE(而不是一個簡單的INSERT)有助於性能不良。我會選擇一個嚴格的基於集合的解決方案是這樣的:

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

現在,這依賴於返回包含在列500,001和600,000的所有數字的表稱爲n用戶定義的表值函數dbo.GetNums 。你怎麼寫這個功能?您需要在其中動態生成一系列數字。

以下實施摘自"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上工作外的開箱,但它應該是可以適應的。)

+0

這對我很好!我正在使用2012年 – Vinoth 2014-09-11 08:41:19

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 <[email protected] 
    and not exists(
     select 1 from #temp_table where N = t.N 
    ) 

drop table #temp_table 
+0

真棒..它只需要一秒鐘加載整個100,000條記錄!謝謝,謝謝 – Vinoth 2014-09-11 07:37:58

+0

很高興我能幫上忙。 – 2014-09-11 07:43:21

+0

儘管這個解決方案第一次工作得很好,但是當我運行腳本第二次時,這是一個合併,它花費了4分多鐘(不知道需要多長時間,因爲我在第4分鐘停止了) – Vinoth 2014-09-11 08:40:35

0

在標識符列創建索引,然後嘗試上面插入

+0

我不能那樣做。它已經有一些記錄 – Vinoth 2014-09-11 07:38:24

+0

那麼在創建索引時有什麼問題? – Yogesh86 2014-09-11 07:41:14

+0

我的意思是,表已經創建了索引。 – Vinoth 2014-09-11 08:22:28

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

相關問題