Рядок повторної перевірки Cond: в планах запитів при скануванні растрової карти


21

Це відмова від коментарів до попереднього питання:

Використовуючи PostgreSQL 9.4, завжди здається, що Recheck Cond:рядок після сканування індексу растрових зображень у планах запитів виводиться EXPLAIN.

Як і у EXPLAINвисновку згаданого питання:

->  Bitmap Heap Scan on table_three  (cost=2446.92..19686.74 rows=8159 width=7)
      Recheck Cond: (("timestamp" > (now() - '30 days'::interval)) AND (client_id > 0))
      ->  BitmapAnd  (cost=2446.92..2446.92 rows=8159 width=0)
            ->  Bitmap Index Scan on table_one_timestamp_idx  (cost=0.00..1040.00 rows=79941 width=0)
                  Index Cond: ("timestamp" > (now() - '30 days'::interval))
            ->  Bitmap Index Scan on fki_table_three_client_id  (cost=0.00..1406.05 rows=107978 width=0)
                  Index Cond: (client_id > 0)

Або у висновку EXPLAIN ANALYZEдля простої, величезної таблиці (з дуже малою кількістю work_mem):

EXPLAIN ANALYZE SELECT * FROM aa WHERE a BETWEEN 100000 AND 200000;
Bitmap Heap Scan on aa  (cost=107.68..4818.05 rows=5000 width=4) (actual time=27.629..213.606 rows=100001 loops=1)
  Recheck Cond: ((a >= 100000) AND (a <= 200000))
  Rows Removed by Index Recheck: 758222
  Heap Blocks: exact=693 lossy=3732
  ->  Bitmap Index Scan on aai  (cost=0.00..106.43 rows=5000 width=0) (actual time=27.265..27.265 rows=100001 loops=1)
        Index Cond: ((a >= 100000) AND (a <= 200000))

Чи означає це, що середні умови індексу повинні перевірятися вдруге після сканування індексу растрового зображення?
Що ще ми можемо дізнатися з EXPLAINрезультатів?

Відповіді:


17

Як @Chris правильно прокоментував відповідне запитання :

Здається, що невелике розслідування вказує на те, що умова повторної перевірки завжди друкується у EXPLAIN, але насправді виконується лише тоді, коли вона work_memє достатньо малою, щоб растрова карта втрачала. Думки? http://www.postgresql.org/message-id/464F3C5D.2000700@enterprisedb.com

Хоча це все вірно і основний розробник Хейкі Ліннакангас є джерелом першого класу, публікація датується 2007 роком (Postgres 8.2). Ось допис у блозі Майкла Пак'є з детальним поясненням для Postgres 9.4 , де результати EXPLAIN ANALYZEпокращені за допомогою додаткової інформації.

Recheck Cond:Лінія завжди там для індексу реєстрового сканування. Вихід базових EXPLAINне розкаже нам більше. Ми отримуємо додаткову інформацію, EXPLAIN ANALYZEяк це видно з другої цитати у запитанні:

Heap Blocks: exact=693 lossy=3732

Із загальної кількості 4425 сторінок даних (блоків) 693 збереглися кортежі рівно (включаючи кортежні покажчики), а інші 3732 сторінки втратили (лише сторінки даних) у растровій карті. Це трапляється, коли work_memвоно недостатньо велике, щоб точно зберігати всю розроблену з індексу сканування (без втрат).

Умову індексу потрібно повторно перевірити на сторінках із втраченою часткою, оскільки растрова карта пам'ятає лише, які сторінки отримати, а не точні кортежі на сторінці. Не всі кортежі на сторінці обов'язково пройдуть умови індексу, потрібно фактично перевірити умову.

Це нитка на хакерах pgsql, де обговорювалося нове доповнення . Автор Етсуро Фуджіта пропонує формулу, як обчислити мінімум, work_memщоб уникнути втрат растрових записів та наступних перевірок умов. Розрахунок не є надійним для складних випадків з декількома скануваннями растрових зображень, тому він не використовувався для виведення фактичних чисел з EXPLAIN. Він все ще може слугувати оцінкою для простих випадків.

Додатковий рядок BUFFERS:

Крім того, при запуску з BUFFERSопцією: EXPLAIN (ANALYZE, BUFFERS) ...додається ще один рядок, як:

Buffers: shared hit=279 read=79

Це вказує, скільки основної таблиці (та індексу) було прочитано з кеша ( shared hit=279) і скільки потрібно було отримати з диска ( read=79). Якщо ви повторите запит, частина «прочитати» зазвичай зникає для не надто величезних запитів, оскільки все кешовано зараз після першого дзвінка. Перший дзвінок повідомляє вам, скільки вже було кешовано. Подальші дзвінки показують, наскільки обробляє кеш (наразі).

Є більше варіантів. Посібник про BUFFERSваріант:

Зокрема, включіть кількість спільних блоків, звернених, прочитаних, забруднених та записаних, кількість локальних блоків, які потрапили, прочитані, забруднені та записані, та кількість тимчасових блоків, прочитаних та записаних.

Читайте далі, є ще більше.
Ось список вихідних параметрів у вихідному коді .


10

Ервін, оскільки це було нашим обговоренням у нитці коментарів від цього раніше, я вирішив заглянути ще трохи далі ...

У мене дуже простий запит із таблиці досить розумного розміру. У мене зазвичай достатньо work_mem, але в цьому випадку я використовував команди

SET work_mem = 64;

встановити дуже маленький work_memі

SET work_mem = default;

щоб встановити work_memспину достатньо великою для мого запиту.

ПОЯСНЕННЯ та повторна перевірка стану

Отже, запуск мого запиту з лише EXPLAINяк

EXPLAIN 
SELECT * FROM olap.reading_facts
WHERE meter < 20;

Я отримав результати як для низьких, так і для високих work_mem:

Низький work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Високий work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Короткий огляд короткого EXPLAINопису, оскільки, як очікується, план запитів вказує, що умова повторної перевірки можлива, але ми не можемо знати, чи насправді буде обчислено.

ПОЯСНІТЬ АНАЛІЗ & Перевірте стан

Коли ми включаємо ANALYZEв запит, результати повідомляють нам більше про те, що нам потрібно знати.

Низький work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=3.130..13.946 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Rows Removed by Index Recheck: 86727
  Heap Blocks: exact=598 lossy=836
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=3.066..3.066 rows=51840 loops=1)
        Index Cond: (meter < 20)

Високий work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=2.647..7.247 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Heap Blocks: exact=1434
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=2.496..2.496 rows=51840 loops=1)
        Index Cond: (meter < 20)

Знову ж таки, як і очікувалося, включення ANALYZEвідкриває нам дуже важливу інформацію. У нижньому work_memвипадку ми бачимо, що є рядки, видалені повторною перевіркою індексу, і що у нас є lossyблоки купи.

Висновок? (або його відсутність)

На жаль, схоже, що саме EXPLAINпо собі недостатньо, щоб знати, чи дійсно буде необхідна повторна перевірка індексу, оскільки частина ідентифікаторів рядків відпадає на користь збереження сторінок під час сканування бітової карти.

Використання EXPLAIN ANALYZEчудово для діагностики проблем із запитами середньої довжини, але у випадку, якщо запит потребує надзвичайно тривалого часу для завершення, то запущення, EXPLAIN ANALYZEщоб виявити, що ваш індекс бітової карти перетворюється на втрату через недостатнє work_mem, все ще є важким обмеженням. Мені б хотілося, щоб EXPLAINз табличної статистики було оцінено ймовірність цього явища.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.