SQL Server 2005 загрузка данных с внешнего сервера - PullRequest
0 голосов
/ 12 сентября 2009

Новый проект со следующими настройками и требованиями: -

Мой клиент имеет сервер MSSQL 2005 (A) в своем офисе. У их поставщика есть сервер MSSQL 2005 (B) в другой части мира, который содержит транзакционные данные в реальном времени. Мой клиент хочет загружать данные из (B) в (A) ежедневно в нерабочее время. У них есть доступ к хранилищу данных (B), но это все, поставщик не будет выполнять репликацию, доставку журналов и т. Д., И мой клиент несет полную ответственность за получение собственных данных, чтобы они могли запускать свои собственные отчеты / кубы.

Сценарий, который я использовал, использует распределенный TSQL и связанный сервер с (B): -

DECLARE @sqlCommand        VARCHAR(2000)
DECLARE @LastProcessedDate DATETIME

-- run the following code for Table 1 to Table XX

SELECT @LastProcessedDate = LastProcessedDate 
  FROM [ProcessControl] 
 WHERE TableName = 'table_1'

SET @sqlCommand = 'INSERT INTO Table1 
                   SELECT * 
                     FROM OPENQUERY(VendorsLinkedServerName, 
                          ''SELECT * 
                              FROM Table1 
                             WHERE LastModified >= '''' + @LastProcessedDate + '''')'

EXEC @sqlCommand

Я провел первоначальную пробную версию для 10 самых больших таблиц за 1 полный день данных, и это заняло 1 час, что слишком долго. Также для теста я уже удалил все индексы и ограничения, кроме первичного ключа (который содержит 1-4 столбца BIGINT) для таблиц. Любые предложения о том, как я могу ускорить время загрузки или загрузить данные?

edit: просто добавить, если вам интересно, почему оператор select был написан таким образом, в приведенном выше примере таблица 1 в (A) находится в базе данных ETL, и впоследствии данные будут сравниваться для определения вставки / обновления / удаления в базе данных фактических отчетов в (A)

Ответы [ 5 ]

1 голос
/ 13 сентября 2009

Звучит так, будто вы ищете одностороннюю (только для загрузки) синхронизацию. Для большей надежности я бы попросил продавца (B) добавить столбец ROWVERSION, он немного безопаснее, чем DateTime или DateTimeOffset.

Что касается вашего запроса, я сделал что-то вроде следующего:

INSERT INTO dbo.Table1
(
    Field1,
    Field2,
    Field3
)
SELECT
    T1.Field1,
    T1.Field2,
    T1.Field3
FROM [LinkedServer].[DatabaseName].[dbo].[Table1] T1
WHERE T1.Version > @LastAnchor

Вы можете пропустить всю фазу ETL, если ваши схемы одинаковы, используя CreatedVersion и UpdatedVersion со строками Tombstone для удалений, если это необходимо. Sync Framework многое упрощает для вас, хотя вы можете использовать концепции, чтобы испечь свои собственные относительно легко. Правила следующие:

-- get inserts in dependency order
INSERT INTO ...
SELECT ...
FROM ...
WHERE CreatedVersion > @LastAnchor
-- get updates in dependency order
UPDATE [dbo].[Table1]
SET ...
FROM [LinkedServer].[DatabaseName].[dbo].[Table1] T1
WHERE [dbo].[Table1].[PK] = T1.[PK]
    AND T1.CreatedVersion <= @LastAnchor
    AND T1.UpdatedVersion > @LastAnchor
-- get deletes (if you need them)
DELETE T
FROM [dbo].[Table1] T
JOIN [LinkedServer].[DatabaseName].[dbo].[Table1_Tombstone] T1
    ON T.[PK] = T1.[PK]
    AND T1.DeletedVersion > @LastAnchor

Чтобы все эти запросы работали хорошо, столбцы CreatedVersion, updatedVersion и DeletedVersion должны быть проиндексированы.

Вся вышеуказанная логика работает для DateTime или RowVersion, просто RowVersion является более точным, и есть некоторые проблемы, которые SP2 2005 решает в отношении текущих транзакций. В основном, в SQL 2005 с пакетом обновления 2 и SQL 2008 вы устанавливаете максимальную привязку на MIN_ ACTIVE_ROWVERSION () - 1 и запрашивает промежуточные данные. Посмотрите MSDN заметки для получения дополнительной информации о том, почему.

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

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

1 голос
/ 12 сентября 2009

К сожалению, я полагаю, что самое большое замедление - просто задержка в сети, и вы ничего не можете с этим поделать.

Хотя у меня есть одна идея. Попробуйте добавить предложение ORDER BY в инструкцию SELECT, которая соответствует первичному ключу (кластеризованному индексу) целевой таблицы. Это может сократить необходимость повторного заказа таблицы во время вставок.

Кроме того, сколько там таблиц и сколько у вас времени? Если вы сделали 10 наибольших за час, вы можете обнаружить, что в игре есть правило 90/10, такое, что все остальные столы вместе занимают меньше времени, чем эти 10.

0 голосов
/ 12 сентября 2009

Попробуйте выполнить запрос локально (или попросите его выполнить запрос локально) и посмотрите, сколько времени это займет. Как указал Крис, это может быть задержка в сети. У вас есть возможность развернуть пакет служб SSIS на стороне поставщика? Если это так, вы можете извлечь и сжать данные, отправить их через задачу FTP или другой механизм, и распаковать / вставить данные на конце.

0 голосов
/ 12 сентября 2009

Возможно, вы захотите провести несколько тестов, чтобы определить, где происходит замедление, как предлагает Крис В.

Например, сделайте запрос и дамп информации в файл, и время его.

Время просто выполнить запрос и игнорировать любые данные, которые вы получаете, чтобы увидеть, сколько времени требуется для передачи данных.

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

Тогда вы сможете определить лучший курс действий.

Вы также можете выполнить множество отдельных запросов.

Итак, сколько времени занимает перевод с одного большого стола.

Затем выполните 5 запросов больших таблиц и посмотрите, что произойдет.

Если возможно, возможно, вы захотите узнать, можете ли вы сделать несколько одновременных подключений и быстро обработать данные, сбросить их в пустую базу данных, а затем заплатить цену за индексы, скопировав их из локальной копии в базу данных. 1017 *

Но, все это бессмысленно, пока у вас нет цифр, чтобы увидеть, сколько времени занимает операция.

0 голосов
/ 12 сентября 2009

Производительность связана с задержкой в ​​сети, а не с подходом, который вы используете? С какими объемами вы имеете дело и т. Д.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...