Перейти к основному содержимому

Сканирование индексов

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

Ключ сканирования - это внутреннее представление предложения WHERE вида index_key operator constant, где ключ индекса - это один из столбцов индекса, а оператор - один из членов семейства операторов, связанных с этим столбцом индекса. Индексное сканирование имеет ноль или более ключей сканирования, которые неявно объединяются - ожидается, что возвращаемые кортежи будут удовлетворять всем указанным условиям.

Метод доступа может сообщить, что индекс не несет потерь или требует перепроверки для конкретного запроса. Это означает, что при сканировании индекса будут возвращены все записи, удовлетворяющие ключу сканирования, плюс, возможно, дополнительные записи, которые не удовлетворяют. Механизм сканирования индекса основной системы затем снова применит условия индекса к кортежу кучи, чтобы проверить, действительно ли он должен быть выбран. Если опция перепроверки не указана, сканирование индекса должно вернуть точно такой же набор совпадающих записей.

Обратите внимание, что метод доступа полностью зависит от того, насколько корректно он находит все и только те записи, которые соответствуют всем заданным ключам сканирования. Кроме того, система ядра просто передаст все предложения WHERE, соответствующие ключам индекса и семействам операторов, без какого-либо семантического анализа, чтобы определить, являются ли они избыточными или противоречивыми. Например, для WHERE x > 4 AND x > 14, где x - индексированный столбец b-дерева, функции b-дерева amrescan остается понять, что первый ключ сканирования избыточен и может быть отброшен. Степень предварительной обработки, необходимой при amrescan, будет зависеть от того, насколько метод доступа к индексу должен привести ключи сканирования к «нормализованной» форме.

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

  • Методы доступа, которые всегда возвращают записи в естественном порядке своих данных (например, btree), должны установить amcanorder в true. В настоящее время такие методы доступа должны использовать btree-совместимые стратегические числа для своих операторов равенства и упорядочивания.
  • Методы доступа, поддерживающие операторы упорядочивания, должны установить значение amcanorderbyop в true. Это означает, что индекс способен возвращать записи в порядке, удовлетворяющем ORDER BY ключ_индекса оператор константа. Модификаторы сканирования такой формы могут быть переданы в amrescan, как описано ранее.

Функция amgettuple имеет аргумент direction, который может быть либо ForwardScanDirection (обычный случай), либо BackwardScanDirection. Если в первом вызове после amrescan указано BackwardScanDirection, то набор совпадающих записей индекса будет сканироваться не в обычном направлении вперед-назад, а назад-вперед, поэтому amgettuple должна возвращать последний совпадающий кортеж в индексе, а не первый, как обычно. (Это происходит только для методов доступа, в которых для параметра amcanorder установлено значение true.) После первого вызова amgettuple должен быть готов к продвижению сканирования в любом направлении, начиная с последней возвращенной записи. (Но если значение amcanbackward равно false, все последующие вызовы будут иметь то же направление, что и первый).

Методы доступа, поддерживающие упорядоченное сканирование, должны поддерживать «пометку» позиции в сканировании и последующий возврат к отмеченной позиции. Одна и та же позиция может быть восстановлена несколько раз. Однако для каждого сканирования необходимо запоминать только одну позицию; новый вызов ammarkpos отменяет ранее отмеченную позицию. Метод доступа, не поддерживающий упорядоченное сканирование, не должен предоставлять функции ammarkpos и amrestrpos в IndexAmRoutine; вместо этого установите эти указатели в NULL.

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

Если индекс хранит исходные значения индексируемых данных (а не какое-то их представление с потерями), полезно поддерживать сканирование только по индексу, при котором индекс возвращает фактические данные, а не только TID кортежа кучи. Это позволит соптимизировать ввод/вывод, только если карта видимости показывает, что TID относится к полностью видимой странице; в противном случае кортеж кучи все равно должен быть посещен для проверки видимости MVCC. Но это уже не забота метода доступа.

Вместо использования amgettuple можно выполнить сканирование индекса с помощью amgetbitmap, чтобы получить все кортежи за один вызов. Это может быть заметно эффективнее, чем amgettuple, поскольку позволяет избежать циклов блокировки/разблокировки в методе доступа. В принципе, amgetbitmap должен иметь те же эффекты, что и повторные вызовы amgettuple, но мы накладываем несколько ограничений, чтобы упростить ситуацию. Во-первых, amgetbitmap возвращает все кортежи сразу, и маркировка или восстановление позиций сканирования не поддерживается. Во-вторых, кортежи возвращаются в виде битовой карты, которая не имеет определенного упорядочения, поэтому amgetbitmap не принимает аргумент direction. (Операторы упорядочивания также никогда не будут предоставлены для такого сканирования). Кроме того, в amgetbitmap не предусмотрено сканирование только по индексам, поскольку нет возможности вернуть содержимое кортежей с индексами. Наконец, amgetbitmap не гарантирует никакой блокировки возвращаемых кортежей, последствия этого описаны в разделе «Замечания по блокировкам индексов».

Обратите внимание, что допускается, чтобы метод доступа реализовывал только amgetbitmap, но не amgettuple, или наоборот, если его внутренняя реализация не подходит для одного API или другого.