2014-09-11 2 views
2

Я использую следующий скрипт для вставки 100 000 записей в таблицу. В основном int от 500001 до 600 000. Я вставляю целое число в строку и вставляя coz, как я хочу его в таблице (целое число в виде строки). Я использую слияние, чтобы проверить, существует ли запись или нет.Самый быстрый способ вставить 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

«ts занимает более 2 минут для загрузки» - и почему вы думаете, что это слишком много? Мы не знаем настройки вашего оборудования. –

+0

Его часть процесса загрузки в нашем приложении. Я читал о молниеносных вставках миллионов записей, и это 100 000 записей. Я предполагаю, что я делаю что-то неправильно, поэтому хочу пояснить это. i7 Процессор с 8 ГБ RAM 64-разрядной ОС - это моя системная конфигурация – Vinoth

ответ

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 табличных, которая возвращает таблицу, содержащую все числа между 500,001 и 600,000 в колонке под названием n , Как вы пишете эту функцию? Вам нужно создать ряд чисел «на лету» внутри него.

Следующая реализация взята из книги "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

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

Awesome .. Для загрузки всего 100 000 записей потребовалось всего одну секунду !!! Спасибо тонну – Vinoth

+0

Рад, что я мог бы помочь. –

+0

Хотя решение работало отлично в первый раз, это было слияние, когда я запустил скрипт, второй раз он занимает больше 4 минут (не знаю, сколько времени потребуется, когда я остановился на 4-й минуте) – Vinoth

0

Создать индекс на столбце Идентификатор, а затем попытаться вышеуказанную вставку

+0

Я не могу этого сделать. У него уже есть записи в нем – Vinoth

+0

, так что же проблема в создании индекса ?? – Yogesh86

+0

Я имел в виду, что таблица уже была создана с индексом. – Vinoth

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.

Смежные вопросы