Комментарии 21
Решение прикольное. По сути это эмуляция части логики N-ного уровня на N+1-ом, так как сам движок не догадывается о частном случае использования собственных же средств ускорения доступа.
А как выглядит план там же без хаков?!
Глянул, грустно. Я надеялся по простоте душевной что слоник умеет выбирать по индексу и досортировывать потом…
Из опыта работы.
Ни одному юзеру никогда не требовался этот самый реестр, особенно с пейджингом.
Что касается таких учетных систем, как сбис, 1с, axapta, и прочих, прочих
Юзер всегда ищет конкретный документ! Всегда!
Юзер, работающий с потоуом звявок Всегда (!!) будет смотреть только первые 5-10 строк и выбирать из них.
По этому. Все эти реестры документов и "проблемы" сортировки лишь в головах разработчиков.
Создавать индексы нужно правильно, но нужно.
Проблемы мутации кортежей надо отслеживать и применять разные техники. Например партицирование и прочее, а не отбрасывать с определением, что вставуа медленная…
Если она медленная, то это проблема архитектуры БД.
Иначе прюолучишь проседание по выборкам с фулсканами.
По мне, так это костыль, для прилуманной проблемы.
Ни одному юзеру никогда не требовался этот самый реестр, особенно с пейджингом.
а, например, покупка авиабилетов? (да и в целом, логистика)
Что касается учётных систем, то совсем не редкость, когда что-то с чем-то не сходится, и тогда юзер начинает «крыжить» документы.
Юзер всегда ищет конкретный документ! Всегда!
Беда в том, что иногда это нужно вдолбить в головы всем людям на проекте, вплоть до архитекторов. А потом еще и юзерам, которые тоже не всегда догадываются, что им нужна хорошая система фильтров, а не «бахнем 10К записей в таблице на экран, а дальше сами поищите».
Из опыта работы.
А у вас опыт, простите, юзера или разработчика?
Юзер всегда ищет конкретный документ!
Только вот идентифицирует пользователь этот документ совсем не по ID. А примерным интервалом дат и чем-то в комментарии, что "точно не помню, но как увижу, сразу узнаю". И именно грамотный пейджинг позволяет в таких ситуациях найти этот документ максимально быстро.
По опыту, юзерам может и не нужно, но вот заказчику нужно. Обычно не разработчики предлагают сделать пагинацию, а заказчик, стейкхолдера и т. п.
Представьте, вы приходите с аппаратом комплексных чисел к электротехникам-постоянщикам, и они вас посылают — так как это выдумка сплошная, к практике неприменимо никак итд. Затем они изобретают машину переменного тока, и вдруг оказывается, что аппаратец-то очень кстати, и теперь они уже идут к вам ;)
Поэтому я просто запомнил, что существует прикольный способ — пусть даже 100% как гимнастика ума, ибо в практическом применении действительно а) размер специального индекса будет пренебрежимо мал по сравнению с размером записи в таблице реестров, б) обычно в бизнес-таблицах и так несколько индексов, так что компактный индекс, одна из колонок которого — кластерный, перестроить будет несложно
Представьте что у вас есть массив циферок в строчке — разделов. Так вот, если по нему построить составной btree (cats, ctime) — то вы получите все комбинации того, что лежит внутри cats и списки строк отсортированные по ctime, но индекс не будет толком работать при поиске по вхождению в этот индекс: например cats @> array[2] и будет давать full scan, а вот … where cats = array[2] order by ctime даст, через, так называемый sort hint, очень быструю выдачу по вторичному ключу (не забудьте limit).
Если сделать индекс gin (с расширением btree_gin) — то запросы @> заработают, но вот незадача, sort hint, увы, на gin по полю ctime уже не заработает.
Если кто знает как это решить без доп-таблицы и пачки вариаций btree индексов с where cat @> 1,2,3…, поделитесь плиз )
WHERE cat @> '{1,2,3}'::int[] ORDER BY point(ctime, ctime) <-> point(0, 0) LIMIT 1
, если я правильно понял задачу.www.percona.com/blog/2020/09/10/index-improvements-in-postgresql-13
Только PG13 нужен.
Не заумно ли тут все написано? Хотя, ту да голый SQL или поздно и я не уловил сути.
Я делал подобный финт ушами на linq2db (C#), как-то обходился без CTE и UNION по ненадобности.
Главное правило, все что в ORDER BY дожно быть уникальным ключем и тогда такой пейджинг делается с пол пинка. Где-то у меня валялся алгоритм который любой LINQ запрос заворачивал в такой пейджинг. По заявкам откопаю.
Принцип простой, есть ORDER BY asc1, asc2, desc1 DESC
asc1 + asc2 + desc1 — обязательно уникальный ключ
Первый запуск
SELECT * FROM table t
ORDER BY t.asc1, t.asc2, t.desc1 DESC
LIMIT 101
Берем на одну запись больше запоминаем asc1, asc2, desc1 последней записи. Также в таком варианте мы уже можем знать что страница последняя, на клиент возвращаем на одну запись меньше.
Второй запуск, следующая страница
SELECT * FROM table t
WHERE t.asc1 >= asc1 AND t.asc2 >= asc2 AND t.desc1 <= desc1
ORDER BY t.asc1, t.asc2, t.desc1 DESC
LIMIT 101
Повторяем запоминание попоследнаей записи.
Конечно алгоритм чуток больше еще учитывал, просто передал кратко принцип
SQL HowTo: курсорный пейджинг с неподходящей сортировкой