Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
такая ситуация: есть две таблицы (аналог для приходных или расходных накладных/счетов) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. заполняю таблицы: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. сильно смущает "Filter: (name = 'name44'::text)" и "Filter: (((dt)::timestamp with time zone >= (now() - '00:30:00'::interval)) AND ((dt)::timestamp with time zone <= (now() - '00:10:00'::interval)))" хотелось бы использовать индексы в данном случае. собственно, вопрос: как это сделать и на сколько вообще это реально (обойтись одними вьюхами)? за год накапливается около сотни тысяч накладных. выгребать их раньше чем через 5 лет крайне не желательно. з.ы. сейчас гоняю все это дело на рабочей машине. стоит Код: plaintext 1. 2. 3. з.з.ы. время такой выборки с любыми условиями должно быть не более секунды при максимальной заполненности базы ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 14:00 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
Дык эта, если поиск идёт по 2 полям одновременно, сделай индекс по двум полям сразу. Причём в обих таблицах это надо сделать. В pwb по (spl_id, dt) В pwr по (pwb_id, name) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 14:35 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
Гм. Вопрос про другое был. :-) В Постгресе представления не индексируются и не "материализуются", отсюда надо и плясать. Если запрос на котором основано представление достаточно оптимизирован, то представления хватит, но если запрос тяжёлый, а данные не сильно часто изменяются, то прийдётся делать материализированое(индексированое) "представление". То есть создавать таблицу, которая будет заполняться с помощью триггеров. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 14:43 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
mwolfДык эта, если поиск идёт по 2 полям одновременно, сделай индекс по двум полям сразу. Причём в обих таблицах это надо сделать. В pwb по (spl_id, dt) В pwr по (pwb_id, name)оп... точно %)) виноват, дурак, исправлюсь ;) напрочь забыл %) немного помогло:EXPLAIN ANALYZE select * from pwr where pwb_id in (select id from pwb where spl_id=4 and dt between (now()-'200 minute'::interval) and (now()-'0 minute'::interval)) and name='name44'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=2931.36..4188.21 rows=1 width=36) (actual time=187.951..645.679 rows=98 loops=1) -> HashAggregate (cost=2931.36..2931.36 rows=6 width=4) (actual time=183.515..208.794 rows=10316 loops=1) -> Index Scan using pwb_spl_id_ind on pwb (cost=0.00..2931.35 rows=6 width=4) (actual time=0.353..159.445 rows=10316 loops=1) Index Cond: (spl_id = 4) Filter: (((dt)::timestamp with time zone >= (now() - '03:20:00'::interval)) AND ((dt)::timestamp with time zone <= (now() - '00:00:00'::interval))) -> Index Scan using pwr_pwb_id_name_ind on pwr (cost=0.00..208.83 rows=52 width=36) (actual time=0.039..0.039 rows=0 loops=10316) Index Cond: ((pwr.pwb_id = "outer".id) AND (pwr.name = 'name44'::text)) Total runtime: 646.215 ms(хотя, время увеличилось. может, надо неиспользуемые индексы грохнуть?) правда, по timestamp все равно, фильтр гоняет. вот что с ним можно сделать, чтоб не было такого? mwolfВ Постгресе представления не индексируются и не "материализуются", отсюда надо и плясать. Если запрос на котором основано представление достаточно оптимизирован, то представления хватит, но если запрос тяжёлый, а данные не сильно часто изменяются, то прийдётся делать материализированое(индексированое) "представление". То есть создавать таблицу, которая будет заполняться с помощью триггеров.тут полностью согласен, но стоит учесть и такой момент: индексы-то лежат в "материализованном" виде. да и заполняться он будет по быстрее чем обычная табличка через ХР в триггере. в общем-то именно от этого и отталкиваюсь. т.е. хотелось бы построить индексы, по которым будут идти все эти выборки ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 15:09 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
mwolfВ Постгресе представления не индексируются и не "материализуются", отсюда надо и плясать.пардон, читать разучился %) т.е. не на ту мысль ответил. собственно, я об этом и говорю. очень хочется построить индексы на все возможные тяжелые запросы и использовать вьюхи с этими запросами. вопрос именно в том, как именно проиндексировать и в каких случаях (если они есть) этот подход не поможет? з.ы. пардон за очетяпки и косноязычие, бошка уже кругом идет от работы ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 15:33 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
Жёстка. Время увеличилось в полтора раза!!! Однако нездоровая какаято хрень наблюдается((( Ну с первым циклом ясно - индекс по одному ИД оказывается выгоднее, чем по имени-дате. Почему так - не понятно. Попробуй подправить так between (now()-'200 minute'::interval)::timestamp with time zone and (now()-'0 minute'::interval))::timestamp with time zone Со вторым циклом вообще интересно: в первом случае pwr_pwb_id_ind on pwr (cost=0.00..17.08 rows=1 width=36) (actual time=0.086..0.086 rows=0 loops=3601) во втором pwr_pwb_id_name_ind on pwr (cost=0.00..208.83 rows=52 width=36) (actual time=0.039..0.039 rows=0 loops=10316) Зачем он выбрал план с большей стимостью? Блин, а что такое loops честно говоря забыл. Мож таблицы переанализировать попробовать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 15:43 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
URIXFilter: (((dt)::timestamp with time zone >= (now() - '03:20:00'::interval)) AND ((dt)::timestamp with time zone <= (now() - '00:00:00'::interval)))Видимо индекс на таблицу pwb надо дополнить полем (dt)::timestamp with time zone, или в запросе приводить (now() - '...'::interval) к типу timestamp. Попробуйте запрос select * from pwr where name='name44' and exists ( select 1 from pwb where spl_id=4 and id=pwb_id and dt between (now()-'200 minute'::interval) and (now()-'0 minute'::interval) ) с использованием индекса по pwb(spl_id,id,dt::timestamp with time zone). Приведите пожалуйста explain analyze. mwolfЖёстка. Время увеличилось в полтора раза!!!Неудивительно потому что в первом и втором тестах не совпадают значения now() и '30 minute'::interval, '10 minute'::interval с '200 minute'::interval, '0 minute'::interval. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 15:51 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
сделал все вакуумы, аналайзы и пр. поставил фиксированное время без единого индекса: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. create index pwb_spl_id_dt_ind on pwb(spl_id,id,dt); (тип подставить не дает) create index pwr_pwb_id_name_ind on pwr(pwb_id,name); Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 16:27 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
блин, это я уже сам туплю %) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 16:47 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
С 460.957 ms до 115.498 ms. Уже хорошо. Теперь вместо констант ставь выражение с приведением типов и всё будет ок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.06.2005, 16:59 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
mwolfС 460.957 ms до 115.498 ms. Уже хорошо. Теперь вместо констант ставь выражение с приведением типов и всё будет ок.имхо, выражение в таких случаях ставить нельзя, иначе на каждом loop он будет его вычислять. надо либо переменную ставить, либо (select <выражение>) mwolfБлин, а что такое loops честно говоря забылесли я правильно понял, это число джоинов с результатом подзапроса ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2005, 10:54 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
URIX mwolfС 460.957 ms до 115.498 ms. Уже хорошо. Теперь вместо констант ставь выражение с приведением типов и всё будет ок.имхо, выражение в таких случаях ставить нельзя, иначе на каждом loop он будет его вычислять. надо либо переменную ставить, либо (select <выражение>)Можно ставить выражение с приведением типа в это место при этом плане выполнения. Оно будет вычисляться один раз, как и выражение без приведения. :) URIX mwolfБлин, а что такое loops честно говоря забылесли я правильно понял, это число джоинов с результатом подзапросаСколько раз выполняется данная ветка. То есть в вашем примере 'Index Scan using pwr_pwb_id_name_ind on pwr' выполняется 2207 раз для разных значений "outer".id (pwb.id). Почему вы не попробовали exists? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2005, 11:10 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
LeXa NalBat Почему вы не попробовали exists? да и джойн там прокатывает, кажисть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2005, 11:17 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatПочему вы не попробовали exists?забыл, если честно %) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2005, 11:25 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
оп.... еще интереснее ;)) добавил индексы, чтоб с exist проверить. получилось: Код: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2005, 11:34 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. loops=2093 - Я ожидал, что это число будет намного меньше, чем 2207. :( Поэтому exists наверное можно более не пробовать, а попытать различные джоины, как сказал 4321. Но приведитете еще пожалуйста статистику (в первом и втором запросе наверное получится 2207, в третьем - 2093, а сколько в четвертом?): select count(*) from pwb where spl_id=4 and dt between ('2005-06-30 12:40'::timestamp) and ('2005-06-30 12:50'::timestamp); select count(distinct id) from pwb where spl_id=4 and dt between ('2005-06-30 12:40'::timestamp) and ('2005-06-30 12:50'::timestamp); select count(*) from pwr where name='name44'; select count(distinct pwb_id) from pwr where name='name44'; Джоины типа такие EXPLAIN ANALYZE select [distinct] * from pwr join pwb on (id=pwb_id) where name='name44' and spl_id=4 and dt between ('2005-06-30 12:40'::timestamp) and ('2005-06-30 12:50'::timestamp); с различными установками set_enable_*_join to [on,off] и созданными нужными индексами. :) URIXкстати, вариант без exists, по идее, лучше. все таки, там один раз выбирается подзапрос, т.к. в него не передается параметров из внешнего запросаДа, наличие subplan - не лучший вариант. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2005, 12:19 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
алгоритм заполнения таблиц есть в первом посте. на самом деле, я там немного слукавил относительно "(1 .. 200000)": было "(1 .. 300000)", но после 200000 оборвал, т.к. надоело ждать Код: 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. 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. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2005, 14:41 |
|
||
|
вьюха вместо триггеров
|
|||
|---|---|---|---|
|
#18+
URIXалгоритм заполнения таблиц есть в первом постеО! Слона то я только сейчас заметил. :( То есть вы пробуете не на реальных данных, а на тестовых сгенеренных автоматически. Тогда важно чтобы распределения значений в тестовых данных были похожи (напрмер отличались не более чем в 3-10 раз, а чем отличие меньше, тем лучше:) на реальные распределения. Иначе на реальных данных планы могут оказаться другими. В реальных данных у вас: ~ 200 000 pwb.id? ~ 20 различных spl_id, каждому из которых в среднем соответствует 10 000 pwb.id? ~ 1 000 различных name, каждому из которых соотв. в среднем 2 000 pwb.id? URIXпосле 200000 оборвал, т.к. надоело ждатьЭтот скрипт наверное будет работать в несколько раз быстрее, если сделать autocommit => 0, и делать коммит например через каждые 1 000 строк $i. URIX... Merge Join ... 101.921 ms 100.266 ms ... Hash Join ... 92.734 ms 92.831 ms ... Merge Join ... 102.658 ms 100.814 ms ... Nested Loop ... 154.135 ms 154.307 msИ примерно такое же время парой постов раньше вы получили для Hash IN Join: 92.701 ms. Наверное можно сделать вывод, что ~100 ms на этой выборке - это и есть тот результат, котороого хотели добиться. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2005, 10:20 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=33144580&tid=2007144]: |
0ms |
get settings: |
10ms |
get forum list: |
20ms |
check forum access: |
3ms |
check topic access: |
4ms |
track hit: |
136ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
72ms |
get tp. blocked users: |
2ms |
| others: | 281ms |
| total: | 542ms |

| 0 / 0 |
