Строка «Recheck 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, где обсуждалось новое дополнение . Автор Etsuro Fujita предоставляет формулу для расчета минимума, 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оценить вероятность этого явления из таблицы статистики.

Крис
источник