Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянский (PostgreSQL-Consulting.com)

9,070 views

Published on

Вы взяли ваш любимый фреймворк™ и быстро запустили крутой проект, который раскручивается, приносит деньги и требует быстрого развития, чтобы оставить конкурентов далеко позади.

В один далеко не прекрасный момент вы понимаете, что корень всех зол - медленное время ответа базы данных, а ваш админ зло смотрит на разработчиков красными от бессонницы глазами и ругается на безумные запросы, которые генерирует ORM. Тот самый ORM, который позволил вам так быстро запустить ваш замечательный проект.

Знакомо? Тогда вам будет интересно послушать, как заставить вашу базу данных работать прямо сейчас. А именно:
- какое место в общей производительности базы данных занимает оптимизация запросов?
- когда прекращать “крутить гайки” и заниматься медленными запросами?
- что такое медленный запрос и когда их надо начинать оптимизировать?
- как оптимизировать?
- EXPLAIN, EXPLAIN ANALYZE - как читать и на что обращать внимание?
- как работает оптимизатор запросов PostgreSQL и где могут быть узкие места?
- для чего нужны и для чего не нужны индексы, методики индексирования, и как быть уверенным, что ваш индекс правильно используется?
- какие запросы не будут работать быстро никогда, и как с этим жить?
- ошибается ли оптимизатор и, если да, то почему и как его в таком случае призвать к порядку?

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянский (PostgreSQL-Consulting.com)

  1. 1. Производительность запросов в PostgreSQL - шаг за шагом Илья Космодемьянский ik@postgresql-consulting.com
  2. 2. План • Что значит оптимизировать запросы? • Когда начинать оптимизировать запросы? • Какие запросы оптимизировать? • Как оптимизировать запросы? • Какие запросы бесполезно оптимизировать?
  3. 3. Проблема не новая Обыкновенно в теории заботятся и считают хорошим достижением, если удается повысить коэффициент полезного действия винта на 4%, а практика показывает, что от механика, машинистов и кочегаров зависят не 4–5%, а 70–75%. Крылов А.Н. "Мои воспоминания"
  4. 4. Что значит оптимизировать запросы? • Задача редко ставится в такой форме
  5. 5. Что значит оптимизировать запросы? • Задача редко ставится в такой форме • «Всё плохо»- более типичная постановка
  6. 6. Что значит оптимизировать запросы? • Задача редко ставится в такой форме • «Всё плохо»- более типичная постановка • Медленные запросы просто видны наружу
  7. 7. Что значит оптимизировать запросы? • Задача редко ставится в такой форме • «Всё плохо»- более типичная постановка • Медленные запросы просто видны наружу • На ненастроенной базе запросы оптимизировать бесполезно
  8. 8. Что значит ненастроенная база? • Выключен или не настроен автовакуум • 100500 подключений без pgbouncer • ...
  9. 9. Алгоритм • Проверить настройки • Отобрать запросы для оптимизации • Оптимизировать запросы • Повторить
  10. 10. Какие запросы оптимизировать? • Все подряд - бесполезно • Отобрать top • pg_stat_statements
  11. 11. Изучаем top total time: 06:01:33 (IO: 1.15%) total queries: 896,507,876 (unique: 377) report for all databases, version 0.9.2 ============================================================================================================= pos:1 total time: 01:27:08 (24.1%, CPU: 24.4%, IO: 0.0%) calls: 1,038,397 (0.12%) avg_time: 5.03ms (IO: 0.0%) user: someuser db: somedb rows: 1,754,836 query: select q.id, q.type, q.servertime, q.clienttime from foo q left outer join bar qq ON q.buzzid = qq.buzzid where qq.yaid ============================================================================================================= pos:2 total time: 00:28:56 (8.0%, CPU: 8.1%, IO: 0.0%) calls: 120,782,681 (13.47%) avg_time: 0.01ms (IO: 0.0%) user: someuser db: somedb rows: 557,454,570 query: select seqid, id, name, notes from bar where pvid = $1 order by id asc https://github.com/PostgreSQL-Consulting/pg-utils/tree/master/sql/global_reports
  12. 12. Что такое "запрос работает медленно?" • Запрос работает 123,0 ms
  13. 13. Что такое "запрос работает медленно?" • Запрос работает 123,0 ms • Запрос работает 7300,0 ms
  14. 14. Что такое "запрос работает медленно?" • Запрос работает 123,0 ms • Запрос работает 7300,0 ms • Запрос работает 3 min
  15. 15. Что такое "запрос работает медленно?" • Запрос работает 123,0 ms • Запрос работает 7300,0 ms • Запрос работает 3 min • Запрос работает 0.12 ms
  16. 16. Более правильный подход • Как часто исполняется запрос
  17. 17. Более правильный подход • Как часто исполняется запрос • Какое время отклика мы считаем приемлемым
  18. 18. Более правильный подход • Как часто исполняется запрос • Какое время отклика мы считаем приемлемым • Каков характер нагрузки на базе?
  19. 19. Более правильный подход • Как часто исполняется запрос • Какое время отклика мы считаем приемлемым • Каков характер нагрузки на базе? • Какой процент ресурсов базы занимает данный запрос
  20. 20. На чем расходуется время при выполнении запроса • Передача запроса от клиента (НЕ СМЕШНО!)
  21. 21. На чем расходуется время при выполнении запроса • Передача запроса от клиента (НЕ СМЕШНО!) • Парсинг
  22. 22. На чем расходуется время при выполнении запроса • Передача запроса от клиента (НЕ СМЕШНО!) • Парсинг • Оптимизация
  23. 23. На чем расходуется время при выполнении запроса • Передача запроса от клиента (НЕ СМЕШНО!) • Парсинг • Оптимизация • Исполнение
  24. 24. На чем расходуется время при выполнении запроса • Передача запроса от клиента (НЕ СМЕШНО!) • Парсинг • Оптимизация • Исполнение • Возврат результатов
  25. 25. Передача запроса от клиента select id, name, from table id in(312,3443,543,4,76,13,78,98,090,435,565, 2317,1145,76777,23,5678,776,9869,3242,65645,2423,43221, 10,4545,320,59,298,405,47832,5497579,5349934,286438, 5489584,2737284728,43,7б,4б8,3,854,2094,3293826,4773, 394394,5720853,403059,84885,.................
  26. 26. EXPLAIN PREPARE query(int, int) AS SELECT sum(bar) FROM test WHERE id > $1 AND id < $2 GROUP BY foo; EXPLAIN ANALYZE EXECUTE query(100, 200); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------ HashAggregate (cost=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1) Group Key: foo -> Index Scan using test_pkey on test (cost=0.29..9.29 rows=50 width=8) (actual time=0.039..0.091 rows=99 loops=1) Index Cond: ((id > $1) AND (id < $2)) Planning time: 0.197 ms Execution time: 0.225 ms (6 rows) pg@pglect01:~/dellstore2-normal-1.0> psql dellstore2 -c ’explain (analyze on, buffers on) select count(*) from customers’ QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Aggregate (cost=738.00..738.01 rows=1 width=0) (actual time=8.357..8.357 rows=1 loops=1) Buffers: shared hit=488 -> Seq Scan on customers (cost=0.00..688.00 rows=20000 width=0) (actual time=0.026..5.728 rows=20000 loops=1) Buffers: shared hit=488 Total runtime: 8.607 ms (5 rows)
  27. 27. Почему не используетеся индекс? • Собрана-ли статистика? • Ускорит-ли индекс исполнение запроса? • Правильно-ли написан запрос? (where counter + 1 = 46)
  28. 28. Почему join работает медленно? • Какой тип используется? • Есть-ли индексы? • Достаточно-ли памяти?
  29. 29. Длинный IN (очень любят ORM) 1. SELECT * FROM test WHERE id<10000 1.2ms 2. SELECT * FROM test WHERE id<10000 AND val IN (список от 1 до 10) 2.1ms 3. SELECT * FROM test WHERE id<10000 AND val IN (список от 1 до 100) 6ms 4. SELECT * FROM test WHERE id<10000 AND val IN (список от 1 до 1000) 38ms 5. SELECT * FROM test WHERE id<10000 AND val IN (список от 1 до 10000) 380ms (и далее линейно от длинны массива)
  30. 30. IN (1,...100) explain analyze select * from test where id<10000 and val IN (1,...100); QUERY PLAN -------------------------------------------------------------------------------------------------- Index Scan using test_pkey on test (cost=0.43..1666.85 rows=10 width=140) (actual time=0.448..5.602 rows=16 loops=1) Index Cond: (id < 10000) Filter: (val = ANY (’{1,...100}’::integer[])) Rows Removed by Filter: 9984
  31. 31. Длинный IN (hash join) explain select count(*) from test JOIN (VALUES (1),...,(10)) AS v(val) USING (val) where id<10000; QUERY PLAN ------------------------------------------------------------------------ Aggregate (cost=497.65..497.66 rows=1 width=0) -> Hash Join (cost=0.69..497.65 rows=1 width=0) Hash Cond: (test.val = "*VALUES*".column1) -> Index Scan using test_pkey on test (cost=0.43..461.22 rows=9645 width=4) Index Cond: (id < 10000) -> Hash (cost=0.12..0.12 rows=10 width=4) -> Values Scan on "*VALUES*" (cost=0.00..0.12 rows=10 width=4)
  32. 32. Длинный IN (Итоги с hash join) 1. SELECT * FROM test WHERE id<10000 1.2ms 2. JOIN (VALUES (1),...,(10)) 1.6ms (было 2.1ms) 3. JOIN (VALUES (1),...,(100)) 2ms (было 6ms) 4. JOIN (VALUES (1),...,(1000)) 3.9ms (было 38ms) 5. JOIN (VALUES (1),...,(10000)) 10ms (было 380ms)
  33. 33. "Этот запрос не будет работать быстро никогда" • count(*) • join на 300 таблиц • Запрос возвращает клиенту 1 000 000 000 строк • Все это серьезные причины для переделки бизнес-логики
  34. 34. Вопросы? ik@postgresql-consulting.com

×