|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm, я подозреваю что нужно аналогично добавить собираемой статистики по полю tag_id, раз планер ошибается в оценке. по приведенным планам правда не понятно, они все без analyze, кроме последнего. для тестов отключать enable_* параметры очень полезно чтобы перебрать планы для фиксированного запроса и разобраться. на практике это обычно крайняя мера, когда по-другому совсем никак, что бывает редко. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2016, 18:10 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
Alexiusmaxxstorm, я подозреваю что нужно аналогично добавить собираемой статистики по полю tag_id, раз планер ошибается в оценке. по приведенным планам правда не понятно, они все без analyze, кроме последнего. для тестов отключать enable_* параметры очень полезно чтобы перебрать планы для фиксированного запроса и разобраться. на практике это обычно крайняя мера, когда по-другому совсем никак, что бывает редко. Добавил статистики по полю tag_ig также до 1000. Отключил enable_bitmapscan. Вот что получается: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Почему он пытается агрегировать? ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2016, 11:20 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
Отключаю enable_hashagg, получается еще интереснее: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2016, 11:21 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm, Надо же не просто план смотреть, а время, сколько занимает исполнение запроса с таким планом, и кол-во буферов. EXPLAIN (analyze, buffers) ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2016, 12:02 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm Почему он пытается агрегировать? патамушта каунт -- агрегатная ф--я. приведите сам запрос еще раз, а то последнее : Код: plaintext
наводят на мысли о наличии count(distinct ...) ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2016, 12:49 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
qwwqmaxxstormПочему он пытается агрегировать? патамушта каунт -- агрегатная ф--я. приведите сам запрос еще раз, а то последнее : Код: plaintext
наводят на мысли о наличии count(distinct ...) Код: sql 1. 2. 3.
Я понимаю, что функция агрегатная, но почему иногда по индексу идет, а иногда битмап хип скан/агрегейт? Индекс (material_id, tag_id) не уникален, так как значения могут повторяться(несколько одинаковых тегов на один материал). Из-за этого? ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2016, 12:53 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
vyegorovmaxxstorm, Надо же не просто план смотреть, а время, сколько занимает исполнение запроса с таким планом, и кол-во буферов. EXPLAIN (analyze, buffers) Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
Статистика по полю material_id 1000, но все равно ошибается планировщик. Почему? ... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2016, 11:19 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm, покажите результаты выполнения запроса: Код: sql 1.
я правильно понял, что в san_materialdata 110М строк и среди них 6М уникальных material_id ? после того, как добавлялась статистика, analyze san_materialdata делался? ... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2016, 21:10 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
Alexiusmaxxstorm, покажите результаты выполнения запроса: Код: sql 1.
я правильно понял, что в san_materialdata 110М строк и среди них 6М уникальных material_id ? после того, как добавлялась статистика, analyze san_materialdata делался? Результат выполнения: 3.31129e+06 В san_materialdata порядка 150М строк и уникальных material_id 10М. analyze san_materialdata делался, в том числе и автоматически каждую ночь делается. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 09:32 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm, А можно вывод такого запроса глянуть: Код: sql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 12:19 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
vyegorovmaxxstorm, А можно вывод такого запроса глянуть: Код: sql 1.
"material_id"; 0;3.31129e+06; 0.719951 "tag_id"; 0;137; -0.0315493 ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 12:20 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
qwwqприведите сам запрос еще раз, а то последнее : Код: plaintext
наводят на мысли о наличии count(distinct ...) Оптимизатор понимает, что ему достаточно выдать уникальные значения и рассматривает `GROUP BY` по подзапросу. И судя по всему он находит его привлекательным, даже с отключенным HashAgg. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 12:51 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstormРезультат выполнения: 3.31129e+06 В san_materialdata порядка 150М строк и уникальных material_id 10М. analyze san_materialdata делался, в том числе и автоматически каждую ночь делается. не сходится что-то оценка планировщика с ожидаемой в строке с HashAggregate. а можно вывод запросов Код: sql 1. 2.
для каждой строки из san_material есть соответствующая запись в san_materialdata ? ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 13:15 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
Alexius, и еще раз план последнего запроса на всякий случай (можно без analyze), может n_distinct изменился и поэтому не сходится. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 13:17 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
Alexius не сходится что-то оценка планировщика с ожидаемой в строке с HashAggregate. а можно вывод запросов Код: sql 1. 2.
для каждой строки из san_material есть соответствующая запись в san_materialdata ? "Seq Scan on san_materialdata (cost=0.00..3704419.36 rows=167943136 width=62)" "Seq Scan on san_material (cost=0.00..2623611.56 rows=12420256 width=1129)" Не для каждой строки есть запись. Могут быть записи в san_material без тегов(записей в san_materialdata) ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 13:18 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
AlexiusAlexius, и еще раз план последнего запроса на всякий случай (можно без analyze), может n_distinct изменился и поэтому не сходится. Сделал еще раз analyze san_materialdata, теперь n_distinct немного поменялся: Код: sql 1. 2.
Старый запрос(за 1 день) идет теперь по индексу: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
однако, если взять интервал за 2 дня, то картина та же: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 13:51 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm, Ну... n_distinct в 5 раз меньше стал, это много! И теперь расчёты совпадают. Вы ловите неприятный эффект того, что планировщик не знает о том, что `san_material.material_id` и `san_material.detection_datetime` коррелируют. Тут несколько вариантов как "вправить мозг": - `CREATE INDEX CONCURRENTLY i_san_materialdata_tag_n_id ON san_materialdata(tag_id, material_id)` -- чтобы подзапрос быстрее отрабатывал и лучше планировался. - `CREATE INDEX CONCURRENTLY i_san_material_dtime_id ON san_material(detection_time, id)` -- планировщик сможет точнее оценить кол-во ID-шек в заданном диапазоне дат и не идти по ПК (да и IOS может выйти) - `CREATE INDEX CONCURRENTLY i_san_material_id_dtime ON san_material(id, detection_time)` -- так корректнее, поскольку диапазоны надо ставить в конце (дата обычно на больше-меньше проверяется, id -- на соответствие). ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 15:23 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
vyegorovmaxxstorm, Ну... n_distinct в 5 раз меньше стал, это много! И теперь расчёты совпадают. Вы ловите неприятный эффект того, что планировщик не знает о том, что `san_material.material_id` и `san_material.detection_datetime` коррелируют. Тут несколько вариантов как "вправить мозг": - `CREATE INDEX CONCURRENTLY i_san_materialdata_tag_n_id ON san_materialdata(tag_id, material_id)` -- чтобы подзапрос быстрее отрабатывал и лучше планировался. - `CREATE INDEX CONCURRENTLY i_san_material_dtime_id ON san_material(detection_time, id)` -- планировщик сможет точнее оценить кол-во ID-шек в заданном диапазоне дат и не идти по ПК (да и IOS может выйти) - `CREATE INDEX CONCURRENTLY i_san_material_id_dtime ON san_material(id, detection_time)` -- так корректнее, поскольку диапазоны надо ставить в конце (дата обычно на больше-меньше проверяется, id -- на соответствие). Первый индекс уже есть, а вот второй надо попробовать. Однако, щас другая проблема, один и тот же запрос отрабатывает с большой разницей по времени, когда читает с диска и из шаред буфера: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Неужели прочитать с диска 10521 блоков занимает 22 секунды? ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 16:04 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
vyegorovmaxxstorm, Ну... n_distinct в 5 раз меньше стал, это много! И теперь расчёты совпадают. Вы ловите неприятный эффект того, что планировщик не знает о том, что `san_material.material_id` и `san_material.detection_datetime` коррелируют. Тут несколько вариантов как "вправить мозг": - `CREATE INDEX CONCURRENTLY i_san_materialdata_tag_n_id ON san_materialdata(tag_id, material_id)` -- чтобы подзапрос быстрее отрабатывал и лучше планировался. - `CREATE INDEX CONCURRENTLY i_san_material_dtime_id ON san_material(detection_time, id)` -- планировщик сможет точнее оценить кол-во ID-шек в заданном диапазоне дат и не идти по ПК (да и IOS может выйти) - `CREATE INDEX CONCURRENTLY i_san_material_id_dtime ON san_material(id, detection_time)` -- так корректнее, поскольку диапазоны надо ставить в конце (дата обычно на больше-меньше проверяется, id -- на соответствие). Вот здесь время равно ошибка планировщика в HashAggregate 677909 строк вместо ожидаемых 4575: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 16:14 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstormvyegorovmaxxstorm, Ну... n_distinct в 5 раз меньше стал, это много! И теперь расчёты совпадают. Вы ловите неприятный эффект того, что планировщик не знает о том, что `san_material.material_id` и `san_material.detection_datetime` коррелируют. Тут несколько вариантов как "вправить мозг": - `CREATE INDEX CONCURRENTLY i_san_materialdata_tag_n_id ON san_materialdata(tag_id, material_id)` -- чтобы подзапрос быстрее отрабатывал и лучше планировался. - `CREATE INDEX CONCURRENTLY i_san_material_dtime_id ON san_material(detection_time, id)` -- планировщик сможет точнее оценить кол-во ID-шек в заданном диапазоне дат и не идти по ПК (да и IOS может выйти) - `CREATE INDEX CONCURRENTLY i_san_material_id_dtime ON san_material(id, detection_time)` -- так корректнее, поскольку диапазоны надо ставить в конце (дата обычно на больше-меньше проверяется, id -- на соответствие). Первый индекс уже есть, а вот второй надо попробовать. Однако, щас другая проблема, один и тот же запрос отрабатывает с большой разницей по времени, когда читает с диска и из шаред буфера: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Неужели прочитать с диска 10521 блоков занимает 22 секунды? Если у вас не ssd а механика то у вас в лучшем случае 15.000RPM диски а скорее всего 10.000RPM... максимум что можно с такого диска иметь это 200-250 случайных чтений в секунду, так что 22 секунды - еще приличный вполне результат (могло быть и в 2-3 раза медленнее легко). ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 16:15 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstormВот здесь время равно ошибка планировщика в HashAggregate 677909 строк вместо ожидаемых 4575: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
А ПЖ не может (пока, надеюсь) увидеть корреляцию. У `san_materialdata.material_id` 650k уникальных значений. А из таблицы, по предикату `tag_id=602` выбирается 0.7% записей. Вот база и берёт эти самые 0.7% от 650k. И очень неловко, что по факту попадают... все, и даже чуть больше. Кстати, вопрос -- почему HashAgg возвращает больше, чем n_distinct?.. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 16:52 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstormВот здесь время равно ошибка планировщика в HashAggregate 677909 строк вместо ожидаемых 4575: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
есть 2 варианта как это исправить. проблема в том, что на большой таблице сложно корректно оценить число различных значений поля (n_distinct) в некоторых случаях по небольшой выборке, которую делает analyze. 1) можно увеличить stats target для поля material_id еще больше, до 5000 или максимума 10000. минусы: analyze будет дольше (но это обычно не проблема), планирование запросов с этим полем может быть дольше - это может быть в некоторых случаях критично, если например есть много простых быстрых запросов с этой таблицей. 2) подсчитать действительное число различных material_id в этой таблице Код: sql 1.
таким запросом скорей всего будет быстрее (если там будет hashaggregate. стоит предварительно убедиться в этом и если нет - то увеличить work_mem в сессии). далее разделить его на 167943136 или сколько к тому моменту будет строк в таблице. и прописать полученное значение со знаком минус через alter table san_materialdata alter column material_id set (n_distinct = x); знак минус тут говорит планировщику что у нас не число различных значений, а отношение числа уникальных значений к общему числу строк. вполне вероятно что это соотношение в будущем не будет сильно меняться и достаточно его таким образом один раз "прибить гвоздями". ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2016, 20:15 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
Maxim BogukЕсли у вас не ssd а механика то у вас в лучшем случае 15.000RPM диски а скорее всего 10.000RPM... максимум что можно с такого диска иметь это 200-250 случайных чтений в секунду, так что 22 секунды - еще приличный вполне результат (могло быть и в 2-3 раза медленнее легко). Не поверю, что чтобы прочитать 90000 строк из индекса, понадобится 365 секунд: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
dirtied это что за блоки? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2016, 09:06 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm, База читает не по-строчно, а по-блочно. Было `read=275479` произвольных обращений к диску. Чтобы точно знать время IO операций, можно включить `track_io_timing=on`, тогда в плане будет видно реальное время работы с дисками. `dirtied` значит, что ваш запрос должен был "подчищать" за другими запросами, проставля hint bits в записях. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2016, 10:01 |
|
Тяжелый запрос к связанным таблицам
|
|||
---|---|---|---|
#18+
maxxstorm Не поверю, что чтобы прочитать 90000 строк из индекса, понадобится 365 секунд: если базе придется читать 90000 строк из маленькой таблички на 90 000--900 000 строк, то она просто забьёт на индексы и прочитает табличку последовательным доступом. т.е. относительно быстро. и отфильтрует. если же ей придется читать 90000 "по индексу" (из большой реально таблички, которую последовательно читать дорого) -- то это будет уже произвольный доступ. и , в случае механики, "чюдес не бываит" -- вряд ли блоки окажутся расположены так удачно, что затраты на полоборота диска куда--то все пропадут. только если только что что--то типа "кластер" было вдоль этого индекса сказано. и выборка подряд вдоль кластерного индекса. ну и если записей на блок много приходится и коэффициент перекрытия случится удачный (т.е. придется читать физически много меньше 90000 блоков)-- случится экономия в числе доступов (позиционировании головы). к тому же "по индексу", но "с доступом к самим записям" -- это несколько дороже, чем "только по индексу" -- там как бе 2 отдельные физические реляции получаются. и к обеим -- физически доступаться. зы. скоро обещают x--память, или как её -- скоро про механический доступ можно будет не вспоминать ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2016, 10:36 |
|
|
start [/forum/topic.php?fid=53&msg=39359439&tid=1996781]: |
0ms |
get settings: |
7ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
41ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
others: | 16ms |
total: | 156ms |
0 / 0 |