Есть ли способ оптимизировать миграцию данных с Oracle на SQL Server и сократить затрачиваемое время? - PullRequest
0 голосов
/ 05 февраля 2019

Я выполняю миграцию данных из базы данных Oracle (без возможности подключения 12c) на сервер SQL (2012) с использованием сценариев T-SQL в SSMS с базой данных Oracle, настроенной как связанный сервер.Схемы уже синхронизированы, поэтому остается только данные.Проблемы, с которыми я сталкиваюсь, связаны со временем, которое занимает миграция, и объемом используемой памяти.

При запуске моего сценария это занимает очень много времени, и первоначально я столкнулся с проблемами памяти на сервере SQL Server, когдаМиграция полных таблиц, поэтому я решил разбить миграцию таблиц на куски по 1 000 000 строк за раз.Однако, похоже, что в моем коде «утечка памяти», так как память, потребляемая запросом, увеличивается с каждой итерацией, а запрос занимает очень много времени.

РЕДАКТИРОВАТЬ: я отбросилиндексы в базе данных MS SQL Server.

Мой сценарий работает, но при переносе больших таблиц запрос закрывается в доступной памяти, и миграция занимает около 5 минут на 1 строку строк в начале(и медленно увеличивается с каждой итерацией).Конечно, время зависит от количества строк в таблице и т. Д.

Статистика данных: * Таблицы: ~ 1600 * Всего строк: ~ 1 Билл.(Самая большая таблица - 300 млн. Строк)

USE INFODBA
GO

SET NOCOUNT ON

DECLARE @start BIGINT
DECLARE @end BIGINT
DECLARE @maxrows BIGINT
DECLARE @step BIGINT
DECLARE @sqlstr NVARCHAR(4000)
DECLARE @table_name VARCHAR(255)
DECLARE @counter INT
DECLARE @time TIME
DECLARE @error NVARCHAR(4000)

-- Iterates in @step rows at a time
SET @step = 1000000;
SET @start = 0;
SET @end = @start + @step;
SET @counter = 1;

SET @table_name = 'sourceTable'
PRINT @table_name;

-- GET exact rowcount of Oracle table
SELECT @maxrows = NUM_ROWS FROM OPENQUERY(ORACLETC, 'SELECT COUNT(*) AS NUM_ROWS FROM sourceTable')

WHILE @start < @maxrows
BEGIN
    SELECT @time = CONVERT (time, CURRENT_TIMESTAMP)

    SET @sqlstr = 'INSERT INTO targetTable SELECT * FROM OPENQUERY(ORACLETC,''SELECT COL1,COL2,COL3,COL4 FROM sourceTable'
    SET @sqlstr = @sqlstr + ' OFFSET ' + CAST(@start AS NVARCHAR(255)) + ' ROWS FETCH NEXT ' + CAST(@step AS NVARCHAR(255)) + ' ROWS ONLY'') AS ROWSET_1';

    -- Print output immediatly to capture progress
    PRINT 'Iteration;' + CAST(@counter AS VARCHAR(255)) + ';Time;' + CAST(@time AS VARCHAR(255)) + ';Start;' + CAST(@start AS VARCHAR(255)) + ';End;' + CAST(@end AS VARCHAR(255)) + ';MAX;' + CAST(@maxrows AS VARCHAR(255)) + ';Query;' + @sqlstr
    RAISERROR (N'', 0, 1) WITH NOWAIT

    -- Start the migration query and catch error messages
    BEGIN TRY
        BEGIN TRANSACTION;
            EXEC dbo.sp_executesql @sqlstr
        COMMIT;
    END TRY
    BEGIN CATCH
        SELECT @error = ERROR_MESSAGE();
        PRINT 'ERROR on iteration: ' + CAST(@counter AS VARCHAR(255)) + ' with query: ' + @sqlstr + ' - Error: ' + @error
        SELECT ERROR_MESSAGE() AS ErrorMessage;
        RETURN
    END CATCH

    SET @counter += 1
    SET @start = @end
    SET @end += @step
END

Этот сценарий перенесет данные в виде наборов по 1 млн. Строк, но теперь кажется, что запрос оракула занимает больше всего времени (около 80%)в соответствии с планом выполнения.Кроме того, хотя я пытаюсь использовать «начальную транзакцию» и «фиксацию» (возможно, есть лучший способ ее использования), сценарий, как уже упоминалось, увеличивает объем памяти для каждой итерации (большая часть памяти освобождается насовершать, но в фоновом режиме медленно увеличивается)

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Влад ответ правильный;Ваш текущий запрос включает в себя динамический SQL, цикл WHILE и OPENQUERY, которые часто являются скачками производительности.Использование массовой загрузки (т. Е. BCP) или пакета служб SSIS для импорта плоских файлов должно дать вам гораздо лучшие результаты.

0 голосов
/ 05 февраля 2019

Существует несколько подходов.

  1. Удалите индексы в таблице SQL Server, в которую вы импортируете данные, и создайте их снова после импорта.

  2. Отдельный экспорт, передача и загрузка.Это означает извлечение данных на сервере Oracle в текстовые файлы, затем передачу их на компьютер SQL Server по ftp, а затем загрузку их на SQL Server.

  3. (наиболее эффективный способ) Использование MS SQL ServerМассовая загрузка: https://docs.microsoft.com/en-us/sql/relational-databases/import-export/bulk-import-and-export-of-data-sql-server?view=sql-server-2017 В этом случае ваш 1м записей не будет обрабатываться всей базой данных, а будет записываться непосредственно в файлы базы данных, это намного быстрее.

...