Что именно объясняет PostgreSQL?


116

Вывод объяснения MySQL довольно прост. PostgreSQL немного сложнее. Мне тоже не удалось найти хорошего ресурса, который бы это объяснял.

Вы можете описать, что именно объясняет, или хотя бы указать мне направление хорошего ресурса?

Ответы:


50

Explaining_EXPLAIN.pdf тоже может помочь.


65
Я озадачен, почему люди думают, что слайды - это хорошая техническая документация. Видеозапись выступления может быть полезна, но информационная плотность слайдов очень близка к нулю. На первых шести слайдах (1/5 от общего числа) есть ровно одно предложение технического содержания: «• EXPLAIN работает с любым DML, а не только с SELECT (т.е. UPDATE, DELETE и INSERT)». Мое самое большое недоразумение - это то, что означает «время запуска», и это нигде не объясняется на этих 30 слайдах.
Марк Э. Хаасе,

80

Что меня всегда смущало, так это соотношение стоимости запуска и общей стоимости. Я гуглю это каждый раз, когда забываю об этом, что возвращает меня сюда, но это не объясняет разницы, поэтому я пишу этот ответ. Это то, что я почерпнул из документации PostgresEXPLAIN , объяснил, как я это понимаю.

Вот пример из приложения, которое управляет форумом:

EXPLAIN SELECT * FROM post LIMIT 50;

Limit  (cost=0.00..3.39 rows=50 width=422)
  ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Вот графическое объяснение от PgAdmin:

графическое объяснение первого запроса

(Когда вы используете PgAdmin, вы можете навести указатель мыши на компонент, чтобы прочитать сведения о стоимости.)

Стоимость представлена в виде кортежа, например , затраты на LIMITэто cost=0.00..3.39и стоимость сканирования последовательно postнаходится cost=0.00..15629.12. Первое число в кортеже - это стоимость запуска, а второе число - общая стоимость . Поскольку я использовал, EXPLAINа не EXPLAIN ANALYZE, эти затраты являются приблизительными, а не фактическими мерами.

  • Стоимость запуска - понятие хитрое. Это не просто количество времени до запуска этого компонента . Он представляет собой промежуток времени между тем, когда компонент начинает выполнение (чтение данных) и когда компонент выводит свою первую строку .
  • Общая стоимость - это все время выполнения компонента, с момента начала чтения данных до завершения записи вывода.

Сложность заключается в том, что стоимость каждого «родительского» узла включает стоимость его дочерних узлов. В текстовом представлении дерево представлено отступом, например, LIMITявляется родительским узлом и Seq Scanего дочерним узлом . В представлении PgAdmin стрелки указывают от дочернего к родительскому (направление потока данных), что может показаться нелогичным, если вы знакомы с теорией графов.

В документации говорится, что затраты включают все дочерние узлы, но обратите внимание, что общая стоимость родительского узла 3.39намного меньше, чем общая стоимость его дочернего узла 15629.12. Общая стоимость не является исчерпывающей, потому что такой компонент, как LIMITне нужно обрабатывать весь ввод. См. EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2;Пример в документации PostgresEXPLAIN .

В приведенном выше примере время запуска равно нулю для обоих компонентов, потому что ни один из компонентов не должен выполнять какую-либо обработку перед началом записи строк: последовательное сканирование считывает первую строку таблицы и выдает ее. LIMITЧитает первую строку , а затем излучает его.

Когда компоненту потребуется выполнить большую обработку, прежде чем он сможет начать вывод каких-либо строк? Возможных причин множество, но давайте рассмотрим один наглядный пример. Вот тот же запрос, что и раньше, но теперь содержащий ORDER BYпредложение:

EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;

Limit  (cost=23283.24..23283.37 rows=50 width=422)
  ->  Sort  (cost=23283.24..23859.27 rows=230412 width=422)
        Sort Key: body
        ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

И графически:

графическое объяснение второго запроса

И снова последовательное сканирование postне требует затрат на запуск: оно начинает вывод строк немедленно. Но сортировка требует значительных начальных затрат, 23283.24поскольку она должна отсортировать всю таблицу, прежде чем она сможет вывести хотя бы одну строку . Общая стоимость сортировки 23859.27лишь немного превышает начальную стоимость, что отражает тот факт, что после сортировки всего набора данных отсортированные данные могут быть отправлены очень быстро.

Обратите внимание, что время запуска в LIMIT 23283.24точности равно времени запуска сортировки. Это не потому, что LIMITсам по себе имеет большое время запуска. На самом деле он сам по себе имеет нулевое время запуска, но EXPLAINсуммирует все дочерние затраты для каждого родителя, поэтомуLIMIT запуска включает общее время запуска его дочерних элементов.

Такое накопление затрат может затруднить понимание стоимости выполнения каждого отдельного компонента. Например, у нас LIMITнулевое время запуска, но на первый взгляд это не очевидно. По этой причине несколько других людей связались с объяснением.depesz.com , инструментом, созданным Хубертом Любачжевски (он же depesz), который помогает понять EXPLAIN, помимо прочего, вычитанием дочерних затрат из родительских затрат. Он упоминает о некоторых других сложностях в коротком сообщении в блоге о своем инструменте.


4
Спасибо тебе за это. Я также хотел бы добавить визуализатор объяснения, который еще лучше отображает результат (imo). tatiyants.com/pev
Джонатан Портер

Отличный ответ. И ваш комментарий о том, что начальная стоимость включает время до возврата первой строки, помог мне понять, почему начальная стоимость для сортировки не составляла всего 15629,12.
Джоэл Вигтон,

43

Он выполняется от самого большого к минимальному отступу, и я верю, что от основания плана до самого верха. (Таким образом, если есть два раздела с отступом, сначала выполняется один, расположенный ниже по странице, а затем, когда они встречаются, выполняется другое правило, соединяющее их.)

Идея состоит в том, что на каждом шаге есть 1 или 2 набора данных, которые поступают и обрабатываются по некоторому правилу. Если только один набор данных, эта операция выполняется с этим набором данных. (Например, просканируйте индекс, чтобы выяснить, какие строки вам нужны, отфильтруйте набор данных или отсортируйте его.) Если два, два набора данных - это две вещи, которые имеют больший отступ, и они объединяются по правилу, которое вы видите. Смысл большинства правил можно довольно легко угадать (особенно если вы уже читали кучу планов объяснения ранее), однако вы можете попробовать проверить отдельные элементы, просматривая документацию или (проще) просто вставляя фразу в Google вместе с несколькими ключевыми словами, например EXPLAIN.

Очевидно, что это не полное объяснение, но оно дает достаточно контекста, чтобы вы могли понять все, что захотите. Например, рассмотрим этот план из реальной базы данных:

explain analyze
select a.attributeid, a.attributevalue, b.productid
from orderitemattribute a, orderitem b
where a.orderid = b.orderid
and a.attributeid = 'display-album'
and b.productid = 'ModernBook';

------------------------------------------------------------------------------------------------------------------------------------------------------------

 Merge Join  (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1)
   Merge Cond: (a.orderid = b.orderid)
   ->  Sort  (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1)
         Sort Key: a.orderid
         Sort Method:  quicksort  Memory: 1695kB
         ->  Bitmap Heap Scan on orderitemattribute a  (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1)
               Recheck Cond: ((attributeid)::text = 'display-album'::text)
               ->  Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1)
                     Index Cond: ((attributeid)::text = 'display-album'::text)
   ->  Sort  (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1)
         Sort Key: b.orderid
         Sort Method:  quicksort  Memory: 76kB
         ->  Bitmap Heap Scan on orderitem b  (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1)
               Recheck Cond: ((productid)::text = 'ModernBook'::text)
               ->  Bitmap Index Scan on id_orderitem_productid  (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1)
                     Index Cond: ((productid)::text = 'ModernBook'::text)
 Total runtime: 842.134 ms
(17 rows)

Попробуйте прочитать его сами и посмотрите, есть ли в нем смысл.

Я прочитал, что база данных сначала сканирует id_orderitem_productidиндекс, используя его, чтобы найти нужные строки orderitem, затем сортирует этот набор данных с помощью быстрой сортировки (используемая сортировка изменится, если данные не помещаются в ОЗУ), а затем откладывает это в сторону.

Затем он сканирует, orditematt_attributeid_idxчтобы найти нужные строки, orderitemattributeа затем сортирует этот набор данных с помощью быстрой сортировки.

Затем он берет два набора данных и объединяет их. (Объединение слиянием - это своего рода операция «сжатия», при которой два отсортированных набора данных проходят параллельно, создавая объединенную строку, когда они совпадают.)

Как я уже сказал, вы продвигаетесь через внутреннюю часть плана к внешней, снизу вверх.


22

Также доступен онлайн-помощник Depesz , который поможет выделить наиболее дорогие части результатов анализа.

также есть один, вот те же результаты , которые для меня более ясны, в чем проблема.


20
Кажется, что manage-analyze.info не работает, но я согласен с тем, что execute.depesz.com очень полезен.
benvolioT 07

13

PgAdmin покажет вам графическое представление плана объяснения. Переключение между ними действительно может помочь вам понять, что означает текстовое представление. Однако, если вы просто хотите знать, что он собирается делать, вы можете всегда использовать графический интерфейс.



0

Если вы устанавливаете pgadmin, есть кнопка «Объяснить», которая, помимо вывода текста, рисует диаграммы того, что происходит, показывая фильтры, сортировки и слияния подмножеств, которые я считаю действительно полезными, чтобы увидеть, что происходит.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.