Вопрос оценки кардинальности?Параметры даты и времени против приведения? - PullRequest
3 голосов
/ 05 мая 2011

У меня проблемы со стрельбой из-за низкой производительности для запроса, который я разместил ниже.

Вот моя проблема:

Если я выполню точный запрос ниже в студии управления SQL Server или с помощью .NETsqlclient выполнение запроса занимает в среднем 14 секунд.

Однако, если в .NET я вынимаю эту часть запроса:

DECLARE @time_diff INT
DECLARE @start_date DATETIME
DECLARE @end_date DATETIME

SET @time_diff = 2
SET @start_date = '05/04/11 00:00:00 AM'
SET @end_date = '5/4/2011 11:59:59 PM'

и использую параметры в коде, подобном этому:

sqlParameter = sqlCmd.Parameters.Add(New SqlParameter("@start_date", System.Data.SqlDbType.DateTime))
sqlParameter.Value = parameters.StartDate
sqlParameter = sqlCmd.Parameters.Add(New SqlParameter("@end_date", System.Data.SqlDbType.DateTime))
sqlParameter.Value = parameters.EndDate

, тогда выполнение запроса занимает около 2–3 минут.


Кроме того, я заметил, что для выполнения требуется около 2–3 минут, если я заменюзначения параметров со строковыми константами даты и запуска в .NET или SSMS

--AND v.call_start_time BETWEEN @start_date AND @end_date
AND v.call_start_time BETWEEN '05/04/11' AND '5/4/2011 11:59:59 PM'

Я нашел эту статью http://msdn.microsoft.com/en-us/library/ms175933%28SQL.90%29.aspx о количестве элементов и оптимизаторе запросов, и я думаю, что это связано с моей проблемой, но этокажется, не имеет смысла в моем случае.Согласно статье, при определении количества элементов следует выполнять приведение типов.В моем случае этого не происходит.В статье также говорится, что вместо локальных переменных следует использовать параметры - что не очень хорошо работает с параметрами .NET.

Что касается использования хранимой процедуры: У меня есть переменное числопараметры, я не знаю, насколько хорошо это сработает.Даже если это единственный вариант, я все же хотел бы точно знать, в чем проблема.

Запрос:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SET STATISTICS IO ON

DECLARE @time_diff INT
DECLARE @start_date DATETIME
DECLARE @end_date DATETIME

SET @time_diff = 2
SET @start_date = '05/04/11 00:00:00 AM'
SET @end_date = '5/4/2011 11:59:59 PM'

--INSERT QUERY
SELECT * INTO ##tmp_15 FROM (-- PRI CALL RECORDINGS SEARCH QUERY:
    SELECT DISTINCT
    v.call_recording_id,
    v.call_start_time,
    v.call_source,
    v.call_type,
    IsNull(v.phone, '') AS phone,
    d.call_duration_seconds AS pri_call_duration_seconds,
    IsNull(cdr.extension, 'N/A') AS pri_extension,
    IsNull(users.last_name, 'N/A') AS pri_last_name,
    IsNull(users.first_name, 'N/A') AS pri_first_name,
    NULL AS debtor_no,
    NULL AS d_extension,
    NULL AS d_last_name,
    NULL AS d_first_name
    FROM tbl_call_recordings AS v
    JOIN tbl_pri_call_details AS d ON v.call_recording_id = d.call_recording_id
    LEFT JOIN (
        SELECT extension, phone, call_start_time
        FROM tbl_pri_cdr_records
        WHERE is_discard = 0
    ) AS cdr ON v.phone = cdr.phone AND
        ABS(DATEDIFF(mi, v.call_start_time, cdr.call_start_time)) <= @time_diff

    -- MATCH RECORDS TO USER INFO VIA EXTENSION
     LEFT JOIN (
        SELECT extension,
               start_date,
               IsNull(end_date, GETDATE()) AS end_date,
               usr.user_id,
               last_name,
               first_name,
              cr_user_id
        FROM tbl_extensions AS ext
        JOIN tbl_extension_users AS ext_usr ON ext.id = ext_usr.extension_id
        JOIN tbl_users AS usr ON ext_usr.user_id = usr.user_id
    ) AS users ON cdr.extension = users.extension
    AND v.call_start_time BETWEEN users.start_date AND users.end_date
    WHERE 1 = 1

    -- INSERT PRI SEARCH CONSTRAINTS HERE:
    AND v.call_start_time BETWEEN @start_date AND @end_date
    --AND v.call_start_time BETWEEN '05/04/11' AND '5/4/2011 11:59:59 PM'

UNION

-- DIALER RECORDINGS SEARCH QUERY:
      SELECT
        v.call_recording_id,
        v.call_start_time,
        v.call_source,
        v.call_type,
        IsNull(v.phone, '') AS phone,
        NULL AS pri_call_duration_seconds,
        NULL AS pri_extension,
        NULL AS pri_last_name,
        NULL AS pri_first_name,
       d.debtor_no,
        IsNull(users.extension, 'N/A') AS extension,
        IsNull(users.last_name, 'N/A') AS last_name,
        IsNull(users.first_name, 'N/A') AS first_name
      FROM tbl_call_recordings AS v
      JOIN tbl_dialer_call_details AS d ON v.call_recording_id = d.call_recording_id

      -- MATCH RECORDS TO USER INFO VIA EXTENSION
      LEFT JOIN (
                SELECT extension,
                       start_date,
                       IsNull(end_date, GETDATE()) AS end_date,
                       last_name,
                       first_name,
                       cr_user_id
                FROM tbl_extensions AS ext
                JOIN tbl_extension_users AS ext_usr ON ext.id = ext_usr.extension_id
                JOIN tbl_users AS usr ON ext_usr.user_id = usr.user_id

      ) as users ON d.agent = users.cr_user_id
        AND v.call_start_time BETWEEN users.start_date AND users.end_date
      WHERE 1 = 1
      -- INSERT DIALER SEARCH CONSTRAINTS HERE:
    AND v.call_start_time BETWEEN @start_date AND @end_date
    --AND v.call_start_time BETWEEN '05/04/11' AND '5/5/2011'
)t

1 Ответ

1 голос
/ 05 мая 2011

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

Хорошая статья, обсуждающая эту проблему, находится здесь.

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