экспорт таблицы, содержащей большое количество записей, в другую базу данных на связанном сервере

61
8

У меня есть задача в проекте, которая требует результатов процесса, который может быть от 1000 до 10 000 000 записей (приблизительный верхний предел), который должен быть вставлен в таблицу с той же структурой в другой базе данных на связанном сервере. Требование состоит в том, чтобы иметь возможность передавать куски, чтобы избежать любых тайм-аутов

При проведении некоторых тестов я настроил связанный сервер и использовал следующий код для проверки переданных приблизительно 18000 записей:

DECLARE @BatchSize INT = 1000

WHILE 1 = 1
BEGIN

INSERT INTO [LINKEDSERVERNAME].[DBNAME2].[dbo].[TABLENAME2] WITH (TABLOCK)
(
id
,title
,Initials
,[Last Name]
,[Address1]
)
SELECT TOP(@BatchSize)
s.id
,s.title
,s.Initials
,s.[Last Name]
,s.[Address1]
FROM [DBNAME1].[dbo].[TABLENAME1] s
WHERE NOT EXISTS (
SELECT 1
FROM [LINKEDSERVERNAME].[DBNAME2].[dbo].[TABLENAME2]
WHERE id = s.id
)

IF @@ROWCOUNT < @BatchSize BREAK

Это работает отлично, однако для передачи данных потребовалось 5 минут.

Я хотел бы реализовать это, используя SSIS, и я ищу любые советы, как это сделать и ускорить процесс.

спросил(а) 2021-01-19T20:52:46+03:00 1 месяц, 1 неделя назад
1
Решение
62

Откройте Visual Studio/Business Intelligence Designer Studio (BIDS)/Инструменты данных SQL Server - выпуск BI (SSDT)

На вкладке "Шаблоны" выберите "Бизнес-аналитика", "Проект служб интеграции". Дайте ему действительное имя и нажмите "ОК".

В Package.dtsx, который будет открыт по умолчанию, в разделе "Менеджеры подключений" щелкните правой кнопкой мыши "Новое подключение OLE DB". В разделе "Настройка диспетчера подключений OLE DB" нажмите "Создать...", а затем выберите свой сервер и базу данных для ваших исходных данных. Нажмите "ОК", "ОК".

Повторите описанный выше процесс, но используйте его для целевого сервера (связанного сервера).

Переименуйте указанные выше диспетчеры соединений с server\instance.databasename в нечто лучшее. Если databasename не изменяется во всех средах, просто используйте имя базы данных. В противном случае перейдите к общему имени. т.е. если SLSDEVDBSLSTESTDBSLSPRODDB при миграции через ваши среды, сделайте это SLSDB. В противном случае вы в конечном итоге с людьми, говорящими о диспетчере соединений, чье имя "база данных разработчиков", но оно фактически указывает на производство.

Добавьте поток данных в свой пакет. Назовите это чем-то полезным, кроме задачи потока данных. DFT Load Table2 будет моим предпочтением, но ваш пробег может отличаться.

Дважды щелкните задачу потока данных. Здесь вы добавите источник OLE DB, задачу поиска и назначение OLE DB. Наверное, как всегда, это будет зависеть.

OLE DB Source - используйте первый менеджер соединений, который мы определили, и запрос

SELECT 
s.id
,s.title
,s.Initials
,s.[Last Name]
,s.[Address1]
FROM [dbo].[TABLENAME1] s

Выбирайте только нужные столбцы. В вашем текущем ответе отбираются любые дубликаты, которые уже существуют в пункте назначения. Это может быть сложной задачей. Вместо этого мы передадим все TABLENAME1 в конвейер и отфильтровываем то, что нам не нужно. Для очень больших томов в исходной таблице это может быть несостоятельным подходом, и нам нужно будет сделать что-то другое.

Из источника нам нужно использовать преобразование Lookup. Это позволит нам обнаружить дубликаты. Используйте второй менеджер соединений, который мы определили, тот, который указывает на пункт назначения. Измените NoMatch с "Fail Component" на "Redirect Unmatched rows" (имя приблизительное)

Используйте свой запрос, чтобы отменить значение ключа (ов)

SELECT T2.id
FROM [dbo].[TABLENAME2] AS T2;

Карта T2.id в столбец id.

Когда пакет запускается, он выдаст вышеупомянутый запрос в целевой таблице и кэширует все значения T2.id в память. Поскольку это только один столбец, это не должно быть слишком дорого, но опять же, для очень больших таблиц этот подход может не работать.

Теперь доступны 3 выхода из поиска: Match, NoMatch и Error. Match будет любым, что существует в источнике и получателе. Вас это не волнует, поскольку вас интересует только то, что существует в источнике, а не в назначении. Когда вам будет интересно, вам нужно определить, есть ли изменения между значениями в источнике и получателем. NoMatch - это строки, которые существуют в Source, но не существуют в Destination. Это поток, который вы хотите. Для полноты, Error захватила бы вещи, которые пошли очень неправильно, но я не испытывал это "в дикой природе" с поиском.

Подключите поток NoMatch к назначению OLE DB. Выберите там свое имя таблицы и убедитесь, что слова Fast Load находятся в пункте назначения. Перейдите на вкладку "Столбцы" и убедитесь, что все маршрутизировано.

Нужно ли вам возиться с кнопками в OLE DB Destination очень сильно. Я бы проверил его, особенно с вашими большими наборами данных и посмотрел, являются ли условия тайм-аута фактором.

Конструктивные соображения для больших наборов

Это зависит.

Действительно, это так. Но я бы посмотрел, где находится точка боли.

Если моя исходная таблица очень большая и вытягивает все эти данные в конвейер только для того, чтобы отфильтровать ее обратно, я бы посмотрел на что-то вроде потока данных, чтобы сначала привести все строки в моем поиске в исходную базу данных (используйте T2) и записать его в промежуточную таблицу и сделать один столбец кластеризованным ключом. Затем измените исходный запрос для ссылки на свою промежуточную таблицу.

В зависимости от того, насколько активна таблица назначения (независимо от того, может ли любой другой процесс ее загрузить), я мог бы следить за этим потоком данных, чтобы убедиться, что я не загружаю дубликаты. Если этот процесс является единственным, который загружает его, то откройте "Поиск".

Если поиск ошибочен - он не может вытащить все идентификаторы, либо перейдите с первым альтернативом, указанным выше, либо посмотрите, как изменить режим кэширования с полного на частичный. Поймите, что это вызовет запрос к целевой системе для потенциально всех строк, выходящих из исходной базы данных.

Если пункт назначения задает вопросы - я бы определил, в чем проблема. Если это латентность сети для загрузки данных, отмените значение MaximumCommitInsertSize с 2147483647 на что-то разумное, например, размер вашей партии сверху (хотя 1k может быть немного низким). Если вы все еще сталкиваетесь с блокировкой, то, возможно, организовать данные в другую таблицу на удаленном сервере, а затем сделать локальную вставку может быть подход.

ответил(а) 2021-01-19T20:52:46+03:00 1 месяц, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема