TABLESAMPLE возвращает неправильное количество строк?
Я только что обнаружил TABLESAMPLE
но, что удивительно, он не возвращает количество строк, которые я указал.
Таблица, которую я использовал, имеет ~14M строк, и я хотел произвольную выборку из 10000 строк.
select * from tabData TABLESAMPLE(10000 ROWS)
Я получаю не 10000, а другое число каждый раз, когда я его выполняю (между 8000 и 14000).
Что здесь происходит, я неправильно понял предназначение TABLESAMPLE
?
Редактировать:
Ссылка Дэвида объясняет это довольно хорошо.
Это всегда возвращает 10000 примерно случайных строк эффективным способом:
select TOP 10000 * from tabData TABLESAMPLE(20000 ROWS);
и REPEATABLE
опция помогает получить всегда одно и то же (если данные не изменились)
select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS) REPEATABLE(100);
Так как я хотел знать, если это дороже в использовании TABLESAMPLE
с большим количеством строк, чтобы убедиться (?), что я получил правильный номер строки, я его измерил;
1. цикл (20 раз):
select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS);
(9938 row(s) affected)
(10000 row(s) affected)
(9383 row(s) affected)
(9526 row(s) affected)
(10000 row(s) affected)
(9545 row(s) affected)
(9560 row(s) affected)
(9673 row(s) affected)
(9608 row(s) affected)
(9476 row(s) affected)
(9766 row(s) affected)
(10000 row(s) affected)
(9500 row(s) affected)
(9941 row(s) affected)
(9769 row(s) affected)
(9547 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(9478 row(s) affected)
First batch(only 10000 rows) completed in: 14 seconds!
2. цикл (20 раз):
select TOP 10000 * from tabData TABLESAMPLE(10000000 ROWS);
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
Second batch(max rows) completed in: 13 seconds!
3.loop: контрпроверка со 100% случайными строками с использованием ORDER BY NEWID():
select TOP 10000 * from tabData ORDER BY NEWID();
(10000 row(s) affected)
Отменено после одной казни, которая длилась 23 минуты
Вывод:
Так удивительно подход с точным TOP
оговорка и большое количество в TABLESAMPLE
не медленнее. Следовательно, это очень эффективная альтернатива ORDER BY NEWID()
если не имеет значения, что строки являются не случайными для каждой строки, а для уровня страницы (каждой 8К-странице для таблицы присваивается случайное значение).
4 ответа
Смотрите статью здесь. Вам нужно добавить верхнее предложение и / или использовать параметр repeatable, чтобы получить желаемое количество строк.
Из документации.
Фактическое количество возвращаемых строк может значительно различаться. Если вы укажете небольшое число, например 5, вы можете не получить результаты в выборке.
http://msdn.microsoft.com/en-us/library/ms189108(v=sql.90).aspx
Я наблюдал то же самое.
Объяснение страницы определенно имеет смысл и звучит как колокольчик - вы должны увидеть гораздо более предсказуемый счетчик строк, когда размер строки фиксирован. Попробуйте это на таблице без столбцов переменной длины или обнуляемых.
Фактически, я просто использовал это, чтобы доказать теорию о том, как использовать его для обновления (вероятно, вас подстегнул тот же вопрос, что и у меня), и выбор TABLESAMPLE (50000 ROWS) фактически затронул 49 849 строк.
Такое поведение было задокументировано ранее. Здесь есть хорошая рецензия.
Я считаю, что вы можете исправить это, передавая команду REPEATABLE с одним и тем же семенем каждый раз. Вот фрагмент из записи:
... вы заметите, что каждый раз возвращается различное количество строк. Без каких-либо изменений данных повторный запуск идентичного запроса дает разные результаты. Это недетерминированный фактор предложения TABLESAMEPLE. Если таблица статическая, а строки не изменены, что может быть причиной для возврата разных номеров строк, возвращаемых при каждом выполнении. Коэффициент 10 ПРОЦЕНТОВ - это не проценты строк таблицы или записей таблиц, это проценты страниц данных таблицы. Как только образцы страниц данных выбраны, возвращаются все строки с выбранных страниц, это не будет ограничивать количество строк, отобранных с этой страницы. Коэффициент заполнения всех страниц варьируется в зависимости от данных таблицы. Это заставляет скрипт возвращать различное количество строк в наборе результатов при каждом его выполнении. Параметр REPEATABLE приводит к тому, что выбранный образец возвращается снова. Когда REPEATABLE указан с тем же значением repeat_seed, SQL Server возвращает тот же поднабор строк, если в таблицу не было внесено никаких изменений. Если REPEATABLE указан с другим значением repeat_seed, SQL Server обычно возвращает другой образец строк в таблице.,