Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Здравствуйте Господа. Помогите чайнику оптимизировать запрос в PostgreSQL 8.1. Задача у меня усложняется тем что нет полной возможности менять текст приложения (т.е. сам SQL запрос) а хотелось путем настройки параметров базы и создания необходимых индексов увеличить производительность конкретного запроса. Почитал много веток по оптимизации в этом форуме помучился с индексами и кластеризацией таблиц - а результата практически нет. Есть 2 таблицы (привожу их в сокращенном виде) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Есть запрос от приложения который группирует платежи по дням за определенный период (например за месяц) - запрос тоже в обрезанном виде (хотя он и так 20 секунд вылолняется) Код: 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. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. индексы разные пробовал создавать - в delarpayment и по agent и по paymentid и совместный и кластерный по paymentid, делал отдельные поля year, month, day в таблице payment - Большого результата нет. Postgres shared_buffers = 3000 (с большим значением почему-то PG не запускается ),temp_buffers = 3000, work_mem = 4096, effective_cache_size = 6000. Машина вроде не сильно слабая - P4 3200 HT , 1Гиг RAM , SATA RAID, Linux 2.6 kernel. Сейчас планируется увеличение объема записей в таблицах и я с ужасом представляю что будет когда одновременно много пользвателей запустят этот отчет. На Windows при примерно тех же условиях результат чуть лучше, но все равно не впечатляет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2007, 09:50 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Ну по меньшей мере напрашиваються индексы по payment0_.datetime comissions1_.paymentid comissions1_.agent='xxx' extract(year from payment0_.datetime) extract(month from payment0_.datetime) extract(day from payment0_.datetime) Потом можно рассмотреть их комбинации (типа составные индексы) Есил в WHERE тут надо просто взять за какойто месац то с такими индексами можно писать Код: plaintext 1. Так как extract возвращает double precision можно еще и в индексах, и в запросе приводить к integer. И не забудьте стделать vacuum analyze P.S. Ну и, чисто отвлеченно, выходит так, что у вас тут нарушение 1НФ, потому как части даты вам нужны отдельно. Правда это еще спорно. И зачем вообще группировать и сортировать отдельно по году, месяцу, дню? Почему бы не сделать поле просто date и не группировать/сортировать по нему одному, а выводить (если это реально надо) части отдельно? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2007, 18:20 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Ну по меньшей мере напрашиваються индексы по payment0_.datetime Этот есть. comissions1_.paymentid Этот создавал , толку нет. comissions1_.agent='xxx' этот есть extract(year from payment0_.datetime) extract(month from payment0_.datetime) extract(day from payment0_.datetime) От этих индексов толку нет. Я делал отдельные поля year, month, day и исключал extract - не помогает. А вообще такой индекс не всегда создается я даже не понимаю почему - иногда выдает ошибку - functions in index expression must be marked IMMUTABLE Потом можно рассмотреть их комбинации (типа составные индексы) делал составной индекс по comissions1_.agent и comissions1_.paymentid - по ровну. Есил в WHERE тут надо просто взять за какойто месац то с такими индексами можно писать Так усложнится логика приложения потому что в один отчет может попасть нескольно месяцев и 2 года на стыке . И не забудьте стделать vacuum analyze каждый раз делаю P.S. Ну и, чисто отвлеченно, выходит так, что у вас тут нарушение 1НФ, потому как части даты вам нужны отдельно. Правда это еще спорно. И зачем вообще группировать и сортировать отдельно по году, месяцу, дню? Почему бы не сделать поле просто date и не группировать/сортировать по нему одному, а выводить (если это реально надо) части отдельно? Я же говорю что делал эти поля - выигрышь в быстродействии минимальный - основное время я так понял уходит на join таблиц payment и dealerpayment а не на работу с датами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2007, 21:05 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
akimovpделал составной индекс по comissions1_.agent и comissions1_.paymentid - по ровну.Приведите пожалуйста explain analyze при наличии индекса по (agent,paymentid). akimovpосновное время я так понял уходит на join таблиц payment и dealerpayment а не на работу с датами.14 секунд на сканирование таблицы dealerpayment -> Index Scan using dealerpayment_pid on dealerpayment comissions1_ (cost=0.00..32935.51 rows=305065 width=8) (actual time=18.016..13866.880 rows=288160 loops=1) akimovpиногда выдает ошибку - functions in index expression must be marked IMMUTABLEтолько по immutable-функциям можно строить индексы. см доку: CREATE INDEX CREATE FUNCTION ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2007, 11:38 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
LeXa NalBat akimovpделал составной индекс по comissions1_.agent и comissions1_.paymentid - по ровну.Приведите пожалуйста explain analyze при наличии индекса по (agent,paymentid). akimovpосновное время я так понял уходит на join таблиц payment и dealerpayment а не на работу с датами.14 секунд на сканирование таблицы dealerpayment -> Index Scan using dealerpayment_pid on dealerpayment comissions1_ (cost=0.00..32935.51 rows=305065 width=8) (actual time=18.016..13866.880 rows=288160 loops=1) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. akimovpиногда выдает ошибку - functions in index expression must be marked IMMUTABLE только по immutable-функциям можно строить индексы. см доку: CREATE INDEX CREATE FUNCTION Теперь разобрался. по timestamp with timezome extract получается не IMMUTABLE а по простому timestamp IMMUTABLE. Поэтому и сразу не понял почему то создается индекс extract то нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2007, 20:13 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
И еще. Если hash join отключить получается все гораздо веселей но индекс этот все равно не используется. Как же заставить одновременно и по dealerpayment.agent и по delerpayment.paymentid использовать индексы? Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2007, 20:23 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
akimovpиндекс этот все равно не используется. Как же заставить одновременно и по dealerpayment.agent и по delerpayment.paymentid использовать индексы?Должно работать. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. akimovpИ еще. Если hash join отключить получается все гораздо веселей -> Seq Scan on dealerpayment comissions1_ (cost=0.00..24608.53 rows=251616 width=8) (actual time=14.059..18613.972 rows=250203 loops=1) Filter: ((agent)::text = 'pinpay'::text) -> Seq Scan on dealerpayment comissions1_ (cost=0.00..24608.53 rows=251616 width=8) (actual time=0.063..2676.469 rows=250203 loops=1) Filter: ((agent)::text = 'pinpay'::text)Нет. Видимо это ошибка тестирования. Обратите внимание, одинаковые seqscan-ы (совпадают предположения планировщика, actual rows) выполняются разное время - 19 и 3 секунды. Возможно второй запрос выполнялся, когда ось/постгрес закэшировали данные с жесткого диска в память. При тестировании можно выполнять два одинаковых запроса подряд и смотреть на тайминги второго. Или шаманством очищать кэш в памяти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2007, 11:28 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Попробуй. Вряд ли намного быстрее, но всё же попробуй Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2007, 13:06 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
LeXa NalBat правильно говорит: нужен составной индекс по (agent,paymentid) или (paymentid, agent). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2007, 13:18 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatcreate index dealerpayment_agent_paymentid on dealerpayment ( agent, paymentid ); Такой индекс pg начинает использовать (хотя и непонятно почему мой первоначальный не нравился по тем же полям, может конечно я прогнал в прошлый раз). Но результат только немного лучше первоначального: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Bitmap Heap Scan on dealerpayment comissions1_ - занимает очень много времени. Похоже что он этот индекс только для фильтра agent='xxx' использует pg , а для comissions1_.paymentid=payment0_.id не использует. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2007, 21:45 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Funny_FalconПопробуй. Вряд ли намного быстрее, но всё же попробуй Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Вообще не заметил разницы. Да и не заставишь разработчиков вносить DB зависимые конструкции в SQL. Оригинальный SQL генерит ORM Hibernate. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2007, 21:54 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
автор Postgres shared_buffers = 3000 (с большим значением почему-то PG не запускается ),temp_buffers = 3000, work_mem = 4096, effective_cache_size = 6000. Может нужно ему памяти поднять? А то 327725 строк - это немало, а 3000*8Кб=24Мб - маловато-с. Да и остальные памяти - тоже было бы неплохо поднять. На счет PG не запускается -дык надо в ОСи разрешить больше шаред памяти использовать (что-то есть в доках, что-то на формуе). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 10:44 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Мда, прикинул 24Метра - совсем мало, в 8.2 по умолчанию идет 32. Желательно хотя бы до 100-150 метров поднять. Не поможет - попробовать до 300-400. И рабочую память тоже бы где-то до 100 метров. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 10:57 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Andrey DaeronМда, прикинул 24Метра - совсем мало, в 8.2 по умолчанию идет 32. Желательно хотя бы до 100-150 метров поднять. Не поможет - попробовать до 300-400. И рабочую память тоже бы где-то до 100 метров. Я могу ошибаться, но по-моему рабочую память (work_mem) до 100 метров - это бред. В доке сказано - этот размер может несколько раз выделиться для одного запроса - на каждый sort, join и т.д. Кто реально замечал разницу между 16MB workmem и 100MB, просветите меня глупого, я сам с такими значениями не игрался. Но даже если разница есть, по-моему лучше поднять её в отдельном коннекте/запросе (set work_mem = 100000; по-моему). А общего кэша (shared_buffers) и правда маловато. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 12:05 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Funny_Falcon Я могу ошибаться, но по-моему рабочую память (work_mem) до 100 метров - это бред. В доке сказано - этот размер может несколько раз выделиться для одного запроса - на каждый sort, join и т.д. Код: plaintext 1. Если для запросов не нужно больше 16Мб - то увеличение этого значения до 100Мб ситуацию не улучшит, но и ухудшить тоже не должно, за то если это значение является "бутылочным горлышком", то его увеличение может показать путь решения. ЗЫ У меня объем общего кеша = 160МБ для объемов в 1-2 милиона записей и группировке по ним. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 12:23 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Andrey DaeronЕсли для запросов не нужно больше 16Мб - то увеличение этого значения до 100Мб ситуацию не улучшит, но и ухудшить тоже не должно, за то если это значение является "бутылочным горлышком", то его увеличение может показать путь решения.Я верю, что теоретически это верно. Но хотелось бы узнать, сталкивался ли кто-нить с этим на практике: выиграл ли кто-нибудь от увеличения work_mem до 100Мб. Если есть такие, поделитесь, ваш опыт будет интересен всем. Andrey DaeronЗЫ У меня объем общего кеша = 160МБ для объемов в 1-2 милиона записей и группировке по ним.Общего кэша(shared_buffers) или work_mem? У меня общего кэша столько-же. Видимо это тот размер, когда нужные страницы индексов начинают умещаться в кэше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 12:44 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Funny_Falcon Andrey DaeronЗЫ У меня объем общего кеша = 160МБ для объемов в 1-2 милиона записей и группировке по ним.Общего кэша(shared_buffers) или work_mem? У меня общего кэша столько-же. Видимо это тот размер, когда нужные страницы индексов начинают умещаться в кэше. Общего кеша (shared_buffers). Work_mem у меня вообще был 200МБ. Попробую поковыряться, поуменьшать для определения минимально-нужных объемов. И, если получится, попробую сравнить по производительности с 8.2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 13:06 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Первоначальные данные устарели. Я уже разобрался с оганичением в OS. сейчас уже у меня стоит shared_buffers = 6000 temp_buffers = 3000 work_mem = 4096 effective_cache_size = 6000 Сегодня ночью попрообую еще увеличить эти значения и привести результат explain analyze. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 13:10 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
akimovpПервоначальные данные устарели. Я уже разобрался с оганичением в OS. сейчас уже у меня стоит shared_buffers = 6000 temp_buffers = 3000 work_mem = 4096 effective_cache_size = 6000 Сегодня ночью попрообую еще увеличить эти значения и привести результат explain analyze. Было бы интерестно посмотреть на время выполнения при: Код: plaintext 1. 2. 3. 4. Сразу максимум тоже ставить не кузяво - можно выпасть в swap, а это быстродействия не добавит :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 14:34 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Andrey DaeronБыло бы интерестно посмотреть на время выполнения при: Код: plaintext 1. 2. 3. 4. Привожу результаты. Проводил изменения всегда на 3 раз, все другие ресурсоемкие процесы загасил. shared_buffers=3000 work_mem=3000 Total runtime: 5223.187 ms shared_buffers=10000 work_mem=10000 Total runtime: 5119.872 ms shared_buffers=40000 work_mem=40000 Total runtime: 4624.605 ms Зависимость от shared_buffers при постоянном work_mem=10000 shared_buffers=3000 Total runtime: 5094.348 ms shared_buffers=30000 Total runtime: 4868.673 ms shared_buffers=60000 Total runtime: 4881.001 ms Зависимость от work_mem при постоянном shared_buffers=10000 work_mem=3000 Total runtime: 5118.737 ms work_mem=30000 Total runtime: 4863.079 ms Нормальная запуск всех необходимых приложений на сервере и запуск с параметрами shared_buffers=10000 work_mem=10000 Total runtime: 5957.512 ms В принципе какого-то кардинального влиния shared_buffers work_mem не видно (все в пределах 10%). Оставил их по 10000 и пошел спать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2007, 22:27 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
akimovp Andrey DaeronБыло бы интерестно посмотреть на время выполнения при: Код: plaintext 1. 2. 3. 4. Привожу результаты. Проводил изменения всегда на 3 раз, все другие ресурсоемкие процесы загасил. shared_buffers=3000 work_mem=3000 Total runtime: 5223.187 ms shared_buffers=10000 work_mem=10000 Total runtime: 5119.872 ms shared_buffers=40000 work_mem=40000 Total runtime: 4624.605 ms Зависимость от shared_buffers при постоянном work_mem=10000 shared_buffers=3000 Total runtime: 5094.348 ms shared_buffers=30000 Total runtime: 4868.673 ms shared_buffers=60000 Total runtime: 4881.001 ms Зависимость от work_mem при постоянном shared_buffers=10000 work_mem=3000 Total runtime: 5118.737 ms work_mem=30000 Total runtime: 4863.079 ms Нормальная запуск всех необходимых приложений на сервере и запуск с параметрами shared_buffers=10000 work_mem=10000 Total runtime: 5957.512 ms В принципе какого-то кардинального влиния shared_buffers work_mem не видно (все в пределах 10%). Оставил их по 10000 и пошел спать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.01.2007, 11:05 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
akimovp В принципе какого-то кардинального влиния shared_buffers work_mem не видно (все в пределах 10%). Оставил их по 10000 и пошел спать. Ну, на самом деле до 20% :) Можно еще глянуть на Код: plaintext 1. 2. 3. 4. И заодно: Код: plaintext 1. 2. 3. 4. 5. 6. Код: plaintext 1. 2. 3. 4. 5. 6. Я бы предложил следующие направления копания дальше: 1. Поиграться с партиционированием (должно сильно помочь). Плюсы - должно круто помочь, минусы - есть малость гемороя. 2. Написать в рассылку Постгреса pgsql-performance@postgresql.org. Плюсы - если там не помогут - нигде не помогут :) Минусы - иногда игнорируют, иногда аглицкого не хвататет для конструктивных диалогов. 3. Поставить 8.2 где-то слева и поигратся на нем - могет быть попустит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.01.2007, 12:23 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Andrey Daeron Можно еще глянуть на Код: plaintext 1. 2. 3. 4. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. И заодно: Код: plaintext 1. 2. 3. 4. 5. 6. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Код: plaintext 1. 2. 3. 4. 5. 6. Код: plaintext 1. 2. 3. 4. Я бы предложил следующие направления копания дальше: 1. Поиграться с партиционированием (должно сильно помочь). Плюсы - должно круто помочь, минусы - есть малость гемороя. Неохота иметь этот геморой. Тем более при этом придется менять код приложения - а это совсем тяжело и еще будет DB зависимые конструкции в нем. 2. Написать в рассылку Постгреса pgsql-performance@postgresql.org. Плюсы - если там не помогут - нигде не помогут :) Минусы - иногда игнорируют, иногда аглицкого не хвататет для конструктивных диалогов. Да написание понятных текстов на английском занимает у меня много времени. Я думаю будет лучше потратить это время на изучение доков по Oracle, установка его, перенос базы на него , тестирование - наверняка там таких проблем меньше будет. 3. Поставить 8.2 где-то слева и поигратся на нем - могет быть попустит. На Винде локально стоит 8.2, особого ускорения не наблюдаю по сравнения с 8.1 В любом случае спасибо за помощ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2007, 19:18 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
akimovp Да написание понятных текстов на английском занимает у меня много времени. Я думаю будет лучше потратить это время на изучение доков по Oracle, установка его, перенос базы на него , тестирование - наверняка там таких проблем меньше будет. В любом случае спасибо за помощ. Было бы очень интересно посмотреть на результат такого перехода, на сколько стало лучше и за счет чего. Впрочем на ответ из мейллиста Постгреса тоже. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2007, 19:53 |
|
||
|
опять оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Andrey DaeronБыло бы очень интересно посмотреть на результат такого перехода, на сколько стало лучше и за счет чего. Обязательно напишу о результате такого перехода, только вот быстро ли он получитсся - не знаю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2007, 21:27 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=34250205&tid=2005780]: |
0ms |
get settings: |
10ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
59ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
56ms |
get tp. blocked users: |
2ms |
| others: | 263ms |
| total: | 426ms |

| 0 / 0 |
