У нас возникла проблема, когда индексы в наших таблицах игнорируются, а SQL Server 2000
вместо этого выполняет сканирование таблиц.
Несмотря на 4,302
дней, прошедших с Aug 29, 1997
, оптимизатор SQL Server
еще не превратился в SkyNet
и все еще может принимать некоторые неверные решения.
Индексные подсказки - это то, как вы, человеческое существо, помогаете искусственному интеллекту.
Если вы уверены, что собрали статистику, а оптимизатор все еще не работает, продолжайте, воспользуйтесь подсказками.
Они являются законными, правильными, документированными и поддерживаются Microsoft
способом обеспечить выполнение плана запроса, который вы хотите.
В вашем случае:
SELECT CustomerID,
SUM(InvoiceTotal) AS SumOfInvoiceTotal,
SUM(AmountPaid) AS SumOfAmountPaid
FROM tblInvoices
WHERE CustomerID = 2112
GROUP BY
CustomerID
, оптимизатор имеет два варианта:
- Используйте индекс, который подразумевает вложенный цикл над индексом вместе с
KEY LOOKUP
, чтобы получить значения InvoiceTotal
и AmountPaid
- Не используйте индекс и сканируйте все строки таблиц, что быстрее в
rows fetched per second
, но длиннее с точки зрения общего числа строк.
Первый метод может быть или не быть быстрее, чем второй.
Оптимизатор пытается оценить, какой метод быстрее, просматривая статистику, которая сохраняет селективность индекса наряду с другими значениями.
Для выборочных индексов первый метод быстрее; для неселективных - последний.
Не могли бы вы выполнить этот запрос:
SELECT 1 - CAST(COUNT(NULLIF(CustomerID, 2112)) AS FLOAT) / COUNT(*)
FROM tlbInvoices
Обновление:
Поскольку CustomerID = 2112
охватывает только 1,4%
ваших строк, вам следует воспользоваться индексом.
Теперь, не могли бы вы выполнить следующий запрос:
DBCC SHOW_STATISTICS ([tblinvoices], [CustomerID])
, найдите две строки смежных строк в третьем наборе результатов, где RANGE_HI_KEY
меньше и больше 2112
, и разместите строки здесь?
Обновление 2:
Поскольку статистика кажется верной, мы можем только догадываться, почему оптимизатор выбирает полное сканирование таблицы в этом случае.
Вероятно (вероятно), это потому, что это самое значение (2112
) встречается в RANGE_HI_KEY
, и оптимизатор видит, что оно необычно плотное (3427
значения только для 2112
против всего 911
для целого диапазон от 1668
до 2111
)
Не могли бы вы сделать еще две вещи:
Запустить этот запрос:
DBCC SHOW_STATISTICS ([tblinvoices], [CustomerID])
и опубликуйте первые два набора результатов.
, используйте верхний CustomerID
из запроса выше в исходном запросе:
SELECT CustomerID,
SUM(InvoiceTotal) AS SumOfInvoiceTotal,
SUM(AmountPaid) AS SumOfAmountPaid
FROM tblInvoices
WHERE CustomerID = @Top_Customer
GROUP BY
CustomerID
и посмотрите, какой план он создаст.