Тайм-ауты с использованием ODBC, но не Openquery для связанного сервера
Я подключаюсь к внешней базе данных через связанный сервер. Я использую многопоточную консольную программу в C#
разбить это SELECT
заявление.
SELECT *
FROM (
SELECT
C.Part_Key,
C.Part_Operation_Key,
C.Net_Weight,
C.Plexus_Customer_No,
C.Serial_No,
ROW_NUMBER() OVER (ORDER BY C.Serial_No) AS row
FROM Part_v_Container AS C
) a
WHERE a.row > 0 AND a.row <= 1000000
Это работает как чудо, и когда я получаю десять потоков, чтобы получить по 100000 записей каждая, это сокращает время с восьми минут до минуты. Но во время тестирования я сделал только один поток, чтобы получить все 1000000 записей. Основной код выглядит следующим образом:
try
{
adapter = new OdbcDataAdapter(sqlStatement, connection);
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
TimeSpan span = (timerStart - DateTime.Now);
Console.WriteLine("Data collected for thread " + threadNumber + " in the time of " + span);
timeTest(span);
Console.WriteLine("Rows collected = " + dataTable.Rows.Count);
retries = 0;
dataCollected = true;
}
Опять же, это работает, так что это не проблема. Проблема в том, что я получаю сообщение об ошибке тайм-аута от плекса, когда пытаюсь получить все 1000000 записей:
При извлечении данных из базы данных для потока с номером 0 возникла ошибка. Сообщение об ошибке было следующим: System.Data.Odbc.OdbcException (0x80131937): ОШИБКА [HYT00] [Plex][Драйвер источника данных отчета ODBC ODBC][OpenAccess SDK SQL Engine] Время ожидания запроса истекло [10246] в System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode) в System.Data.Odbc.OdbcCommand.ExecuteReaderObject(поведение CommandBehavior, метод String, метод SQL объекта, Boolean) odbcApiMethod) в System.Data.Odbc.OdbcCommand.ExecuteReaderObject(поведение CommandBehavior, метод String, логический needReader) в System.Data.Odbc.OdbcCommand.ExecuteReader(поведение CommandBehavior)
в System.Data.Odbc.OdbcCommand.ExecuteDbDataReader(поведение CommandBehavior) в System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(поведение CommandBehavior) в System.Data.Common.DbDataAdapter.FillTase ] datatables, int32 startRecord, Int32 maxRecords, String srcTable, команда IDbCommand, поведение CommandBehavior) в System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, поведение IDbCommandv at at), CommandB.Common.DbDataAdapter.Fill(DataTable dataTable) в ShippedContainerSettlement.DataCollectionThread.dataCollectionThread() в c:\Users\dkb\Source\Workspaces\ Рабочая область \Danrex\ShippedContainerSettlement\ShippedContainerSettlement FROM (ВЫБРАТЬ C.Part_Key, C.Part_Operation_Key, C.Net_Weight, C.Plexus_Customer_No, C.Serial_No, ROW_NUMBER() OVER (ORDER BY C.Serial_No) КАК строка FROM Part_v_Container AS C) ГДЕ a.row > 0 и a.row <=1005066
Если я выполню этот же запрос в SQL Management Studio, используя openquery, он может собрать все 1000000 записей.
Я понятия не имею, почему, потому что я не очень хорошо разбираюсь в базах данных, поэтому я надеялся, что кто-то может объяснить, почему это может иметь место?
РЕДАКТИРОВАТЬ: Это может быть ответ, который я нашел на этом форуме.
OpenQuery выполняется на сервере, и, возможно, он обрабатывает строки намного быстрее и возвращает только одну строку по сети. Делая это в Visual Studio, вы можете получить полный набор результатов и затем отфильтровать его на принимающем (клиентском) сервере. Это может быть причиной того, что это произошло с Visual Studio, но не с SSMS.
Кажется разумным?
Я только что протестировал openquery в C# и получил тайм-аут даже для таблиц с 3000 записей. Так что на самом деле не уверен, что происходит.