Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

Половин година назад представихме explain.tensor.ru — публичен сервиз за анализ и визуализация на плановете на заявките към PostgreSQL.

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

През последните месеци направихме доклад за него на PGConf.Russia 2020, подготвихме обобщаваща статия за ускоряване на SQL заявки на базата на препоръките, които той предоставя… но най-важното е, че събирахме вашите отзиви и наблюдавахме реални случаи на уп Usage.

И сега сме готови да ви разкажем за новите възможности, с които можете да се възползвате.

Поддръжка на различни формати на планове

План от лог, заедно с заявката

Пряко от конзолата выделяме целия блок, започвайки от реда с Query Text, с всички водещи интервали:

        Query Text: INSERT INTO dicquery_20200604 VALUES ($1.*) ON CONFLICT (query)
                           DO NOTHING;
        Insert on dicquery_20200604 (cost=0.00..0.05 rows=1 width=52) (actual time=40.376..40.376 rows=0 loops=1)
          Conflict Resolution: NOTHING
          Conflict Arbiter Indexes: dicquery_20200604_pkey
          Tuples Inserted: 1
          Conflicting Tuples: 0
          Buffers: shared hit=9 read=1 dirtied=1
          ->  Result (cost=0.00..0.05 rows=1 width=52) (actual time=0.001..0.001 rows=1 loops=1)

… и качваме всичко копирано направо в полето за план, без разделяне:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

На изхода получаваме бонус към разбираемия план и вкладка „контекст“, където нашата заявка е представена в цялата си прелест:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

JSON и YAML

EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT * FROM pg_class;

"[
  {
    "Plan": {
      "Node Type": "Seq Scan",
      "Parallel Aware": false,
      "Relation Name": "pg_class",
      "Alias": "pg_class",
      "Startup Cost": 0.00,
      "Total Cost": 1336.20,
      "Plan Rows": 13804,
      "Plan Width": 539,
      "Actual Startup Time": 0.006,
      "Actual Total Time": 1.838,
      "Actual Rows": 10266,
      "Actual Loops": 1,
      "Shared Hit Blocks": 646,
      "Shared Read Blocks": 0,
      "Shared Dirtied Blocks": 0,
      "Shared Written Blocks": 0,
      "Local Hit Blocks": 0,
      "Local Read Blocks": 0,
      "Local Dirtied Blocks": 0,
      "Local Written Blocks": 0,
      "Temp Read Blocks": 0,
      "Temp Written Blocks": 0
    },
    "Planning Time": 5.135,
    "Triggers": [
    ],
    "Execution Time": 2.389
  }
]"

Независимо дали с външни кавички, както копира pgAdmin, или без — качваме в същото поле, на изхода — красота:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

Разширена визуализация

Планирано време / Време за изпълнение

Сега е по-ясно къде е отишло допълнителното време при изпълнението на заявката:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

I/O Timing

Понякога се налага да се сблъскваме със ситуация, в която изглежда, че не е използвано твърде много ресурси в плана, но времето за изпълнение е неоснователно голямо.

Тук се налага да кажем: "О, вероятно в този момент дискът на сървъра е бил твърде натоварен, затова четенето е отнело толкова дълго!" Но това не е много точно…

Но може да се определи абсолютно точно. Факт е, че сред опциите за настройка на PG-сървъра има track_io_timing:

Включва меренето на времето за операции с вход/изход. Тази настройка по подразбиране е деактивирана, тъй като тя изисква постоянно запитване на текущото време от операционната система, което може значително да забави работата на някои платформи. За оценка на разходите за мерене на времето на вашата платформа можете да използвате утилитата pg_test_timing. Статистиката за вход/изход може да бъде получена чрез представянето pg_stat_database, в изхода на EXPLAIN (когато се използва настройката BUFFERS) и чрез представянето pg_stat_statements.

Тази настройка може да се активира и в рамките на локална сесия:

SET track_io_timing = TRUE;

Но сега идва най-приятното — научихме се да разбираме и показваме тези данни с оглед на всички трансформации на изпълнителното дърво:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

Тук може да се забележи, че от 0.790ms общо време за изпълнение 0.718ms е отнело четенето на една страница данни, 0.044ms — записването ѝ, а за цялата останала полезна активност са изразходвани само 0.028ms!

Бъдещето с PostgreSQL 13

Можете да се запознаете с пълния преглед на нововъведенията в подробната статия, а ние конкретно ще разгледаме промените в плановете.

Планиращи буфери

Отчитането на ресурсите, отделени за планиращия, намери отражение и в друг патч, който не е свързан с pg_stat_statements. EXPLAIN с опция BUFFERS ще информира за броя на буферите, използвани на етапа на планиране:

 Seq Scan on pg_class (actual rows=386 loops=1)
   Buffers: shared hit=9 read=4
 Planning Time: 0.782 ms
   Buffers: shared hit=103 read=11
 Execution Time: 0.219 ms

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

Инкрементална сортировка

В случаи, когато е необходима сортиране по много ключове (k1, k2, k3…), планиращият сега може да се възползва от знанието, че данните вече са сортирани по няколко от първите ключове (например k1 и k2). В този случай не е необходимо да се пренареждат всички данни, а вместо това да се разделят на последователни групи с еднакви стойности на k1 и k2, и да се "досортира" по ключа k3.

По този начин цялата сортиране се разпада на няколко последователни сортирания с по-малък размер. Това намалява необходимия обем памет, а също така позволява да се извеждат първите данни по-рано, преди цялата сортиране да бъде изпълнено напълно.

 Инкрементална Сортиране (actual rows=2949857 loops=1)
   Sort Key: ticket_no, passenger_id
   Presorted Key: ticket_no
   Full-sort Groups: 92184 Sort Method: quicksort Memory: avg=31kB peak=31kB
   ->  Index Scan using tickets_pkey on tickets (actual rows=2949857 loops=1)
 Planning Time: 2.137 ms
 Execution Time: 2230.019 ms

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно
Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

Подобрения на UI/UX

Скриншотите, те са навсякъде!

Сега всеки раздел предлага възможността бързо да вземете екранна снимка на раздела в клипборда с цялата ширина и дълбочина на раздела — «прицел» вдясно-горе:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

По същество, повечето изображения за тази публикация са получени именно по този начин.

Препоръки на възлите

Не само, че станаха повече, но за всеки от тях може подробно да прочетете в статията, като кликнете на връзката:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

Изтриване от архива

Някои много ни помолиха да добавим възможността да изтривате «напълно» планове, които не са публикувани в архива — моля, просто натиснете съответната икона:

Разсъждаваме по плановете на PostgreSQL заявки още по-удобно

А, и не забравяйте, че имаме група за поддръжка, където може да пишете своите забележки и предложения.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster