Я изучал пороговые значения выборки с помощью обновлений статистики на SQL Server (2012) и заметил некоторое любопытное поведение. По сути, число выбранных строк при некоторых обстоятельствах может меняться - даже с одним и тем же набором данных.
Я запускаю этот запрос:
--Drop table if exists
IF (OBJECT_ID('dbo.Test')) IS NOT NULL DROP TABLE dbo.Test;
--Create Table for Testing
CREATE TABLE dbo.Test(Id INT IDENTITY(1,1) CONSTRAINT PK_Test PRIMARY KEY CLUSTERED, TextValue VARCHAR(20) NULL);
--Insert enough data so we have more than 8Mb (the threshold at which sampling kicks in)
INSERT INTO dbo.Test(TextValue)
SELECT TOP 1000000 'blahblahblah'
FROM sys.objects a, sys.objects b, sys.objects c, sys.objects d;
--Create Index on TextValue
CREATE INDEX IX_Test_TextValue ON dbo.Test(TextValue);
--Update Statistics without specifying how many rows to sample
UPDATE STATISTICS dbo.Test IX_Test_TextValue;
--View the Statistics
DBCC SHOW_STATISTICS('dbo.Test', IX_Test_TextValue) WITH STAT_HEADER;
Когда я смотрю на вывод SHOW_STATISTICS, я обнаруживаю, что «Выборка строк» меняется с каждым полным выполнением (т. Е. Таблица удаляется, воссоздается и заполняется).
Например:
Ряды, выбранные
- 318618
- 319240
- 324198
- 314154
Я ожидал, что эта цифра будет одинаковой каждый раз, когда таблица идентична. Кстати, я не получаю такого поведения, если я просто удаляю данные и вставляю их заново.
Это не критический вопрос, но мне было бы интересно понять, что происходит.
sql-server
sql-server-2012
statistics
Мэтью МакДжиффен
источник
источник
318618 = 1142*279
,319240 = 1144*279 + 64
,324198=1162*279
И314154=1126
поэтому дисперсия является число страниц , отобранных.Ответы:
Задний план
Данные для объекта статистики собираются с помощью оператора в форме:
Вы можете собрать этот оператор с помощью расширенных событий или Profiler (
SP:StmtCompleted
).Запросы генерации статистики часто обращаются к базовой таблице (а не к некластеризованному индексу), чтобы избежать кластеризации значений, которые естественным образом происходят на страницах некластеризованного индекса.
Количество выбранных строк зависит от количества целых страниц, выбранных для выборки. Каждая страница таблицы либо выбрана, либо нет. Все строки на выбранных страницах вносят свой вклад в статистику.
Случайные числа
SQL Server использует генератор случайных чисел, чтобы решить, соответствует ли страница требованиям или нет. В этом случае используется генератор случайных чисел Лемера со значениями параметров, как показано ниже:
Значение рассчитывается как сумма:
Xseed
Младшая целая часть
bigint
базовой таблицы ( ),partition_id
напримерЗначение, указанное в
REPEATABLE
пунктеUPDATE STATISTICS
, тоREPEATABLE
значение равно 1.m_randomSeed
элементе внутренней информации отладки метода доступа, показанной в планах выполнения, например, когда включен флаг трассировки 8666<Field FieldName="m_randomSeed" FieldValue="1" />
Для SQL Server 2012 этот расчет происходит в
sqlmin!UnOrderPageScanner::StartScan
:где memory at
[rcx+30h]
содержит младшие 32 бита идентификатора раздела, а memory at[rcx+2Ch]
содержит используемоеREPEATABLE
значение.Генератор случайных чисел инициализируется позже в том же методе, вызывая
sqlmin!RandomNumGenerator::Init
, где инструкция:... умножает начальное число на
41A7
шестнадцатеричное (16807 десятичное = 7 5 ), как показано в приведенном выше уравнении.Более поздние случайные числа (для отдельных страниц) генерируются с использованием того же основного кода, встроенного в
sqlmin!UnOrderPageScanner::SetupSubScanner
.Statman
Для примера
StatMan
запроса, показанного выше, будут собраны те же страницы, что и для оператора T-SQL:Это будет соответствовать выводу:
Край случае
Одним из следствий использования генератора случайных чисел MINSTD Lehmer является то, что начальные значения нуля и int.max не должны использоваться, так как это приведет к тому, что алгоритм выдаст последовательность нулей (выбор каждой страницы).
Код обнаруживает ноль и использует значение из системных «часов» в качестве начального числа в этом случае. Это не делает то же самое, если начальное число int.max (
0x7FFFFFFF
= 2 31 - 1).Мы можем разработать этот сценарий, поскольку начальное начальное число рассчитывается как сумма младших 32 бит идентификатора раздела и
REPEATABLE
значения.REPEATABLE
Значение , которое приведет к семени быть int.max и , следовательно , каждая страница выбирается для выборки:Работая это в полный пример:
Это выберет каждую строку на каждой странице, что бы ни
TABLESAMPLE
говорилось в предложении (даже ноль процентов).источник
Это отличный вопрос! Я начну с того, что знаю наверняка, а затем перейду к предположениям. Много подробностей об этом в моем блоге здесь .
Выборочные обновления статистики используют
TABLESAMPLE
за кулисами. Это довольно легко найти документацию об этом в Интернете. Тем не менее, я считаю, что не очень хорошо известно, что строки, возвращаемые функциейTABLESAMPLE
частично, зависятhobt_id
от объекта. Когда вы отбрасываете и воссоздаете объект, вы получаете новый,hobt_id
поэтому строки, возвращаемые случайной выборкой, различаются.Если вы удалите и повторно вставите данные, они
hobt_id
останутся прежними. Пока данные располагаются одинаково на диске (проверка порядка размещения возвращает одинаковые результаты в том же порядке), выборочные данные не должны изменяться.Вы также можете изменить количество выбранных строк, перестроив кластеризованный индекс в таблице. Например:
Что касается того, почему это происходит, я считаю, что это связано с тем, что SQL Server сканирует кластеризованный индекс вместо некластеризованного индекса при сборе выборочной статистики по индексу. Я также думаю, что есть скрытое (для тех из нас, кто отслеживает скрытые запросы на обновление статистики) значение для
REPEATABLE
использования сTABLESAMPLE
. Я не доказал ничего из этого, но он объясняет, почему ваша гистограмма и выбранные строки изменяются с перестройкой кластерного индекса.источник
Я видел это в Inside Microsoft SQL Server 2008: T-SQL Querying от Ицик Бен-Гана, и я не могу добавить его в качестве комментария, поэтому я публикую его здесь, я думаю, что это интересно и другим:
Смотрите также Выборка с использованием TABLESAMPLE от Roji. П. Томас.
источник