Частичная сортировка
От: valker  
Дата: 25.01.22 13:32
Оценка:
Всем привет!

Допустим есть таблица с колонкой типа число.

CREATE TABLE tbl (value int NOT NULL);


и в этой таблице, допустим 10000 записей.

Надо вернуть тысячу самых маленьких значений.

SELECT * FROM tbl ORDER BY value LIMIT 1000;


В результате, эти значения будут упорядочены: 1, 2, 3...

Существует ли способ сделать этот запрос быстрее, если нас не интересует упорядоченность результирующего списка строк (2, 3, 1, ...) ?
Re: Частичная сортировка
От: wildwind Россия  
Дата: 25.01.22 14:39
Оценка: 4 (1)
Здравствуйте, valker, Вы писали:

V>Существует ли способ сделать этот запрос быстрее, если нас не интересует упорядоченность результирующего списка строк (2, 3, 1, ...) ?


Если есть индекс по value, и LIMIT не слишком велик, доступ по индексу даст нужный результат без сортировки.

Если индекса нет или он неприменим, то, в зависимости от используемой СУБД и ее версии, для таких запросов может использоваться оптимизированный top-N алгоритм. Значения на выходе будут все равно упорядоченными, но он будет эффективнее, чем полная сортировка. Точно знаю, про современные версии SQL Server и Oracle. Скорее всего, в PostgreSQL он тоже есть (точно не знаю).
Re: Частичная сортировка
От: cppguard  
Дата: 25.01.22 18:21
Оценка: 12 (1)
Здравствуйте, valker, Вы писали:

V>Существует ли способ сделать этот запрос быстрее, если нас не интересует упорядоченность результирующего списка строк (2, 3, 1, ...) ?


SoF по теме https://stackoverflow.com/questions/33936485/understanding-order-by-using-top-n-heapsort-in-postgres
Re: Частичная сортировка
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.01.22 12:19
Оценка: -1
Здравствуйте, valker, Вы писали:
V>Существует ли способ сделать этот запрос быстрее, если нас не интересует упорядоченность результирующего списка строк (2, 3, 1, ...) ?
Нет.
Во-первых, limit без order by не имеет смысла — СУБД вольна возвращать результат select в произвольном порядке; вряд ли вы захотите видеть "любые 1000 записей". (а если захотите именно любые, то вам нужен надёжный способ их перемешивать).
Во-вторых, невозможно отобрать top N записей по некоторому критерию без сортировки всего набора по этому критерию.
Поэтому упорядоченность у вас будет так или иначе достигнута. Она будет достигнута быстро, если вы сортируете по (суб)ключу некоторого индекса. Ещё быстрее — если это будет кластерный индекс, или индекс, покрывающий ваш список атрибутов в select.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Частичная сортировка
От: wildwind Россия  
Дата: 26.01.22 13:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>невозможно отобрать top N записей по некоторому критерию без сортировки всего набора по этому критерию.


Еще как возможно, если под "сортировкой всего набора" понимать материализацию отсортированного набора в памяти. Для top N же достаточно O(N) памяти.
Re[3]: Частичная сортировка
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.01.22 13:58
Оценка:
Здравствуйте, wildwind, Вы писали:
W>Еще как возможно, если под "сортировкой всего набора" понимать материализацию отсортированного набора в памяти. Для top N же достаточно O(N) памяти.
А зачем это так понимать? Речь идёт о том, что придётся просмотреть весь набор. И в памяти придётся держать N позиций отсортированными.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Частичная сортировка
От: wildwind Россия  
Дата: 26.01.22 14:04
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А зачем это так понимать? Речь идёт о том, что придётся просмотреть весь набор. И в памяти придётся держать N позиций отсортированными.

"Просмотреть", согласен, это другое дело.
Re[4]: Частичная сортировка
От: cppguard  
Дата: 27.01.22 04:32
Оценка:
Здравствуйте, Sinclair, Вы писали:


S> И в памяти придётся держать N позиций отсортированными.


Прогуляли курс "алгоритмы и структуры данных" в универе? Есть, как-минимум, два способа вернуть top-N без выделения памяти на весь объём данных: heap и балансировочные деревья.
Re[5]: Частичная сортировка
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.01.22 05:57
Оценка: +1
Здравствуйте, cppguard, Вы писали:
C>Прогуляли курс "алгоритмы и структуры данных" в универе? Есть, как-минимум, два способа вернуть top-N без выделения памяти на весь объём данных: heap и балансировочные деревья.
Нет, просто вы невнимательно читаете. И heap и балансировочные деревья держат N позиций в памяти до окончания сортировки.
Вы, наверное, перепутали то N, которое top-N с тем, которое "всего позиций".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.