2012-05-23 4 views
9

Я только что нашел предложение TABLESAMPLE, но на удивление он не возвращает число строк, которые я указал.TABLESAMPLE возвращает неправильное количество строк?

Таблица, которую я использовал, имеет ~ 14M строк, и мне нужен произвольный образец из 10000 строк.

select * from tabData TABLESAMPLE(10000 ROWS) 

Я получаю не 10000, а другое число каждый раз, когда выполняю его (между 8000 и 14000).

Что здесь происходит, я неправильно понял, что цель TABLESAMPLE?

Edit:

David's link объясняет это довольно хорошо.

Это всегда возвращает 10000 примерно случайных строк эффективным способом:

select TOP 10000 * from tabData TABLESAMPLE(20000 ROWS); 

и вариант REPEATABLE помогает получить всегда то же самое (если данные не изменились)

select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS) REPEATABLE(100); 

Поскольку я хотел знаете, стоит ли использовать TABLESAMPLE с большим количеством строк, чтобы гарантировать (?), что я получаю правильный номер строки, я ее измерил;

1.loop (в 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.loop (в 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: counterscheck со 100% случайных строк с использованием ORDER BY NEWID() :

select TOP 10000 * from tabData ORDER BY NEWID(); 

(10000 row(s) affected) 

Отменено после одного исполнения, которая длилась 23 минут

Заключение:

Так удивительно подход с точным TOP пункта и большим количеством в TABLESAMPLE является не медленнее. Следовательно, это очень эффективная альтернатива ORDER BY NEWID(), если неважно, что строки не являются случайными для каждой строки, а для каждого уровня страницы (каждой странице 8K для таблицы присваивается случайное значение).

ответ

4

См. article here. Вам нужно добавить верхнее предложение и/или использовать параметр repeatable, чтобы получить нужное количество строк.

+0

Повторяемый параметр не помогает получить 10000 строк. Это гарантирует, что я получаю одинаковый номер каждый раз, когда выполняется запрос (данные unitl не изменились). Во всяком случае, статья объясняет это очень хорошо. Я могу комбинировать его с «TOP'-предложением (f.e 10000), чтобы получить почти 10000 строк. Благодарю. –

+1

Не делает TOP, если результат * меньше *, чем номер TABLESAMPLE. –

+0

@David: Так вы можете получить точный номер с помощью TABLESAMPLE: 'select TOP 10000 * from tabData TABLESAMPLE (20000 ROWS);'. Соответственно отредактировал мой ответ. –

1

Это поведение было зарегистрировано ранее. На нем есть хорошая запись here.

Я считаю, что вы можете исправить это, пропустив REPEATABLE с тем же самым семенем каждый раз. Вот фрагмент из записки:

... вы заметите, что разные строки строк возвращаются каждый раз. Без изменения данных повторный запуск идентичного запроса сохраняет разные результаты. Это недетерминистический фактор предложения TABLESAMEPLE.Если таблица статична , и строки не изменяются, что может быть причиной возврата разных номеров строк, возвращаемых в каждом исполнении. Коэффициент равен 10 PERCENT не является процентом записей таблиц строк или таблиц, а - это проценты страниц данных таблицы. После того, как выбраны образцы страниц из , все строки из выбранных страниц возвращаются, не будет ограничивать количество строк, взятых с этой страницы. Коэффициент заполнения всех страниц зависит от данных таблицы. Это делает скрипт для возврата числа строк в результирующем наборе каждый раз, когда выполняется . Опция REPEATABLE приводит к возврату выбранного образца . Когда REPEATABLE указан с тем же значением repeat_seed , SQL Server возвращает такое же подмножество строк, если в таблицу не были внесены изменения . Когда REPEATABLE задано с другим значением repeat_seed, SQL Server обычно возвращает другой образец строк в таблице. ,

+1

Спасибо, но связана статья Дэвида объясняет это лучше. Опция repeatable не помогает получить 10000 строк, она будет обеспечивать, чтобы каждый раз получать то же самое, до тех пор, пока данные не будут изменены. –

1

Я наблюдал то же самое.

Объяснение страницы определенно имеет смысл и звонит в колокольчик. Вы должны увидеть гораздо более предсказуемые подсчеты строк при фиксированном размере строки. Попробуйте его в таблице без столбцов с нулевой или переменной длиной.

Фактически я просто использовал его, чтобы доказать теорию об использовании его для обновления (вероятно, вы были подстегнуты тем же вопросом, что и я), и выбор TABLESAMPLE (50000 ROWS) фактически затронул 49,849 строк.

+0

Таким образом, мы не можем полагаться на 'TABLESAMPLE', если количество строк играет важную роль? –

+0

@TimSchmelter Я не вижу, как, нет. Если количество строк имеет значение, используйте TOP или подзапрос с ROW_NUMBER() или в SQL Server 2012 OFFSET/FETCH. Дорогая часть будет сортироваться, если сортировка должна быть рандомизирована. –

+0

Хмм, пропуская эту часть: ссылка Дэвида предлагает совместить точное 'TOP' с большим номером строки в' TABLESAMPLE'. Он работает (см. Мое редактирование)! Считаете ли вы, что большое количество делает TABLESAMPLE более дорогим? –

2

Из документации.

Фактическое количество возвращаемых строк может значительно различаться. Если указывается небольшое число, например 5, вы не можете получать результаты в .

http://msdn.microsoft.com/en-us/library/ms189108(v=sql.90).aspx

+0

Спасибо, но [Davids Link] (http://www.mssqltips.com/sqlservertip/1308/retrieving-random-data-from-sql-server-with-tablesample/) объясняет это лучше, чем MSDN. –

Смежные вопросы