62.3. Индексное сканирование#

62.3. Индексное сканирование

62.3. Индексное сканирование

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

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

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

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

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

  • Методы доступа, которые всегда возвращают записи в естественном порядке их данных (например, btree), должны устанавливать amcanorder в значение true. В настоящее время такие методы доступа должны использовать стратегические числа, совместимые с btree, для своих операторов равенства и порядка.

  • Доступные методы, поддерживающие операторы сортировки, должны установить amcanorderbyop в значение true. Это указывает, что индекс способен возвращать записи в порядке, удовлетворяющем ORDER BY index_key operator constant. Модификаторы сканирования такого вида могут быть переданы в функцию 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 не гарантирует блокировку возвращаемых кортежей, с последствиями, описанными в Раздел 62.4.

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