|
|
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
хотя и не пятница http://habrahabr.ru/post/242999/ забавно, пассажир, похоже не понимает, что это решение (как и все подобные) работает только в предположении сплошного (или хотя бы равномерного) заполнения id. К примеру если [равномерное "в большом"] заполнение сделано по шаблону "островки" по m через лакуны по N, где N >>m -- верхние границы островков будут попадать в выборку в ~N раз более часто, чем "сидящие в толще островков". более общо -- любое заполнение id с дырками и островами приводит к неравновероятности выборок по алгоритму по ссылке. т.е. приглашаю желающих предложить сглаживающие островной эффект алгоритмы, не требующие полного перебора мн-ва id. (а например всего-то редкого прощупывания его плотности тем же монтекарлом). Есть ли такие ? К каким прореженным множествам id применимы ? -- для не очень больших островков можно пуститься на неглубокий рендомный оффсет, но кто ж гарантирует отсутствие больших глубин. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 15:30:36 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
?Ыхотя и не пятница http://habrahabr.ru/post/242999/ забавно, пассажир, похоже не понимает, что это решение (как и все подобные) работает только в предположении сплошного (или хотя бы равномерного) заполнения id. К примеру если [равномерное "в большом"] заполнение сделано по шаблону "островки" по m через лакуны по N, где N >>m -- верхние границы островков будут попадать в выборку в ~N раз более часто, чем "сидящие в толще островков". более общо -- любое заполнение id с дырками и островами приводит к неравновероятности выборок по алгоритму по ссылке. т.е. приглашаю желающих предложить сглаживающие островной эффект алгоритмы, не требующие полного перебора мн-ва id. (а например всего-то редкого прощупывания его плотности тем же монтекарлом). Есть ли такие ? К каким прореженным множествам id применимы ? -- для не очень больших островков можно пуститься на неглубокий рендомный оффсет, но кто ж гарантирует отсутствие больших глубин. я думаю в общем случае эта задача не решается просто по причине фундаментальных ограничений математики так что особо тут ничего не придумаешь. Если предполагать что множество ID не слишком сильно разрежено (ну скажем не более чем в 100 раз разница между количества записей и разности между min/max id). В таком случае можно решить следующим образом (я так делал) - просто в цикле запросом или хранимкой выбираются записи по случайному id из диапазона min/max пока не набератся нужные N. Подход работает и обеспевивает честный random(). Но становится неэффективен если множество id сильно разрежено. --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 16:00:51 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, "высший разум" в исходном посте попробовал решить проблему разреженной наумерации именно для моего алгоритма... но естественно он получил проблему краев на островах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 16:04:03 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, т.е. если заменить t.id > min + (max - min) * random() на t.id = min + (max - min) * random() и переписать запрос слегка (чтобы он нормально miss обрабатывал) то будет нормальный алгоритм без краевых эффектов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 16:08:17 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
?Ы, можно воспользоваться имеющейся статистикой по полю histogram_bounds из pg_stats , там должны быть границы диапазонов, вероятность попадания в которые примерно одинакова. алгоритм тогда будет примерно такой: сначала случайным образом выбираем диапазон, а потом выбираем значение из диапазона. при правильно подобранном значении statistics_target и актуальной статистике теоретически должно работать. в исходный запрос автора не сильно вникал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 16:16:35 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim BogukMaxim Boguk, т.е. если заменить t.id > min + (max - min) * random() на t.id = min + (max - min) * random() и переписать запрос слегка (чтобы он нормально miss обрабатывал) то будет нормальный алгоритм без краевых эффектов. т.е. чтобы не прибавлять лакунами веса краевым точкам. Да , это наверное работает. хотя бы на равномерном распределении с равномерными лакунами. надо поразмышлять. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 16:24:34 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
?ЫMaxim BogukMaxim Boguk, т.е. если заменить t.id > min + (max - min) * random() на t.id = min + (max - min) * random() и переписать запрос слегка (чтобы он нормально miss обрабатывал) то будет нормальный алгоритм без краевых эффектов. т.е. чтобы не прибавлять лакунами веса краевым точкам. Да , это наверное работает. хотя бы на равномерном распределении с равномерными лакунами. надо поразмышлять. Вот эта версия работает на совершенно любом распределении и работает корректно. Но на сильно разреженных таблицах конечно не быстрая: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. PS: кто был на PgMaster 2014 в Питере должны опознать стиль да :). --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 17:32:27 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim BogukЕсли предполагать что множество ID не слишком сильно разрежено (ну скажем не более чем в 100 раз разница между количества записей и разности между min/max id). В таком случае можно решить следующим образом (я так делал) - просто в цикле запросом или хранимкой выбираются записи по случайному id из диапазона min/max пока не набератся нужные N. Подход работает и обеспевивает честный random(). Но становится неэффективен если множество id сильно разрежено . PS думаю можно обобщить {min max} на range[], min-max -->length(range[]) (т.е. SUM(length (range[i])) при miss пополнять наш массив range[] (информцию о дырках) ну и т.д. При малом количестве очень больших дыр -- будет работать сносно. [1..10 , 1E8::bigint] [т.е. большие сплошные дырки будут быстро выколоты] но это "улучшение" не очень эффективно -- при числе дыр сравнимым с числом точек (добавит изрядную константу--множитель в стоимость, не улучшив производительность) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2014, 17:41:54 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, > Но на сильно разреженных таблицах конечно не быстрая интересно оценить бы точнее. может руки дойдут, попробую. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 01:43:39 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Misha Tyurin, ну да. отношение кол-ва элементов N к длине интервала min-max M -- это основа. тогда на каждом шаге будем попадать с вероятностью P = N/M, а мазать с Q = 1 - P = (M - N)/M. и нам надо набрать k элементов. а дальше придите знатоки и нарисуйте формулу для числа попыток i = I(N, M, k). это какая-то классическая задача. не могу вспомнить/придумать сходу... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 02:04:19 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Misha Tyurin, https://ru.wikipedia.org/wiki/Формула_Бернулли это всё про "Формула_Бернулли" и с этим связанным, вроде оно. http://www.math.com.ua/mathdir/formula_bernoulli.html http://www.matburo.ru/ex_tv.php?p2=bernul3 " Решение задачи на формулу наивероятнейшего числа успехов Задача 3: Сколько следует сыграть партий в шахматы с вероятностью победы в одной партии, равной 1/3, чтобы наивероятнейшее число побед было равно 5? " вроде даже можно всё найти, если интернет не врёт ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 03:31:29 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Misha Tyurin, если интервал min-max большой и таблица большая, а число сколько надо взять сильно маленькое. и если вероятность попасть при этом 1%, то чтобы набрать 5 элементов, надо щелкнуть 500 раз. как-то очень интуитивно даже ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 03:51:22 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Misha Tyurin, собственно именно такие прикидки у меня и были... в общем то 500 index only probes - оно дешево даже 5000 приемлемо на самом деле по скорости. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 07:43:44 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Misha Tyurin, можно решить такую задачу. пусть p=count/(max-min) - вероятность случайным образом попасть в элемент, q = 1-p, k - количество необходимых элементов (могут повторяться). вопрос: сколько раз нужно выбирать, чтобы с вероятностью 99% выбрать не менее k элементов? если вспомнить теорию вероятностей, в частности схему Бернулли и интегральную теорему Муавра - Лапласа, то можно получить приближенное уравнение, справедливое при достаточно большом n*p*q: Код: sql 1. поиграться с параметрами можно тут . например, если p=0.01 и нужно получить k=100 элементов, то нужно выбирать 12615 раз, что в общем-то близко к очевидной оценке k/p=10000. а вот при p=0.01 и k=5 получается уже 1357 вместо 500, хотя это уже на границе применимости формулы. если кому не лень - проверьте экспериментально. конечно, можно брать доверительный интервал не 99%, а поменьше, тогда и числа будут меньше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 09:08:48 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
?Ыхотя и не пятница http://habrahabr.ru/post/242999/ забавно, пассажир, похоже не понимает, что это решение (как и все подобные) работает только в предположении сплошного (или хотя бы равномерного) заполнения id. К примеру если [равномерное "в большом"] заполнение сделано по шаблону "островки" по m через лакуны по N, где N >>m -- верхние границы островков будут попадать в выборку в ~N раз более часто, чем "сидящие в толще островков". более общо -- любое заполнение id с дырками и островами приводит к неравновероятности выборок по алгоритму по ссылке. т.е. приглашаю желающих предложить сглаживающие островной эффект алгоритмы, не требующие полного перебора мн-ва id. (а например всего-то редкого прощупывания его плотности тем же монтекарлом). Есть ли такие ? К каким прореженным множествам id применимы ? -- для не очень больших островков можно пуститься на неглубокий рендомный оффсет, но кто ж гарантирует отсутствие больших глубин. Задача редкая, и на ум приходит только одна цель, по которой рандомно что-то нужно выдернуть из БД - показать случайный набор вопросов испытуемому. Следовательно такой набор вопросов практически не изменяем и для ликвидации "окон" стоит завести отдельное "непрерывное" поле, по которому и вести случайный поиск. Периодически, по необходимости это поле обновлять. Дёшево и сердито. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 12:39:35 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
zeon11 <> Задача редкая, и на ум приходит только одна цель, по которой рандомно что-то нужно выдернуть из БД - показать случайный набор вопросов испытуемому. Следовательно такой набор вопросов практически не изменяем и для ликвидации "окон" стоит завести отдельное "непрерывное" поле, по которому и вести случайный поиск. Периодически, по необходимости это поле обновлять. Дёшево и сердито. кхм. как бы это помяхше. на табличке в 10^8 (даже партицированной) это уже и не дёшево и не сердито. а как джопп авовакуума-то будет рад работе. да и редискенс -- не подарок , простите, reindex . а про редкость задачи -- дык лотерейщики жеж (те же розыгрыши лохов у операторов и прочие завлекалки - несть им числа). (или вот тот же монтекарло попытаться натянуть в каком- нить алгоритме -- она и встанет). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 12:57:53 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexius, > p=0.01 и k=5 получается уже 1357 вместо 500 интегралы эти, про Муавра - Лапласа, замечал ночью, но далее не стал углубляться в школьные годы чудесные) угу, но в два раза промазать это еще боле менее) так что на 5 попаданий надо будет прыгнуть в индекс (возможно индекс_онли) 1000 раз грубо. ок ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 13:46:56 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Вот последняя самая быстрая версия: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. время получения 10 записей из таблицы с 1M записей с разрежением 100 (т.е. 1миллион id в диапазоне до 100M) - 3-5ms (смотря как random попадает). (~1000 итераций в среднем) время получения 1000 записей из той же таблицы (100.000 итераций в среднем) 450ms (весьма стабильное но нужен большой work_mem). изменения: 1)выяснено что JOIN c Код: plsql 1. 2. 3. в цикле занимает заметное время и сильно быстрее пробрасывать min/max через r на каждой итерации. 2)убрано вычисление (max - min) из цикла 3)версия с ручным cnt вместо coalesce(array_length(res,1),0) быстрее на 5-10% заодно и последний unnest блок стал побыстрее изза сортировки по константе а не по функции от массива. 4)странная конструкция id IS NULL OR ...<=10 которая могла приводить к получению N+1 и более вариантов при редком стечении обстоятельств заменена на простую и понятную cnt<10 (заодно стало понятнее что творится). Вообще оказалось что пробрасывать дополнительные колонки через рекурсивный WITH очень дешево чем надо пользоваться. 70% времени теперь занимают Index Only Scan using table1_pkey on table1 так что дальше ускорять смысла нет. Это предел для этого алгоритма. --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 19:39:13 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, Нет мне всетаки не спится... В общем вот версия которая на коротких списках работает приблизительно так же как и предыдущая а вот на списках в 1000 случайных работает в 3 раза быстрее и главное требует на 3 порядка меньше памяти для работы (предыдущая версия требовала на 1000 случайных значений при 0.01 заполнении больше 200MB текущая в 1MB влезает и работает за 150ms): Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Идея в том чтобы на каждой итерации пробовать получить не по одной случайной записи а сразу по N. Крайне выгодно для разреженных таблиц (так как резко сокращает число итераций). Для плотных таблиц в общем баш на баш будет. Заодно получилась сильно укороченная и более понятная версия неоптимизированного (с скоростью работы как в предыдущем посте) запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. И кто после этого скажет что на SQL неитересно программировать :). --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2014, 21:42:15 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, > Идея в том чтобы на каждой итерации пробовать получить не по одной случайной записи а сразу по N. ) мощь и сила! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.11.2014, 14:39:20 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Забавно, что пассажыр на хабре упоротствует. ему показали, что его "решение" НЕ решает поставленную им же задачу. от слова вообще. так божья росца смешные они там. PS тут тоже, помнится, кто-то про карму заикался, не будем тыкать пальцем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.11.2014, 17:57:33 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
PS тут тоже, помнится, кто-то про карму заикался, не будем тыкать пальцем. это жесткий оффтоп, вот по этому поводу, в том числе, чтобы такого не было, я и предлагал вводить доп требования. можно найти по моему профилю, моим темам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.11.2014, 18:27:20 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, А что даст запрос если в таблице будут 5 записей с ID = {1, 2, 2000000000, 2000000001, 2000000002} P.S. попал в топик с Хабра ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.11.2014, 00:50:49 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Шавлюк ЕвгенийMaxim Boguk, А что даст запрос если в таблице будут 5 записей с ID = {1, 2, 2000000000, 2000000001, 2000000002} P.S. попал в топик с Хабра будет очень долго думать... про разреженные таблицы что алгоритм работает с ними не очень хорошо. если разрежение 1:100 - скорость 5ms на выбор 10 записей из 10M строк разрежение 1:1000 - 50ms на выбор 10 записей из 10M строк дальше алгоритм уже неприменим скорее. Алгоритм с хабра никогда вообще число 2 не этом наборе не выдаст (точнее выдаст с вероятностью 1/2000000000). Что показывает его некорректность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.11.2014, 09:52:05 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim BogukMaxim Boguk, <> Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. красиво тоько я всё время сам забываю про краевые эффекты, когда краям дается вес по 0.5, а в середке -- по 1. кажется с поправкой оно вернее (могу врать). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.11.2014, 15:13:15 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Шавлюк ЕвгенийMaxim Boguk, А что даст запрос если в таблице будут 5 записей с ID = {1, 2, 2000000000, 2000000001, 2000000002} P.S. попал в топик с Хабра вот для такого "разделения по областям ключа" -- я и пытался накидать "на словах", скорее всего много что наврал (где-то лишние коленца), но примерная канва "выбрасывания гигантских дырок" ( понятно, что основной выйгрыш должен идти от индекс скана, кторого в тесте нет) где-то такая: Код: 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. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.11.2014, 15:20:22 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Misha Tyurin<> это жесткий оффтоп, вот по этому поводу, в том числе, чтобы такого не было, я и предлагал вводить доп требования. можно найти по моему профилю, моим темам. ну зочем же так шапковозгораццо ? охолоните, что ли. тут вас больше одного, комсомольцев-то. во всех пальцем не натыкаесся. PS там, на хабре, поцыент вообще например пишед: авторПодвох обнаружился в самом "сердце" алгоритма — выборке записи из диапазона. Действительно, рекурсивный запрос пытается выбрать строчку, для которой выполнялось бы условие: Код: plaintext Но в случае, когда random() возвращает "1", это условие трансформируется в: ... и гордо лупцует себя пьяткой в хрудь я, хоть помню, что много раз себя перепроверял , что рандом пж возвращает открытый интервал , но всё равно полез в RTFM -- смотртеь с какого конца открыто: RTFM Код: plaintext и т.д. тащемто. рукалицо и порченный стыд. вот что карма и прочие комсомольские склонности с людяма делают ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.11.2014, 16:02:10 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
PS: кстати сообразил: чтобы принудить пж к индекс скану -- поцыенту потребовалось кастнуть левую сторону r int-у Код: sql 1. ну вот тут кривизна пж бесконечна, и таковой и будет ближайшие лет 200, как объясняет нам smagen а дальше он попросту всё попутал -- полез на rendom() батоны крошить, когда причина -- в касте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.11.2014, 16:12:21 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
PS . цена удаления дырок (т.е. усложнение алгоритма) получилась великовата. надо бы подсократить. привожу скрипты теста ddl Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. insert rnd with holes Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. Bogyk Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ORDER BY random() на такой табличке быстрее всего Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 14random + 10^6row_number() поиск по оконному порядку дороже ? Код: 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. -- предподсчет count() удешевит на 0.1-0.2 removing BIG holes Код: 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. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391. 392. 393. 394. -- дороговато выходит восстанавливать карту дырок всякий раз, даже когда их всего 15 (15 интервалов в массивах) надо б удешевить ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 13:36:34 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
PPS если слегка добавить рядков -- в 5 раз примерно, то наконец начинаем немного отыгрывать у full-scan- а Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. Код: 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. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391. 392. и если перенести расчет карты дырок на моменты попадания в большие дырки ( а не высчитывать всякий раз), то немного ускоряемся: Код: 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. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391. 392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419. 420. 421. 422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433. 434. 435. 436. 437. 438. 439. 440. 441. 442. 443. 444. 445. 446. 447. 448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460. 461. 462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475. 476. 477. 478. 479. 480. 481. 482. 483. 484. 485. 486. 487. 488. 489. 490. 491. 492. 493. 494. 495. 496. 497. 498. 499. 500. но не сильно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 15:44:34 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
?Ы, путем ковыряния в носу придумал такой алгоритм true рандома, который будет работать для этого случая. условия: 1) поле, по которому выбираем уникально 2) элементы расположены близко друг к другу, но существуют значительные "дырки" 3) число больших дырок < значения statistics target/2 (а лучше выкручиваем statistics для поля в максимум 10000) 4) статистика относительно аккуратная (autoanalyze собирает) take the best of both worlds: 1) выбираем границы диапазонов из имеющейся статистики, их у нас получится 10000 (если таблица большая конечно же) Код: sql 1. 2. 3. 4. 5. 2) сортируем диапазоны по их длине. тут нам нужно пометить те диапазоны, которые намного больше других - именно они и содержат дырки. можно по-разному это делать, например можно выделить те диапазоны, длины которых больше 2*median(len). получится что-то вроде такого: Код: plaintext 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. 3) алгоритмом Максима выбираем N диапазонов (могут повторяться, группируем потом по диапазонам) = сколько чисел нам надо выбрать 4) цикл по помеченным диапазонам (выборка из диапазонов с дырками): тут мы выбираем обычным order by random() с условиями по границам диапазона сколько элементов нам нужно. для каждого такого диапазона это всего будет index scan по 1/10000 строк таблицы. 5) цикл по непомеченным диапазонам: выбираем алгоритмом Максима столько элементов для каждого диапазона, сколько нужно. т.к. дырок больших в этих диапазонах нет - будет быстро 6) объединяем результаты 7) profit кодить это все не сильно хочется, но должно работать быстрее order by random (если только полтаблицы не выбирать конечно) и без краевых эффектов возле дырок. не важно, открытый интервал у random() или закрытый, все равно вероятность попасть в точку почти 0. а вот при касте происходит неявное округление, так что по 0.5 добавить не помешает, да. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 17:37:17 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexius, снкс. разрабатывая ноздрю: если разбить на 2 отдельных этапа --1. вырезание дырок (наперёд не более некоего финитного кол-ва) --2. выборка рандомов тыканием в единожды размеченное "картой" мн-ве то : 1. на первом жестко получаем мн-во (TABLE) {Lmin,Lrange}, которое никогда не перевычисляем на 2-м 2. выбрасываем большинство накладных (на свертку/развертку array-ев) на 2-м этапе -- заменив (JOIN LATERAL (SELECT * FROM {L_CTE_table} ORDER BY .. LIMIT 1) с предподсчитанной CTE табличкой, про которую выше) => вероятно будем иметь тот же профит но -- без обращения к не обязательно актуальной статистике тут важно -- отжать всё лишнее с каждого из этапов. но при всюду редком заполнении (когда всюду дырки одного порядка) full scan на очень редких заполнениях (10^-6) выиграет всегда. (или надо уметь очень дёшево вырезать очень много дырок). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 19:57:59 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
?Ы, хм, при всюду редком заполнении можно ввести какое-нибудь поле с хешем небольшой длины, так получим более-менее равномерное распределение (при хорошей хеш функции), куда тыкать можно, но правда с дублями. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 20:33:10 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
точнее поле можно и не создавать, только функциональный индекс. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 20:36:37 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
вот как-то так например, берем первые 16 бит от md5 в качестве хеша Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. Код: 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. 100 строк, 26ms. game over? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 21:16:45 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexius<> 100 строк, 26ms. game over ? до тез пор, пока я умышленно не прорежу именно по (('x'||md5($1::text))::bit(16)::integer); -- после чего игра потребует новой переиндексации (т.е. фуллскана ++) с новым хешем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 22:03:09 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexius, Hm не совсем. Там где будут коллизии 16битного хеша - скорее всего будет всегда выбираться первый в индексе с этим хешом... а остальные с тем же хешом не будут выбираться НИКОГДА. Достаточно неприятная особенность... учитывая что шанс коллизий на 16битах высокий. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 22:17:47 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim BogukAlexius, Hm не совсем. Там где будут коллизии 16битного хеша - скорее всего будет всегда выбираться первый в индексе с этим хешом... а остальные с тем же хешом не будут выбираться НИКОГДА. Достаточно неприятная особенность... учитывая что шанс коллизий на 16битах высокий. А увидел... order by random() каюсь да этой проблемы нет. Интересное решение факт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.11.2014, 22:20:00 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, тут еще важно правильно выбрать длину хешей. оптимальной наверное будет такая, при которой для каждого значения будет по 10 записей из таблицы (postgres для hash join'ов такое же правило использует). т.е. вычисляем длину хеша по простой формуле (lg(N)-1)/lg(2), для моей таблицы в 1.6М записей получаем 17 бит. для 100 строк время снизилось до 18-20ms. таким образом получаем почти константное время выборки одной строки, не зависящее от размера таблицы. правда при изменении числа строк в таблице на порядок и больше желательно перехешировать с новой длиной. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 06:36:58 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexius, Круто с хешом. Интересно, можно глянуть, если такого нету -- можно и на вики написать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 10:11:23 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexius 100 строк, 26ms. game over? помедитируйте над: Код: sql 1. 2. 3. 4. 5. 6. //если сходу неясно -- фтыкать до посинения резюме: пассажыр велосипедист, гружёный лишним знанием -- опаснее велосипедиста без башни [хотя бы тем, что врёт убедительней] простите, если кого обидел. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 10:52:43 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
лопата, Интересное замечание. Я почему то ожидал заметно более равномерного распределения первых 16 бит md5 относительно того что получилось. Возможно первые биты md5 - неудачный алгоритм хеширования для этой задачи и надо что то другое делать (фундаментально оно может ситуацию не изменит но как минимум сделает ее достаточно плоской для практического применения). Но тут уже начинается суровый computer science. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 12:22:22 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
лопата, вопросы выбора хеш функции, качества получившегося рандома и применимости подхода к конкретной задачи открытые. я смотрел на это распределение и посчитал его удовлетворительным. у меня получилось как-то так: Код: sql 1. 2. 3. 4. 5. 6. 7. Код: plaintext 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. вот тут есть некоторые исследования http://michiel.buddingh.eu/distribution-of-hash-values если кто запилит хи квадрат тест и сравнит результат с другими хеш функциями будет хорошо. или найдет публикации, наверняка это сто раз уже исследовано. ну и никто не запрещает ввести индексируемое поле и заполнять его при вставке каким-нибудь рандомным числом в заданном диапазоне. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 12:46:03 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, я ожидал разброса sqrt(avg(count(1)) -- по теорверу, типа (т.к. мы не подгоняли распределение под хеш ф-ю ). что уже фиксирует неравенство раз и навсегда (для любого заранее данного хеша и заданного распределения набора id). но, кажется, даже это ожЫдание не оправдалось (т.е. там другой собаки sqrt порылся) кто-то может вспомнить, как это делаецца по науке ? Дисперсия там, то ,сё. От числа бросаний, ага. Можно ж определить изначально ожидаемую "несправедливость" для случайно выбранной хеш ф-ии, и неизвестного наперёд распределения (через count(1)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 12:47:33 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Alexiusлопата, <> ну и никто не запрещает ввести индексируемое поле и заполнять его при вставке каким-нибудь рандомным числом в заданном диапазоне. как бы помяхше в общем рандом -- он несправедливый. [Если мы его взяли не один раз а повторили 100 раз один результат.] как и хеш. справедливо только 1-1. и рендомная выборка из 1-1 -- как гарантии равновероятности исходов. а вы замораживаете несправедливость (различие весов) для всех последующих якобы "рендомных" выборок. что неверно. поэтому предварительный рендом, рендом по невыстроенному мн-ву с фиксированными дырками, рендом по хешу -- одинаково гарантируют неравновероятность единожды замороженную на мн-ве. То, что несправедливость получена (раз за разом) случайным образом -- оно конечно греет. того, кто от неё вкушает. Ага. честным это будет только если каждый раз вы начнете выбират заведомом произвольную "заморозку" (хеш ф-ю с проихвольными сдвигами, и т.п.) -- а это -- каждый раз -- фулл скан. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 12:56:50 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
хехехе на хабре этот малолетний далпайоп ещё и упирается, лять http://habrahabr.ru/post/242999/#comment_8129565 убивать, убивать , убивать ржавой лопатой только биореактор, только хардкор ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.11.2014, 18:36:07 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, А подскажите, как такие сложные рекурсивные запросы отлаживать? Мне в голову приходит только PL/pgSQL функция с `RAISE NOTICE` возвращающая константу, которую CROSS JOIN-ить в рекурсивной части. Вот только что ей на вход давать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.11.2014, 16:59:30 |
|
||
|
очередной велосипедист
|
|||
|---|---|---|---|
|
#18+
vyegorovMaxim Boguk, А подскажите, как такие сложные рекурсивные запросы отлаживать? Мне в голову приходит только PL/pgSQL функция с `RAISE NOTICE` возвращающая константу, которую CROSS JOIN-ить в рекурсивной части. Вот только что ей на вход давать?хотя там входит словцо recursive, никакой рекурсии нет, есть итерации (прямопроходные, а не обратный проход до корня, с возвратом), которые можно обрезать просто счетчиком итераций -- и смотреть за результатом. т.е. каждая итерация возвращает очередной "слайс" т.н. "working table", с этим слайсом "рекурсивно" (итеративно) делается UNION [ALL] - и результат поступает в следующую итерацию. И тоько в конце (т.е. в наружнем селекте) выплёвывается всё накопленное на итерациях. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.11.2014, 17:15:01 |
|
||
|
|

start [/forum/topic.php?all=1&fid=53&tid=1998334]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
207ms |
get topic data: |
14ms |
get forum data: |
4ms |
get page messages: |
99ms |
get tp. blocked users: |
1ms |
| others: | 232ms |
| total: | 588ms |

| 0 / 0 |
