У меня есть 2 установки, которые показывают разную производительность, и я хочу понять, почему.Я должен записать много информации, чтобы все, если это имеет смысл в контексте.
TLTR: Почему я теряю логарифмическую масштабируемость моего индекса из нескольких столбцов?
таблица:
CREATE TABLE Schema1.Item
(
Id INT IDENTITY(1,1) PRIMARY KEY,
UniqueName VARCHAR(20) NOT NULL UNIQUE,
GroupId INT NOT NULL FOREIGN KEY REFERENCES Schema1.Group(Id),
Category VARCHAR(200),
Properties VARCHAR(max)
);
В последнем столбце «Свойства» содержится словарь JSON, если имя-свойства + значение-свойства.Какие свойства там есть, зависит от GroupId.
Тестовые данные:
- состоит из 1 миллиона элементов
- , распределенных по 20 группам (таким образом, 50000 элементов наgroup)
- , которые содержат 10 категорий (т. е. 5000 элементов на категорию на группу)
Это индекс с уменьшающейся производительностью по мере увеличения таблицы:
CREATE NONCLUSTERED INDEX IX_GroupId_Category
ON [Schema1].[Item] (GroupId, Category)
INCLUDE(Id, UniqueName, Properties)
Таким образом, запрос может выглядеть следующим образом:
SELECT TOP (1000) *
FROM [Schema1].[Item]
WHERE GroupId = 2
AND Category = 'Category4'
AND JSON_VALUE(Properties, '$."PropertyName"') LIKE '%PropertyValue%'
Но я хочу обсудить только ЭТОТ запрос, потому что в конечном итоге все ПОСЛЕ этого запроса всегда <5000 элементов: </p>
SELECT TOP (1000) *
FROM [Schema1].[Item]
WHERE GroupId = 2
AND Category = 'Category4'
План выполнения в основном состоит из 100% поиска по индексу, с предполагаемым + фактическим количеством строк = 1000 (как и ожидалось).Здесь все выглядит хорошо.
Но с 1.000.000 элементов этому запросу все еще нужно 2-3 секунды для завершения (без кэширования запроса).Для 100 000 элементов это было <1 секунда </strong>.
Это, кажется, противоречит логике логарифмической масштабируемости индексов?Даже с моими очень большими листами индекса (поскольку они содержат весь столбец с nvarchar(max)
, который обычно составляет около 500 байт), все равно не должно быть такой большой разницы между 100 000 и 1 000 000 элементов?
Далее я попытался создать индексированное представление, которое
- фильтрует по
GroupId
(таким образом, оно имеет максимум 50 000 строк) - и имеет индекс по категории (+ включая всестолбцы, такие же, как и раньше)
И для этого представления запросы вроде этого:
SELECT TOP (1000) *
FROM [Schema1].[Item_ViewGroupId1]
WHERE Category = 'Category4'
нужны только <1 секунда </strong>!
Может ли кто-нибудь объяснить мне, почему между этими двумя реализациями такая большая разница?
Я что-то упустил?
РЕДАКТИРОВАТЬ: Кажется, проблема вбыть связано с физическими показаниями:
- Медленно: Таблица «Элемент».Сканирование 1, логическое чтение 362, физическое чтение 148, чтение с опережением 547, чтение логического объекта 0, чтение с физического объекта 0, чтение с опережением 0.
- Fast: Таблица «Элемент».Сканирование 1, логическое чтение 362, физическое чтение 0, чтение с опережением 264, логическое чтение с лоба 0, физическое чтение с лоба 0, чтение с опережением чтения 0
И кажется, что в среднемзапросам на представления реже требуется физическое чтение?
Значит ли это, что я просто зависел от того, что сервер кэширует?Можно ли как-нибудь улучшить это?