"order by newid ()" - как это работает? - PullRequest
34 голосов
/ 12 февраля 2011

Я знаю, что если я выполню этот запрос

select top 100 * from mytable order by newid()

он получит 100 случайных записей из моей таблицы.

Однако меня немного смущает, как это работает, поскольку я не вижу newid() в списке select. Может кто-нибудь объяснить? Есть ли здесь что-то особенное в newid()?

Ответы [ 5 ]

33 голосов
/ 13 февраля 2011

Я знаю, что делает NewID (), я просто пытаюсь понять, как это поможет при случайном выборе.Если (1) оператор select выберет ВСЕ из mytable, (2) для каждой выбранной строки, прикрепите уникальный идентификатор, сгенерированный NewID (), (3) отсортируйте строки по этому уникальному идентификатору и (4) выберете верх100 из отсортированного списка?

Да.это в значительной степени верно (за исключением того, что не обязательно сортировать все строки).В этом можно убедиться, посмотрев фактический план выполнения.

SELECT TOP 100 * 
FROM master..spt_values 
ORDER BY NEWID()

Скалярный оператор вычисления добавляет столбец NEWID() для каждой строки (2506 в таблице в моем примере запроса), а затем строки втаблицы отсортированы по этому столбцу с топ 100 выбранных.

SQL Server на самом деле не нужно сортировать весь набор по позициям 100 вниз, поэтому он использует оператор сортировки TOP N, который пытается выполнить всю операцию сортировки в памяти ( для небольших значений N)

Plan

10 голосов
/ 13 февраля 2011

В целом это работает так:

  • Все строки из mytable"зациклены"
  • NEWID () выполняется для каждой строки
  • Строки отсортированы по случайному номеру из NEWID ()
  • 100 выбран первый ряд
7 голосов
/ 07 мая 2014

Ключом здесь является функция NEWID, которая генерирует глобально уникальный идентификатор (GUID) в памяти для каждой строки.По определению, GUID является уникальным и довольно случайным;поэтому, когда вы сортируете по этому GUID с предложением ORDER BY, вы получаете случайный порядок строк в таблице.Взяв верхние 10 процентов (или любой другой процент), вы получите случайную выборку строк в таблице.

Предложен запрос NEWID;это просто и работает очень хорошо для небольших столов.Однако запрос NEWID имеет большой недостаток, когда вы используете его для больших таблиц.Предложение ORDER BY приводит к копированию всех строк в таблице в базу данных tempdb, где они сортируются.Это вызывает две проблемы: Операция сортировки обычно связана с высокой стоимостью.Сортировка может использовать много дискового ввода-вывода и может выполняться в течение длительного времени.В худшем случае в базе данных tempdb может не хватить места.В лучшем случае tempdb может занимать большой объем дискового пространства, которое никогда не будет возвращено без команды сжатия вручную.Вам нужен способ случайного выбора строк, который не будет использовать базу данных tempdb и не станет намного медленнее по мере увеличения таблицы.Вот новая идея о том, как это сделать:

SELECT * FROM master..spt_values
  WHERE (ABS(CAST(
  (BINARY_CHECKSUM(*) *
  RAND()) as int)) % 100) < 10

Основная идея этого запроса заключается в том, что мы хотим сгенерировать случайное число от 0 до 99 для каждой строки в таблице, а затем выбрать всеиз тех строк, случайное число которых меньше значения указанного процента.В этом примере мы хотим, чтобы приблизительно 10 процентов строк были выбраны случайным образом;поэтому мы выбираем все строки, чье случайное число меньше 10.

4 голосов
/ 12 февраля 2011

as MSDN говорит:

NewID () Создает уникальное значение типа uniqueidentifier.

, и ваша таблица будет отсортирована по этомуслучайные значения.

1 голос
/ 01 сентября 2015

используйте select top 100 randid = newid(), * from mytable order by randid Вы будете прояснены тогда ..

...