63.3. Escaneo de índices #

En un escaneo de índice, el método de acceso al índice es responsable de regurgitar los TIDs de todas las tuplas de las que se le ha hablado que coinciden con las claves de escaneo (scan keys). El método de acceso no está involucrado en la recuperación real de esas tuplas de la tabla padre del índice, ni en la determinación de si pasan la prueba de visibilidad del escaneo u otras condiciones.

Una clave de escaneo es la representación interna de una cláusula WHERE de la forma clave_de_índice operador constante, donde la clave de índice es una de las columnas del índice y el operador es uno de los miembros de la familia de operadores asociada con esa columna de índice. Un escaneo de índice tiene cero o más claves de escaneo, que están unidas implícitamente mediante AND — se espera que las tuplas devueltas satisfagan todas las condiciones indicadas.

El método de acceso puede reportar que el índice es con pérdidas (lossy), o que requiere comprobaciones repetidas, para una consulta en particular. Esto implica que el escaneo del índice devolverá todas las entradas que pasan la clave de escaneo, más posiblemente entradas adicionales que no lo hacen. La maquinaria de escaneo de índices del sistema central aplicará entonces las condiciones del índice de nuevo a la tupla del montón para verificar si realmente debe ser seleccionada o no. Si no se especifica la opción de volver a comprobar, el escaneo del índice debe devolver exactamente el conjunto de entradas coincidentes.

Ten en cuenta que depende enteramente del método de acceso garantizar que encuentra correctamente todas y solo las entradas que pasan todas las claves de escaneo dadas. Además, el sistema central simplemente entregará todas las cláusulas WHERE que coincidan con las claves del índice y las familias de operadores, sin ningún análisis semántico para determinar si son redundantes o contradictorias. Como ejemplo, dado WHERE x > 4 AND x > 14 donde x es una columna indexada por b-tree, se deja a la función amrescan de b-tree darse cuenta de que la primera clave de escaneo es redundante y se puede descartar. El alcance del preprocesamiento necesario durante amrescan dependerá de la medida en que el método de acceso al índice necesite reducir las claves de escaneo a una forma normalizada.

Algunos métodos de acceso devuelven las entradas del índice en un orden bien definido, otros no lo hacen. En realidad, hay dos formas diferentes en las que un método de acceso puede admitir salidas ordenadas:

La función amgettuple tiene un argumento direction, que puede ser bien ForwardScanDirection (el caso normal) o bien BackwardScanDirection. Si la primera llamada después de amrescan especifica BackwardScanDirection, entonces el conjunto de entradas de índice coincidentes debe escanearse de atrás hacia adelante en lugar de en la dirección normal de adelante hacia atrás, por lo que amgettuple debe devolver la última tupla coincidente en el índice, en lugar de la primera como lo haría normalmente. (Esto solo ocurrirá para los métodos de acceso que establecen amcanorder en verdadero). Después de la primera llamada, amgettuple debe estar preparada para avanzar el escaneo en cualquier dirección desde la entrada devuelta más recientemente. (Pero si amcanbackward es falso, todas las llamadas subsiguientes tendrán la misma dirección que la primera).

Los métodos de acceso que admiten escaneos ordenados deben admitir marcar una posición en un escaneo y volver más tarde a la posición marcada. La misma posición se puede restaurar varias veces. Sin embargo, solo se necesita recordar una posición por escaneo; una nueva llamada a ammarkpos anula la posición marcada anteriormente. Un método de acceso que no admite escaneos ordenados no necesita proporcionar las funciones ammarkpos y amrestrpos en IndexAmRoutine; en su lugar, establece esos punteros en NULL.

Tanto la posición del escaneo como la posición de la marca (si la hay) deben mantenerse de manera coherente frente a inserciones o eliminaciones concurrentes en el índice. Está bien si una entrada recién insertada no es devuelta por un escaneo que habría encontrado la entrada si hubiera existido cuando comenzó el escaneo, o que el escaneo devuelva dicha entrada al volver a escanear o al retroceder a pesar de que no se había devuelto la primera vez. Del mismo modo, una eliminación concurrente puede o no verse reflejada en los resultados de un escaneo. Lo que es importante es que las inserciones o eliminaciones no causen que el escaneo pierda o devuelva repetidamente entradas que no se estaban insertando o eliminando en sí mismas.

Si el índice almacena los valores de datos indexados originales (y no una representación con pérdidas de ellos), es útil admitir escaneos de solo índice, en los que el índice devuelve los datos reales y no solo el TID de la tupla del montón. Esto solo evitará E/S si el mapa de visibilidad muestra que el TID está en una página visible para todos (all-visible); de lo contrario, la tupla del montón debe ser visitada de todos modos para comprobar la visibilidad MVCC. Pero eso no es de incumbencia del método de acceso.

En lugar de usar amgettuple, se puede hacer un escaneo de índice con amgetbitmap para recuperar todas las tuplas en una sola llamada. Esto puede ser notablemente más eficiente que amgettuple porque permite evitar ciclos de bloqueo/desbloqueo dentro del método de acceso. En principio, amgetbitmap debería tener los mismos efectos que las llamadas repetidas a amgettuple, pero imponemos varias restricciones para simplificar las cosas. En primer lugar, amgetbitmap devuelve todas las tuplas a la vez y no se admite marcar o restaurar posiciones de escaneo. En segundo lugar, las tuplas se devuelven en un mapa de bits que no tiene ninguna ordenación específica, que es por lo que amgetbitmap no toma un argumento direction. (Tampoco se suministrarán operadores de ordenación para tal escaneo). Además, no hay provisión para escaneos de solo índice con amgetbitmap, ya que no hay forma de devolver el contenido de las tuplas de índice. Finalmente, amgetbitmap no garantiza ningún bloqueo de las tuplas devueltas, con implicaciones detalladas en Section 63.4.

Ten en cuenta que se permite que un método de acceso implemente solo amgetbitmap y no amgettuple, o viceversa, si su implementación interna no es adecuada para una API o la otra.