Каков самый быстрый способ копирования данных из таблицы DataWindow/DataStore в таблицу SQL Server с помощью Powerbuilder

У нас есть хранилище данных (сестра-близнец powerbuilder datawindow), которое содержит более 40 000 строк, вставка которых в занимает более 30 минут. Таблица Microsoft SQL Server.

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

Я уже обнаружил, что процесс создания скрипта занимает более 97% всей задачи.

Не могли бы вы помочь мне найти более эффективный способ копирования данных моего клиента в таблицу сервера sql?

Edit1 (после комментариев NoazDad):

Прежде чем ответить, пожалуйста, имейте в виду, что:

  • Структура таблицы динамическая;
  • Я пытаюсь избежать использования метода datastore.Update();

person Julio Nobre    schedule 10.07.2014    source источник
comment
Собственные операторы обработки строки PB (mid(), pos(), конкатенация,...) выполняются медленно. Это может объяснить, что генерация сценария занимает 97% всего процесса. Вы можете использовать профилировщик, чтобы получить идеи по оптимизации.   -  person Seki    schedule 14.07.2014
comment
Да, ты прав. Обработка строки PB действительно очень медленная. Спасибо за ваш комментарий.   -  person Julio Nobre    schedule 14.07.2014


Ответы (4)


Не уверен, что это будет быстрее, но вы можете сохранить данные из хранилища данных в файле с разделителями табуляции, а затем выполнить BULK INSERT через Sql. Что-то вроде

МАССОВАЯ ВСТАВКА CSVTest FROM 'c:\csvtest.txt' WITH (FIELDTERMINATOR = '\t', ROWTERMINATOR = '\n') GO

Вы можете попробовать сохранить содержимое хранилища данных в строковую переменную с помощью синтаксиса ds.object.datawindow.data, затем сохранить его в файл и выполнить SQL.

person Matt Balent    schedule 11.07.2014
comment
Да, именно такой подход я и ищу. Однако мне интересно, соответствуют ли его ограничения моим сценариям использования. Я дам ему попробовать. Большое спасибо! - person Julio Nobre; 11.07.2014
comment
это было бы самым быстрым на сегодняшний день, в противном случае вы можете использовать объект конвейера и установить коэффициент фиксации на 1000 или 5000 строк, чтобы вы не выполняли коммиты при каждом обновлении (если данные позволяют это). Но вставка 40 КБ из окна данных будет болезненной, если у вас нет системы, которая живет на одном сервере без сетевых задержек. У Мэтта правильная идея: сохранить файл, а затем создать на сервере процесс, выполняющий массовую загрузку. - person Rich Bianco; 12.07.2014
comment
Просто чтобы добавить мои две монеты, мы делаем именно это с различными системами, в файлах csv, содержащих до нескольких миллионов строк. - person vittore; 15.07.2014

Как я это прочитал, вы говорите, что таблица, в которую вставляются данные, даже не существует в схеме, пока пользователь не нажмет «GO» и не запустит скрипт? А затем вы создаете встроенные операторы SQL, которые создают таблицу и вставляют строки 1 за 1 в цикле?

Это... Ну, скажем так, я бы так не поступил.

Вы заранее не представляете, как будет выглядеть схема? Если вы это сделаете, нарисуйте хранилище данных для этой таблицы и используйте ds_1.Update() для создания операторов INSERT. Используйте окно данных для того, для чего оно полезно.

Если это невозможно, и вы должны использовать встроенный SQL, то, по крайней мере, выполняйте COMMIT каждые 1000 строк или около того. В противном случае SQLServer создает журналы UNDO для таблицы на случай, если что-то пойдет не так, и их придется откатить.

person NoazDad    schedule 10.07.2014
comment
Привет, НоазДад! Большое спасибо за ваши комментарии. Я забыл упомянуть, что ищу решение помимо метода ds.Update(). Я пересмотрю свой ответ. - person Julio Nobre; 11.07.2014

Другие идеи...

  • Отключить триггеры в обновленной таблице, пока она обновляется (если возможно)
  • Используйте объект PB Pipeline, у него есть настройки для фиксации — может быть быстрее, но ненамного.
  • Лучшая идея. Сделайте что-нибудь на стороне сервера. Я бы попытался создать операторы SQL для ваших вставок 40 КБ и вызвать хранимую процедуру, отправляющую все операторы вставки/обновления 40 КБ, и позволить хранимой процедуре обрабатывать вставки/обновления.
  • Создайте фиктивную таблицу с несколькими столбцами, один из которых представляет собой длинный текст, обновите ее блоком операторов SQL, как указано в последней идее, и создайте процесс, который разграничивает и выполняет операторы sql.
  • Некоторый вариант выше, но с использованием объемной вставки, как упомянуто Мэттом. Массовая вставка — это самый быстрый способ вставки большого количества строк.
  • Может быть, попробуйте что-нибудь с автоматической фиксацией, чтобы вы фиксировали только в конце или каждые 10 000 строк, как уже упоминалось кем-то.
  • PB имеет асинхронную опцию в объекте транзакции (соединение), возможно, вы могли бы позволить обновлению идти в фоновом режиме и позволить пользователю продолжить. Это работает не со всеми базами данных и может не работать в вашей ситуации. Мне не повезло с асинхронным вариантом.

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

Расширяя идею отправки операторов SQL в процедуру, вы можете очень легко создать sql, выполнив dw_1.saveas( SQL!) (синтаксис неверен) и сразу отправив его на сервер. Пусть сервер проанализирует его и запустит SQL.

Отправьте что-то подобное на сервер через процедуру, она должна обновляться довольно быстро, так как это всего лишь одно выражение:

Update TABLE set (col1, col2) values ('a', 'b')|Update TABLE set (col1, col2) values ('a', 'b')|Update TABLE set (col1, col2) values ('a', 'b')

В процедуре:

Разберите операторы sql и запустите их. Очень просто.

person Rich Bianco    schedule 15.07.2014
comment
Большое спасибо за ваши комментарии. Я действительно нацелен на что-то на основе массовой вставки или на основе XML-окна данных, поскольку генерация строки скрипта вставки потребляет большую часть выполнения. - person Julio Nobre; 19.07.2014

Хотя ответ Мэтта, вероятно, лучший, у меня есть другой вариант. (Варианты хороши, верно?)

Я не уверен, почему вы избегаете метода datastore.Update(). Я предполагаю, что это потому, что схема не существует во время обновления. Если это единственная причина, его все еще можно использовать, что устраняет 40 000 случаев манипулирования строками для создания действительного SQL.

Для этого вы должны сначала создать таблицу. Затем вы должны использовать datastore.SyntaxFromSQL() для создания хранилища данных, привязанного к таблице. Чтобы сделать хранилище данных доступным для обновления, может потребоваться несколько операторов Modify(). Затем вы переместите данные из исходного хранилища данных в привязанное хранилище данных с возможностью обновления. (Посмотрите на RowsMove() или запись через точку.) После этого оператор Update() генерирует весь ваш SQL без накладных расходов на синтаксический анализ строки и зацикливание.

person Jason    schedule 31.07.2014
comment
Хотя ваше предложение действительно является ценным решением, я искал передовое решение Edge, которое предоставил Мэтт. В любом случае, поставил вам плюс за усилия. Спасибо - person Julio Nobre; 01.08.2014