REINDEX — reconstruye índices
REINDEX [ (option[, ...] ) ] { INDEX | TABLE | SCHEMA } [ CONCURRENTLY ]nameREINDEX [ (option[, ...] ) ] { DATABASE | SYSTEM } [ CONCURRENTLY ] [name] dondeoptionpuede ser uno de: CONCURRENTLY [boolean] TABLESPACEnew_tablespaceVERBOSE [boolean]
REINDEX reconstruye un índice utilizando los datos
almacenados en la tabla del índice, reemplazando la copia antigua del índice. Existen
varios escenarios en los que se debe usar REINDEX:
Un índice se ha corrompido y ya no contiene datos válidos.
Aunque en teoría esto no debería suceder nunca, en la
práctica los índices pueden corromperse debido a errores de software o
fallas de hardware. REINDEX proporciona un
método de recuperación.
Un índice se ha vuelto “bloated” (hinchado), es decir, contiene muchas
páginas vacías o casi vacías. Esto puede ocurrir con índices B-tree en
PostgreSQL bajo ciertos patrones de acceso poco comunes.
REINDEX proporciona una forma de reducir
el consumo de espacio del índice escribiendo una nueva versión del
índice sin las páginas muertas. Consulta Section 24.2 para más información.
Has modificado un parámetro de almacenamiento (como fillfactor) para un índice, y deseas asegurarte de que el cambio haya surtido pleno efecto.
Si la creación de un índice falla con la opción CONCURRENTLY,
este índice queda como “inválido”. Estos índices son inútiles,
pero puede ser conveniente usar REINDEX para reconstruirlos.
Ten en cuenta que solo REINDEX INDEX es capaz
de realizar una reconstrucción concurrente en un índice inválido.
INDEX
Recrea el índice especificado. Esta forma de REINDEX
no se puede ejecutar dentro de un bloque de transacción cuando se usa con un
índice particionado.
TABLE
Recrea todos los índices de la tabla especificada. Si la tabla tiene una
tabla secundaria “TOAST”, esta también se reindexa.
Esta forma de REINDEX no se puede ejecutar dentro de un
bloque de transacción cuando se usa con una tabla particionada.
SCHEMA
Recrea todos los índices del esquema especificado. Si una tabla de este
esquema tiene una tabla secundaria “TOAST”, esta también se reindexa.
Los índices en catálogos compartidos del sistema también se procesan.
Esta forma de REINDEX no se puede ejecutar dentro de un
bloque de transacción.
DATABASE
Recrea todos los índices dentro de la base de datos actual, excepto los
catálogos del sistema.
Los índices en los catálogos del sistema no se procesan.
Esta forma de REINDEX no se puede ejecutar dentro de un
bloque de transacción.
SYSTEM
Recrea todos los índices de los catálogos del sistema dentro de la base de datos actual.
Se incluyen los índices en catálogos del sistema compartidos.
Los índices en las tablas de usuario no se procesan.
Esta forma de REINDEX no se puede ejecutar dentro de un
bloque de transacción.
name
El nombre del índice, tabla o base de datos específica que se va a
reindexar. Los nombres de índices y tablas pueden estar calificados por esquema.
Actualmente, REINDEX DATABASE and REINDEX SYSTEM
solo pueden reindexar la base de datos actual. Su parámetro es opcional
y debe coincidir con el nombre de la base de datos actual.
CONCURRENTLYCuando se utiliza esta opción, PostgreSQL reconstruirá el índice sin adquirir ningún bloqueo que impida inserciones, actualizaciones o eliminaciones concurrentes en la tabla; mientras que una reconstrucción de índice estándar bloquea las escrituras (pero no las lecturas) en la tabla hasta que finaliza. Hay varias advertencias a tener en cuenta al usar esta opción: consulta Rebuilding Indexes Concurrently más abajo.
Para tablas temporales, REINDEX siempre es
no concurrente, ya que ninguna otra sesión puede acceder a ellas, y
la reindexación no concurrente es más económica.
TABLESPACEEspecifica que los índices se reconstruirán en un nuevo tablespace.
VERBOSE
Imprime un informe de progreso a medida que se reindexa cada índice
a nivel INFO.
boolean
Especifica si la opción seleccionada debe activarse o desactivarse.
Puedes escribir TRUE, ON o
1 para activar la opción, y FALSE,
OFF o 0 para desactivarla. El
valor boolean también
se puede omitir, en cuyo caso se asume TRUE.
new_tablespaceEl tablespace donde se reconstruirán los índices.
Si sospechas que hay corrupción en un índice de una tabla de usuario, puedes
simplemente reconstruir ese índice, o todos los índices de la tabla, utilizando
REINDEX INDEX o REINDEX TABLE.
Las cosas son más difíciles si necesitas recuperarte de la corrupción de
un índice en una tabla del sistema. En este caso es importante que el
sistema no haya utilizado ninguno de los índices sospechosos.
(De hecho, en este tipo de escenario podrías encontrar que los procesos del
servidor se caen inmediatamente al iniciarse, debido a la dependencia de
los índices corrompidos). Para recuperarse de forma segura, el servidor debe iniciarse
con la opción -P, que le impide utilizar los
índices para las búsquedas en los catálogos del sistema.
Una forma de hacer esto es detener el servidor e iniciar un servidor
PostgreSQL en modo monousuario
con la opción -P incluida en su línea de comandos.
Luego, se puede ejecutar REINDEX DATABASE, REINDEX SYSTEM,
REINDEX TABLE o REINDEX INDEX,
dependiendo de cuánto quieras reconstruir. En caso de
duda, utiliza REINDEX SYSTEM para seleccionar la
reconstrucción de todos los índices del sistema en la base de datos. A continuación, sal de
la sesión del servidor en modo monousuario y reinicia el servidor regular.
Consulta la página de referencia de postgres para obtener más
información sobre cómo interactuar con la interfaz del servidor en modo monousuario.
Alternativamente, se puede iniciar una sesión de servidor regular con
-P incluido en sus opciones de línea de comandos.
El método para hacer esto varía según el cliente, pero en todos los
clientes basados en libpq, es posible establecer
la variable de entorno PGOPTIONS en -P
antes de iniciar el cliente. Ten en cuenta que aunque este método no
requiere bloquear a otros clientes, podría ser aconsejable evitar que
otros usuarios se conecten a la base de datos dañada hasta que se hayan
completado las reparaciones.
REINDEX es similar a eliminar y recrear el índice,
en el sentido de que los contenidos del índice se reconstruyen desde cero. Sin embargo, las
consideraciones de bloqueo son bastante diferentes. REINDEX bloquea las escrituras
pero no las lecturas de la tabla padre del índice. También adquiere un
bloqueo ACCESS EXCLUSIVE en el índice específico que se está procesando,
lo que bloqueará las lecturas que intenten utilizar ese índice. En particular,
el planificador de consultas intenta adquirir un bloqueo ACCESS SHARE
en cada índice de la tabla, independientemente de la consulta, por lo que
REINDEX bloquea prácticamente cualquier consulta excepto algunas
consultas preparadas cuyo plan ha sido almacenado en caché y que no utilizan este
índice. En contraste,
DROP INDEX adquiere momentáneamente un bloqueo
ACCESS EXCLUSIVE en la tabla padre, bloqueando tanto las
escrituras como las lecturas. El subsiguiente CREATE INDEX bloquea las
escrituras pero no las lecturas; dado que el índice no está allí, ninguna lectura intentará
utilizarlo, lo que significa que no habrá bloqueo, pero las lecturas podrían verse forzadas
a realizar costosos escaneos secuenciales.
Mientras se ejecuta REINDEX, la variable de entorno search_path se cambia temporalmente a pg_catalog,
pg_temp.
Reindexar un único índice o tabla requiere
tener el privilegio MAINTAIN en la
tabla. Ten en cuenta que aunque REINDEX en un índice o
tabla particionada requiere tener el privilegio MAINTAIN en la
tabla particionada, dichos comandos omiten las comprobaciones de privilegios al procesar
las particiones individuales. Reindexar un esquema o base de datos requiere ser el
propietario de ese esquema o base de datos o tener los privilegios del
rol pg_maintain.
Ten en cuenta específicamente que por lo tanto es
posible para los usuarios que no son superusuarios reconstruir índices de tablas que pertenecen a
otros usuarios. Sin embargo, como excepción especial,
REINDEX DATABASE, REINDEX SCHEMA
y REINDEX SYSTEM omitirán los índices en los catálogos compartidos
a menos que el usuario tenga el privilegio MAINTAIN en el
catálogo.
La reindexación de índices particionados o tablas particionadas es compatible
con REINDEX INDEX o REINDEX TABLE,
respectivamente. Cada partición de la relación particionada especificada se
reindexa en una transacción independiente. Esos comandos no se pueden utilizar dentro
de un bloque de transacción cuando se trabaja en una tabla o índice particionado.
Cuando se utiliza la cláusula TABLESPACE con
REINDEX en un índice o tabla particionada, solo se
actualizan las referencias de tablespace de las particiones hoja. Como los índices
particionados no se actualizan, se recomienda utilizar por separado
ALTER TABLE ONLY en ellos para que las nuevas particiones
asociadas hereden el nuevo tablespace. En caso de fallo, es posible que no se hayan movido
todos los índices al nuevo tablespace. Volver a ejecutar el comando reconstruirá
todas las particiones hoja y moverá los índices previamente no procesados al nuevo
tablespace.
Si se utiliza SCHEMA, DATABASE o
SYSTEM con TABLESPACE,
se omiten las relaciones del sistema y se generará una única advertencia (WARNING).
Los índices en las tablas TOAST se reconstruyen, pero no se mueven
al nuevo tablespace.
La reconstrucción de un índice puede interferir con la operación regular de una base de datos. Normalmente, PostgreSQL bloquea la tabla cuyo índice se reconstruye contra escrituras y realiza la construcción completa del índice con un único escaneo de la tabla. Otras transacciones aún pueden leer la tabla, pero si intentan insertar, actualizar o eliminar filas en la tabla, se bloquearán hasta que finalice la reconstrucción del índice. Esto podría tener un efecto grave si el sistema es una base de datos de producción activa. Las tablas muy grandes pueden tardar muchas horas en ser indexadas, e incluso para tablas más pequeñas, una reconstrucción de índice puede bloquear a los escritores durante períodos que son inaceptablemente largos para un sistema de producción.
PostgreSQL admite la reconstrucción de índices con un bloqueo mínimo
de las escrituras. Este método se invoca especificando la
opción CONCURRENTLY de REINDEX. Cuando se utiliza esta opción,
PostgreSQL debe realizar dos escaneos de la tabla
para cada índice que deba reconstruirse y esperar a la finalización de
todas las transacciones existentes que potencialmente podrían utilizar el índice.
Este método requiere más trabajo total que una reconstrucción de índice estándar
y tarda significativamente más tiempo en completarse, ya que necesita esperar
a las transacciones no finalizadas que podrían modificar el índice. Sin embargo, dado que
permite que continúen las operaciones normales mientras se reconstruye el índice, este
método es útil para reconstruir índices en un entorno de producción. Por
supuesto, la carga adicional de CPU, memoria y E/S impuesta por la reconstrucción del índice
puede ralentizar otras operaciones.
Los siguientes pasos ocurren en una reindexación concurrente. Cada paso se ejecuta en una transacción independiente. Si hay múltiples índices que reconstruir, entonces cada paso recorre todos los índices antes de pasar al siguiente paso.
Se añade una nueva definición de índice transitorio al catálogo
pg_index. Esta definición se utilizará para reemplazar
al índice antiguo. Se adquiere un bloqueo SHARE UPDATE EXCLUSIVE a
nivel de sesión en los índices que se están reindexando, así como en sus
tablas asociadas para evitar cualquier modificación del esquema mientras se procesa.
Se realiza una primera pasada para construir el índice para cada nuevo índice. Una vez que el
índice está construido, su flag pg_index.indisready se
cambia a “true” para que esté listo para inserciones, haciéndolo
visible para otras sesiones una vez que la transacción que realizó la construcción
haya finalizado. Este paso se realiza en una transacción independiente para cada
índice.
A continuación, se realiza una segunda pasada para añadir las tuplas que se añadieron mientras se ejecutaba la primera pasada. Este paso también se realiza en una transacción independiente para cada índice.
Todas las restricciones que hacen referencia al índice se modifican para hacer referencia a la
nueva definición del índice, y se cambian los nombres de los índices. En
este punto, pg_index.indisvalid se cambia a
“true” para el nuevo índice y a “false” para
el antiguo, y se realiza una invalidación de caché que hace que se invaliden todas las sesiones que
hacían referencia al índice antiguo.
Los índices antiguos tienen su flag pg_index.indisready cambiado a
“false” para evitar cualquier nueva inserción de tuplas, después de esperar
a que se completen las consultas en ejecución que podrían hacer referencia al índice antiguo.
Se eliminan los índices antiguos. Se liberan los bloqueos de sesión
SHARE UPDATE EXCLUSIVE para los índices y la tabla.
Si surge un problema al reconstruir los índices, como una
violación de unicidad en un índice único, el comando REINDEX
fallará, pero dejará un nuevo índice “inválido” además del
preexistente. Este índice se ignorará para fines de consulta
porque podría estar incompleto; sin embargo, seguirá consumiendo sobrecarga de
actualización. El comando \d de psql informará
de dicho índice como INVALID:
postgres=# \d tab
Table "public.tab"
Column | Type | Modifiers
--------+---------+-----------
col | integer |
Indexes:
"idx" btree (col)
"idx_ccnew" btree (col) INVALID
Si el índice marcado como INVALID tiene el sufijo
_ccnew, entonces corresponde al índice transitorio
creado durante la operación concurrente, y el método de recuperación recomendado
es eliminarlo utilizando DROP INDEX,
y luego intentar REINDEX CONCURRENTLY de nuevo.
Si el índice inválido tiene en cambio el sufijo _ccold,
corresponde al índice original que no pudo ser eliminado;
el método de recuperación recomendado es simplemente eliminar dicho índice, ya que la
reconstrucción propiamente dicha ha sido exitosa.
Se puede añadir un número distinto de cero al sufijo de los nombres de los índices
inválidos para mantenerlos únicos, como _ccnew1,
_ccold2, etc.
Las construcciones de índices normales permiten que se realicen simultáneamente otras construcciones de índices normales en la misma tabla,
pero solo puede ocurrir una construcción de índice concurrente en una tabla a la vez. En ambos casos, no se permite ningún otro tipo de modificación del esquema en
la tabla mientras tanto. Otra diferencia es que un comando regular
REINDEX TABLE o REINDEX INDEX
se puede realizar dentro de un bloque de transacción, pero REINDEX
CONCURRENTLY no.
Al igual que cualquier transacción de larga duración, REINDEX en una tabla
puede afectar a qué tuplas pueden ser eliminadas por un VACUUM
concurrente en cualquier otra tabla.
REINDEX SYSTEM no admite
CONCURRENTLY debido a que los catálogos del sistema no se pueden reindexar
de forma concurrente.
Además, los índices para restricciones de exclusión no se pueden reindexar
de forma concurrente. Si dicho índice se nombra directamente en este comando, se
lanzará un error. Si una tabla o base de datos con índices de restricciones de exclusión
se reindexa de forma concurrente, esos índices se omitirán. (Es posible
reindexar dichos índices sin la opción CONCURRENTLY).
Cada proceso backend que ejecute REINDEX informará de su progreso
en la vista pg_stat_progress_create_index. Consulta
Section 27.4.4 para más detalles.
Reconstruye un único índice:
REINDEX INDEX my_index;
Reconstruye todos los índices de la tabla my_table:
REINDEX TABLE my_table;
Reconstruye todos los índices en una base de datos en particular, sin confiar en que los índices del sistema ya sean válidos:
$export PGOPTIONS="-P"$psql broken_db... broken_db=> REINDEX DATABASE broken_db; broken_db=> \q
Reconstruye los índices para una tabla, sin bloquear las operaciones de lectura y escritura en las relaciones involucradas mientras la reindexación está en progreso:
REINDEX TABLE CONCURRENTLY my_broken_table;
No existe el comando REINDEX en el estándar SQL.