Статистика SQL и индексы - насколько они подробны? - PullRequest
5 голосов
/ 22 октября 2010

Учитывает ли статистика (которая помогает решить, следует ли использовать индекс) число строк на фактическое значение столбца или просто используется среднее числоколичество строк на значение.

Предположим, у меня есть таблица с битовым столбцом, который называется активным, в котором содержится миллион строк, но для 99,99% установлено значение false.Если у меня есть индекс для этого столбца, то Sql достаточно умен, чтобы знать, чтобы использовать индекс при поиске active = 1, но что нет смысла, если поиск active = 0.

Другой пример, если яиметь таблицу, в которой, скажем, 1 000 000 записей с индексированным столбцом, который содержит около 50 000 различных значений со средним числом строк на значение 10, но затем одно специальное значение, которое имеет 500 000 строк.Индекс может быть бесполезен при поиске этой специальной записи, но будет очень полезен при поиске любого другого кода.

Но разве этот частный случай разрушает эффективность индекса?

Ответы [ 3 ]

3 голосов
/ 22 октября 2010

Вы можете убедиться сами:

CREATE TABLE IndexTest (
Id int not null primary key identity(1,1),
Active bit not null default(0),
IndexedValue nvarchar(10) not null
)

CREATE INDEX IndexTestActive ON IndexTest (Active)
CREATE INDEX IndexTestIndexedValue ON IndexTest (IndexedValue)

DECLARE @values table
(
    Id int primary key IDENTITY(1, 1),
    Value nvarchar(10)
)

INSERT INTO @values(Value) VALUES ('1')
INSERT INTO @values(Value) VALUES ('2')
INSERT INTO @values(Value) VALUES ('3')
INSERT INTO @values(Value) VALUES ('4')
INSERT INTO @values(Value) VALUES ('5')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')

DECLARE @rowCount int
SET @rowCount = 100000

WHILE(@rowCount > 0)
BEGIN
    DECLARE @valueIndex int
    SET @valueIndex = CAST(RAND() * 10 + 1 as int)
    DECLARE @selectedValue nvarchar(10)
    SELECT @selectedValue = Value FROM @values WHERE Id = @valueIndex
    DECLARE @isActive bit
    SELECT @isActive = CASE 
            WHEN RAND() < 0.001 THEN 1 
            ELSE 0
           END
    INSERT INTO IndexTest(Active, IndexedValue) VALUES (@isActive, @selectedValue)
    SET @rowCount = @rowCount - 1
END

SELECT count(*) FROM IndexTest WHERE Active = 1
SELECT count(*) FROM IndexTest WHERE Active = 0

SELECT count(*) FROM IndexTest WHERE IndexedValue = '1'
SELECT count(*) FROM IndexTest WHERE IndexedValue = 'Many'

Мне кажется, он всегда использует индексы в этом плане запросов:

query plan

1 голос
/ 22 октября 2010

Вы можете просто посмотреть статистику и убедиться в этом :) DBCC SHOW_STATISTICS.См. Раздел «Примечания», в нем есть хорошее объяснение того, как на самом деле хранятся и используются гистограммы:

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

alt text

Для каждого шага гистограммы:

  • Жирная линия представляет верхнее граничное значение (RANGE_HI_KEY) и количество раз, которое это происходит (EQ_ROWS)
  • Сплошная область слева от RANGE_HI_KEY представляет диапазон значений столбца, а среднее число раз, когда каждое значение столбца происходит(AVG_RANGE_ROWS).AVG_RANGE_ROWS для первого шага гистограммы всегда равно 0.
  • Пунктирные линии представляют выборочные значения, используемые для оценки общего числа различных значений в диапазоне (DISTINCT_RANGE_ROWS) и общего количества значений в диапазоне (RANGE_ROWS).Оптимизатор запросов использует RANGE_ROWS и DISTINCT_RANGE_ROWS для вычисления AVG_RANGE_ROWS и не сохраняет выборочные значения.

Оптимизатор запросов определяет шаги гистограммы в соответствии с их статистической значимостью.Он использует алгоритм максимальной разницы, чтобы минимизировать количество шагов в гистограмме, максимизируя разницу между граничными значениями.Максимальное количество шагов - 200. Число шагов гистограммы может быть меньше количества различных значений, даже для столбцов с количеством граничных точек менее 200.Например, столбец с 100 различными значениями может иметь гистограмму с менее чем 100 граничными точками.

1 голос
/ 22 октября 2010

Создает гистограмму и, таким образом, использует ее.

С небольшим столбцом будет хорошо знать, сколько их 0 и 1

Со строковым столбцом у него будет грубое представление о "полосах" (значения, начинающиеся с a, b, c и т. Д.). То же самое для чисел (создает x полос диапазонов значений).

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

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