Медленная вставка SQL на 1 миллион строк - PullRequest
3 голосов
/ 23 марта 2012

С TOP 100000 (100k) этот запрос завершается примерно за 3 секунды

С TOP 1000000 (1 мил), этот запрос будет завершен примерно через 2 минуты

SELECT TOP 1000000
    db_id = IDENTITY(int, 1, 1), *
INTO dbo.tablename
FROM dbname.dbo.tablename

Фактический план выполнения всегда:

clustered index scan 4% cost
top
top
compute scalar
insert (96% cost)
select into

Таблица содержит 1,3 млн строк и имеет первичный ключ int в первом столбце

Могу я как-нибудь ускорить это? Я использую SQL Server 2008 R2.

Ответы [ 2 ]

2 голосов
/ 11 января 2013

Результаты показали, что 100 000 записей занимает 159 мс, а 1 000 000 записей - 1435 мс.В ОС Raid 1, Raid 1 Data, Raid 1 Log, Raid 1 TempDb - все отдельные диски.Наша среда разработки.

Результаты показали, что 100 000 записей занимает 113 мс, а 1 000 000 записей - 996 мс.На моем ноутбуке с одним SSD (Samsung 840 250GB).Рок SSD !!!

Результаты показали, что 100 000 записей занимает 188 мс, а 1 000 000 записей - 1880 мс.В ОС Raid 1, Raid 10 Data, Raid 10 Log, Raid 1 TempDb все отдельные диски находятся под производственной нагрузкой.

1 голос
/ 26 марта 2012

Вот полный скрипт, который показывает, что 1 миллион занимает менее чем в десять раз больше, чем 100 000. Ваша ситуация, вероятно, немного отличается, но это показывает, что основа не в этом.

Результаты показывают, что 100 000 записей занимает 146 мс, а 1 000 000 записей - 1315 мс.

Эти результаты с моего рабочего стола. Если бы кто-то еще мог запустить скрипт и опубликовать свои результаты, это было бы очень полезно.

Rob

USE master;
GO
-- Drop database SourceDB
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'SourceDB') ALTER DATABASE SourceDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'SourceDB') DROP DATABASE  SourceDB;
GO
-- Create database SourceDB
CREATE DATABASE SourceDB; 
ALTER DATABASE SourceDB SET RECOVERY SIMPLE;
GO
USE SourceDB;
GO
-- Create table SourceDB.dbo.SourceTable
CREATE TABLE dbo.SourceTable (
    ColID int PRIMARY KEY
);
GO
-- Populate table SourceDB.dbo.SourceTable
DECLARE @i int = 0;
WHILE @i < 1300000
BEGIN
    SET @i += 1;
    INSERT INTO dbo.SourceTable (ColID) VALUES (@i);
END;
GO
-- Drop database Test1
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'Test1') ALTER DATABASE Test1 SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'Test1') DROP DATABASE  Test1;
GO
-- Create database Test1
CREATE DATABASE Test1;
ALTER DATABASE Test1 SET RECOVERY SIMPLE;
ALTER DATABASE Test1 MODIFY FILE (NAME = Test1, SIZE = 3000MB, MAXSIZE = 8TB);
ALTER DATABASE Test1 MODIFY FILE (NAME = Test1_log, SIZE = 3000MB, MAXSIZE = 2TB);
GO
USE Test1;
GO
IF EXISTS (SELECT * FROM sys.tables WHERE [OBJECT_ID] = OBJECT_ID('dbo.DestinationTable1')) DROP TABLE dbo.DestinationTable1;
IF EXISTS (SELECT * FROM sys.tables WHERE [OBJECT_ID] = OBJECT_ID('dbo.DestinationTable2')) DROP TABLE dbo.DestinationTable2;
GO
DECLARE @n  int       = 100000;
DECLARE @t1 datetime2 = SYSDATETIME();
SELECT TOP (@n) db_id = IDENTITY(int, 1, 1), *
INTO dbo.DestinationTable1
FROM SourceDB.dbo.SourceTable;
SELECT DATEDIFF(ms, @t1, SYSDATETIME()) AS ElapsedMs;
GO
DECLARE @n  int       = 1000000;
DECLARE @t1 datetime2 = SYSDATETIME();
SELECT TOP (@n) db_id = IDENTITY(int, 1, 1), *
INTO dbo.DestinationTable2
FROM SourceDB.dbo.SourceTable;
SELECT DATEDIFF(ms, @t1, SYSDATETIME()) AS ElapsedMs;
GO
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...