|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Получение рандомных строк с помощью ORDER BY random() быстро работает на небольших таблицах, но скорость выполнения падает с ростом количества строк в таблице. В связи с этим я стал искать решение, которое выбирало бы рандомные строки и работало быстро, как на небольших, так и на огромных таблицах. Первым делом наткнулся на решение из статьи , отредактировал его под себя так Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49.
Работает он очень быстро, но не совсем корректно. Имея таблицу с 3750 строк и значения id идущие подряд до 1183, а затем идет пропуск и далее значения id сразу начинаются с 2084. (строки с пропущенными значениями были удалены). В таком случае запрос намного чаще возвращает строку с id 2084 и 2086 и почти никогда не возвращает строки с id > 3000. (Скрин) Этот вариант мне не нравится, хоть и работает быстро. Затем я взял запрос из данной темы, немного переписал его, для получения всей строки по условию. Получилось это Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
custom.numRows = 1; // Количество строк Данный код конечно работает, но имея в таблице только одну совпадающею с условием строку я получаю её грубо говоря через раз. Т.е выполнил я один раз запрос - получил строку, выполнил второй раз точно такой же запрос - не получил строку, хотя в таблице она есть. Я думаю, что это связано с generate_series(1,1000). И, наконец, всеми хвалимый TABLESAMPLE. Он не подходит из-за того что сначала выбирает строки, а уже после применяет условие. Из-за этого в выборке может не оказаться строк, подходящих под условие, несмотря на то, что в базе они есть. Я думал сделать выборку по такому алгоритму: 1) Выбрать все id подходящие под условие. 2) Скриптом (javascript) выбрать рандоное значение из результирующего массива с idшниками. 3) Получить запись со значением id из пункта 2. Но мне он дико не нравится из-за того, что придется в первом пункте тянуть весь список id из базы. (а если строк миллионы...) Я думаю это сильно скажется на производительность. Как можно поступить в моём случае? Какие есть варианты? Postgresql v9.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 19:21 |
|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Risko, если вы можете быстро выбрать "1) Выбрать все id подходящие под условие." то вы и быстро выберете оттуда order by random() limit N 'но скорость выполнения падает с ростом количества строк в таблице.' - не с количеством строк в таблице а с падением скорости выбора всех нужных вам строк. Т.е. от вашего решения толку ровно ноль... order by random() LIMIT N будет быстрее работать в таком случае. Чтобы корректно выбрать случайную строку из выборки - сначала надо всю выборку получить, соответственно быстрее чем получение всех подходящих вам строк - это сделать НЕ ВОЗМОЖНО. Так что никаких вариантов у вас и нет. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 19:48 |
|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Risko, Посмотрите в сторону предложения TABLESAMPLE команды SELECT . А так же стандартное расширение tsm_system_rows Это если позволяет версия. Потом расскажете о результатах. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2020, 12:11 |
|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Предлагаю выбирать псевдослучайные строки. То есть создать индекс по, например, MD5 от первичного ключа: Код: sql 1.
Потом выбирать по нему: Код: sql 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2020, 23:25 |
|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Flashpoke Предлагаю выбирать псевдослучайные строки. То есть создать индекс по, например, MD5 от первичного ключа: Код: sql 1.
Потом выбирать по нему: Код: sql 1. 2. 3. 4. 5.
не работает когда надо выбирать по условиям из таблицы (о чем написано в исходном письме) из просто таблицы я могу придумать несколько рабочих схем но вот когда надо выбирать с дополнительными условиями не заданными заранее - рабочих решений нет. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 02:12 |
|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Maxim Boguk не работает когда надо выбирать по условиям из таблицы (о чем написано в исходном письме) Однако на миллионе записей довольно быстро. Код: sql 1. 2. 3. 4. 5. 6.
В поле val случайные значения от 0 до 1000000. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
При val BETWEEN 100 AND 200: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Ускорение ведь будет относительно seq scan с рандомом, или я что-то не учёл? Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 14:53 |
|
Как быстро получить рандомные строки?
|
|||
---|---|---|---|
#18+
Flashpoke, И опять цитирую автора "Данный код конечно работает, но имея в таблице только одну совпадающею с условием строку я получаю её грубо говоря через раз. Т.е выполнил я один раз запрос - получил строку, выполнил второй раз точно такой же запрос - не получил строку, хотя в таблице она есть." оно будет криво работать например на условии where val=10 именно с вышеуказанными симптомами. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 15:01 |
|
|
start [/forum/topic.php?fid=53&fpage=24&tid=1994536]: |
0ms |
get settings: |
8ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
40ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
54ms |
get tp. blocked users: |
2ms |
others: | 296ms |
total: | 438ms |
0 / 0 |