SQL Server 2000: почему этот запрос с переменными такой медленный по сравнению с переменными? - PullRequest
1 голос
/ 25 мая 2010

Я не могу понять, почему этот запрос будет таким медленным с переменными, а не без них. Я прочитал кое-что, где мне нужно включить «Динамические параметры», но я не могу найти, где это сделать.

DECLARE
      @BeginDate AS DATETIME
     ,@EndDate AS DATETIME
SELECT
      @BeginDate = '2010-05-20'
     ,@EndDate = '2010-05-25'

-- Fix date range to include time values
SET @BeginDate = CONVERT(VARCHAR(10), ISNULL(@BeginDate, '01/01/1990'), 101) + ' 00:00'
SET @EndDate = CONVERT(VARCHAR(10), ISNULL(@EndDate, '12/31/2099'), 101) + ' 23:59'

SELECT
     *
FROM
    claim c
WHERE
    (c.Received_Date BETWEEN @BeginDate AND @EndDate) --this is much slower
    --(c.Received_Date BETWEEN '2010-05-20' AND '2010-05-25') --this is much faster

Ответы [ 3 ]

7 голосов
/ 25 мая 2010

Какой тип данных "c.Received_Date"?

Если это не дата и время, тогда столбец будет преобразован в дату и время, потому что @ BeginDate / @ EndDate - это дата и время. Это известно как приоритет типа данных . Это включает в себя, если столбец smalldatetime (согласно ссылке), потому что datetime имеет почти самый высокий приоритет

С константами оптимизатор будет использовать тип данных столбца

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

Изменить, увидев планы запросов

Что касается литералов, SQL Server определил, что поиск, за которым следует поиск по закладкам, является лучшим, поскольку значения являются литералами.

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

Для запроса, использующего переменные, он принял общий случай, поскольку при изменении значений он может повторно использовать план. Общий случай - избегать поиска по закладкам, и в этом случае у вас есть сканирование PK (кластерный индекс)

Узнайте больше о том, почему поиск по закладкам обычно является плохой вещью на Simple-talk

В этом случае, вы можете попробовать индексную подсказку, чтобы заставить его, но если диапазон слишком широкий, это будет очень медленно. или вы можете удалить SELECT * (плохая практика в любом случае) и заменить на SELECT col1, col2 etc и использовать индекс покрытия

1 голос
/ 25 мая 2010
SET STATISTICS IO ON
SET STATISTICS TIME ON

количество сканирований и логических чтений?

0 голосов
/ 26 мая 2010

Вы упомянули, что один и тот же запрос к одним и тем же данным на другом сервере выполняется быстро.

Аппаратное обеспечение идентично или, по крайней мере, достаточно похоже?

  • процессоров - столько же?
  • Есть ли какой-нибудь процессор с гиперпоточностью?
  • Одинаково ли физическое расположение дисков (скорость диска, отдельные шпиндели для данных, журнал, tempdb?)

Такое поведение часто можно увидеть по устаревшей статистике.

use dbfoo;
go
exec sp_updatestats
go

И, наконец, сравните настройки SQL для каждого поля:

exec sp_configure 'show advanced options', '1'
go
RECONFIGURE
exec sp_configure;
go
...