Мне интересно понять, как Postgres читает страницы с диска / кеша при использовании индекса.

Рассмотрите возможность запроса индексированной таблицы целых чисел с одним столбцом:

select i 
into numbers
from generate_series(1, 200000) s(i);

create index idx on numbers(i);

explain (buffers, analyse)
select * from numbers where i = 456789; -- random row

Этот одиночный поиск только по индексу требует чтения 3 страниц из этой таблицы из 200 тыс. Строк (Buffers: shared hit=3):

Index Only Scan using idx on numbers  (cost=0.42..8.44 rows=1 width=4) (actual time=0.010..0.010 rows=0 loops=1)
  Index Cond: (i = 456789)
  Heap Fetches: 0
  Buffers: shared hit=3
Planning Time: 0.043 ms
Execution Time: 0.022 ms

Ожидается ли это? К чему относятся эти 3 страницы? Это просто количество индексных страниц, которые нужно было прочитать, чтобы пройти по B-дереву?

Предпосылки : я пытаюсь настроить рекурсивный CTE, который просматривает структуру связанного списка, хранящуюся в одной таблице, как дерево отношений родитель-потомок / дерево смежности. Рекурсивный раздел запроса - это очень простой поиск по индексу, аналогичный приведенному выше. Каждый «цикл» рекурсивного CTE приводит к чтению 3 страниц (как указано выше), что составляет большую часть стоимости запроса. Возможно, это невозможно сделать более эффективным, но мне было интересно, можно ли это как-то улучшить (в настоящее время ~ 30000 операций чтения для цепочки узлов из 10 тыс., ~ 25 мс кэшировано).

0
Chris Brook 18 Окт 2019 в 14:27

1 ответ

Лучший ответ

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

Ваш запрос обращался к корневому узлу, промежуточному. узел и листовой узел индекса. Не было необходимости обращаться к блоку таблицы (Heap Fetches: 0), потому что

  1. вся информация доступна в указателе

  2. карта видимости таблицы показывала, что блок таблицы был полностью видимым, поэтому не было необходимости обращаться к блоку таблицы для получения информации о видимости.

1
Laurenz Albe 18 Окт 2019 в 12:04