Решение проблемы тайм-аута ADO в VB6 - PullRequest
5 голосов
/ 01 декабря 2010

У меня проблема с заполнением набора записей ADO в VB6. Запрос (запускающий SQLServer 2008) выполняется всего около 1 секунды, когда я запускаю его с помощью SSMS. Он отлично работает, когда набор результатов невелик, но когда он достигает нескольких сотен записей, это занимает много времени. 800+ записей требуют около 5 минут для возврата (запрос все еще занимает только 1 секунду в SSMS), а 6000+ занимает более 20 минут. Я «исправил» исключение, увеличив тайм-аут команды, но мне было интересно, есть ли способ заставить его работать быстрее, так как это не похоже на реальный запрос, который требует так много времени. Что-то вроде сжатия результатов, чтобы это не заняло много времени. Набор записей открывается следующим образом:

myConnection.CommandTimeout = 2000
myConnection.ConnectionString = "Provider=SQLOLEDB;" & _
        "Initial Catalog=DB_NAME;" & _
        "Data Source=SERVER_NAME" & _
        "Network Library=DBMSSOCN;" & _
        "User ID=USER_NAME;" & _
        "Password=PASSWORD;" & _
        "Use Encryption for Data=True;"
myConnection.Open

myRecordSet.Open STORED_PROC_QUERY_STRING, myConnection, adOpenStatic, adLockReadOnly
Set myRecordSet.ActiveConnection = Nothing

myConnection.Close

Данные возвращают 3 столбца, используемых для заполнения поля со списком.

UPDATE: Я запустил SQL Profiler, и экземпляры с клиентского компьютера выполняют больше операций чтения и занимают в 100 раз больше времени, чем оба показателя для запросов в SSMS. Текст запроса одинаков как для SSMS, так и для клиентского компьютера в соответствии с профилировщиком, поэтому я не думаю, что он должен использовать другой план выполнения. Может ли сетевая библиотека или провайдер повлиять на это?

Статистика профайлера:

  • Из клиентского приложения: 7041720 читает, 59458 мс, 3900 строк насчитывает
  • из SSMS: 30802 чтения, 238 мс длительность, 3900 отсчетов строк

Кажется, что он использует другой план выполнения, но запрос точно такой же, и я не уверен, как проверить план выполнения, который может использовать клиент, если он отличается от того, который показан в SSMS.

1 Ответ

3 голосов
/ 02 декабря 2010

800+ records requires about 5 minutes = проблема запроса.

посмотрите на ваш план выполнения:

В SSMS запустите:

SET SHOWPLAN_ALL ON

затем запустите ваш запрос, он не выдаст ожидаемый набор результатов, а план исключения из того, как база данных извлекает ваши данные. Большинство плохих запросов обычно сканируют таблицу (посмотрите на каждую строку в таблице, что медленно), поэтому ищите слово «SCAN» в столбце StmtText. Попытайтесь выяснить, почему индекс не используется в этой таблице (имя будет там под словом "SCAN"). Если вы объединяете несколько таблиц и имеете несколько SCAN, сначала сконцентрируйтесь на самых больших таблицах.

Без дополнительной информации это лучшая «общая» помощь, которую вы можете получить.

EDIT
Прочитав ваш вопрос, я не уверен, что вы имеете в виду, что он всегда быстрый из SSMS независимо от строк, но медленный из VB по мере увеличения строк. Если это так, проверьте это: http://www.google.com/search?q=sql+server+fast+from+ssms+slow+from+application&hl=en&num=100&lr=&ft=i&cr=&safe=images

может быть что-то вроде: сниффинг параметров или несогласованные параметры соединения (нули ANSI, arithabort и т. Д.)

для настроек соединения, попробуйте запустить их из SSMS и из VB6 (добавьте их в набор результатов) и посмотрите, есть ли различия:

SELECT SESSIONPROPERTY ('ANSI_NULLS') --Specifies whether the SQL-92 compliant behavior of equals (=) and not equal to (<>) against null values is applied.
                                      --1 = ON 
                                      --0 = OFF

SELECT SESSIONPROPERTY ('ANSI_PADDING') --Controls the way the column stores values shorter than the defined size of the column, and the way the column stores values that have trailing blanks in character and binary data.
                                        --1 = ON 
                                        --0 = OFF

SELECT SESSIONPROPERTY ('ANSI_WARNINGS') --Specifies whether the SQL-92 standard behavior of raising error messages or warnings for certain conditions, including divide-by-zero and arithmetic overflow, is applied.
                                         --1 = ON 
                                         --0 = OFF

SELECT SESSIONPROPERTY ('ARITHABORT') -- Determines whether a query is ended when an overflow or a divide-by-zero error occurs during query execution.
                                      --1 = ON 
                                      --0 = OFF

SELECT SESSIONPROPERTY ('CONCAT_NULL_YIELDS_NULL') --Controls whether concatenation results are treated as null or empty string values.
                                                    --1 = ON 
                                                    --0 = OFF

SELECT SESSIONPROPERTY ('NUMERIC_ROUNDABORT') --Specifies whether error messages and warnings are generated when rounding in an expression causes a loss of precision.
                                              --1 = ON 
                                              --0 = OFF

SELECT SESSIONPROPERTY ('QUOTED_IDENTIFIER') --Specifies whether SQL-92 rules about how to use quotation marks to delimit identifiers and literal strings are to be followed.
                                             --1 = ON 
                                             --0 = OFF

сделайте ваш запрос похожим (чтобы вы могли видеть настройки соединения в VB6):

SELECT
    col1, col2
        ,SESSIONPROPERTY ('ARITHABORT') AS ARITHABORT
        ,SESSIONPROPERTY ('ANSI_WARNINGS') AS ANSI_WARNINGS
    FROM ...
...