2016-04-06 3 views
4

У меня есть код C#, который возвращает DataTable, возвращаемый из SELECT в базе данных A, и передает его в качестве хранимого в таблице параметра в хранимую процедуру в базе данных B через Microsoft.Practices.EnterpriseLibrary. Метод Data.Database.ExecuteDataSet. В таблице около 200 тыс. Строк. В нашей тестовой среде, где A и B находятся на одном сервере, для выполнения хранимой процедуры требуется всего несколько секунд. Но в процессе производства вызов ExecuteDataSet занимает почти 30 минут. Рассмотрение журналов базы данных показывает, что почти все это время потребляется между началом вызова ExecuteDataSet и началом хранимой процедуры.C#: Передача DataTable на SQL Server очень медленная

В тесте обе базы данных находятся на одном сервере. В производстве A и B расположены на разных серверах.

Что может быть причиной этой чрезвычайной задержки и что можно сделать по этому поводу? Это происходит только при работе с производственными серверами. Он запускается в нескольких тестовых средах без проблем.

Обновление 2016/04/08

Производительность является разумным, если табличное значение параметра передается как IEnumerable <SqlDataRecord> вместо DataTable. Требуется 7 секунд, чтобы передать 50 000 записей для использования SqlDataRecord, но 400 секунд с использованием DataTable. Проблема связана с сервером. Тот же объем данных передается другому серверу с использованием DataTable без проблем.

+0

Использование параметра table-value для обработки записей 200K, безусловно, вызовет проблемы с производительностью. Его производительность быстро уменьшается по мере увеличения рядов. Кроме того, передача данных на два сервера сопровождается узкими местами производительности из-за различных проблем. Как часто выполняется эта сохраненная процедура proc? Часто ли эти 200k-записи меняются? Можете ли вы подробнее рассказать о том, как эти 200k-записи используются хранимым процессом? – AKS

+0

@Amit: он отлично работает в тестовой среде, работающей через несколько секунд. Деловая потребность - объединить данные на этих двух серверах, и они не могут быть связаны напрямую. –

+1

Он будет работать лучше в тесте, поскольку оба db находятся на одном сервере, как вы упомянули. Если исходная таблица часто не обновляется, вы можете создать какой-то процесс ETL для импорта таблицы из базы данных A в B. Вы также можете использовать репликацию базы данных для репликации таблицы. Вы также можете использовать 'OPENQUERY', или вы можете сделать это в' .net', используя 'SqlBulkInsert'. Я не думаю, что подход с табличным параметром будет соответствовать этому большому набору данных. – AKS

ответ

1

Мы столкнулись с этой проблемой. Обновленный вывод из Кевин Клайн помог нам понять, почему он будет работать быстро на одном сервере и невероятно медленно по другому:

производительность является разумным, если табличное значение параметра передается , как IEnumerable вместо DataTable. Требуется 7 секунд , чтобы передать 50 000 записей на использование SqlDataRecord, но 400 секунд с использованием DataTable. Проблема связана с сервером. Тот же объем данных передается на другой сервер с использованием DataTable без проблем.

Мы обнаружили, что наличие параметра SQL Server ForceEncryption - это разница между быстродействующим сервером и медленным сервером. Если ForceEncryption установлен на Yes, то он работает плохо; если он установлен на No, тогда он хорошо работает. Этот параметр находится в диспетчере конфигурации SQL Server -> Конфигурация сети SQL Server -> Щелкните правой кнопкой мыши «Протоколы» -> «Выбор свойств» -> вкладка «Сертификат» -> выберите вкладку «сертификат» -> флаги.

Чтобы обойти эту проблему, у вас есть два варианта. Либо отключите настройку ForceEncryption в вашей базе данных (возможно, нецелесообразно), либо избегайте использования DataTables и вместо этого используйте SqlDataRecords, как предложил Кевин Клайн.