¿Es peligroso REINDEX?


17

He estado intentando COUNT(*)una tabla con 150,000 filas que tiene una clave primaria. Tiene una herramienta de aproximadamente 5 minutos, así que descubrí que este es un problema de indexación.

Citando el manual de PostgreSQL :

REINDEX es similar a una caída y recreación del índice en 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 primaria del índice. También toma un bloqueo exclusivo en el índice específico que se procesa, lo que bloqueará las lecturas que intenten usar ese índice (...) El CREATE INDEX subsiguiente bloquea las escrituras pero no las lecturas; Como el índice no está allí, ninguna lectura intentará usarlo, lo que significa que no habrá bloqueo, pero las lecturas podrían verse obligadas a realizar costosos escaneos secuenciales.

Desde su propia experiencia, ¿puede decir:

  • es REINDEXINGpeligroso? ¿Puede dañar la consistencia de los datos?
  • ¿Puede tomar mucho tiempo?
  • ¿Es una solución probable para mi escenario?

Actualizar:

La solución que funcionó para nosotros fue recrear el mismo índice con un nombre diferente y luego eliminar el índice anterior.

La creación del índice es muy rápida, y hemos reducido el tamaño del índice de 650 MB a 8 MB. Usar un COUNT(*)con betweentoma solo 3 segundos.

Respuestas:


15

La reindexación no es peligrosa y no puede dañar la consistencia de los datos. Sin embargo, si tiene escrituras de tiempo crítico, puede perder datos si la tabla está bloqueada y se cancela el DML.

La reindexación no debería llevar mucho tiempo, pero generalmente implicará leer toda la tabla, ordenar los campos de índice y escribir un nuevo índice. Dado el tiempo COUNT(*), probablemente tomará cinco minutos o más.

Es poco probable que este sea un problema de indexación. COUNT(*)debería usar una exploración de tabla en cuyo caso no se lee ningún índice. Espero que tengas un problema de IO de algún tipo.

Intente usar COUNT(1)o COUNT(pk_field)que puede usar el índice.

Si está ejecutando en una plataforma Unix o Linux, puede supervisar la actividad del disco sar. También puede tener un disco defectuoso que puede reducir drásticamente las tasas de E / S.

Las tablas con objetos grandes también pueden aumentar la E / S significativamente para construir los registros para COUNT (*).


2
Según wiki.postgresql.org, COUNT(*)es la mejor opción:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80

1

No estoy seguro de la mejor respuesta para ti. Sin embargo, este hilo parece ofrecer algunas buenas sugerencias: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

Una nota es que podría implementar un GATILLO para mantener los recuentos de filas en una tabla separada (si sus aplicaciones llamaran COUNT (*) con frecuencia).

Algunas de las respuestas sugieren que esto es sintomático de una base de datos que no se ha aspirado lo suficiente recientemente (lo que sugiere que el vacío automático está desactivado en su servidor o para esa base de datos en particular).

Otra sugerencia se ve así:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

Y alguien identificado como A. Kretschmer señala:

No. La implementación de índice actual no contiene información sobre la visibilidad de fila dentro de la transacción actual. Debe escanear toda la tabla de datos para obtener si la fila actual es visible dentro de la transacción actual.

... apoyando mi comentario sobre los permisos de nivel de fila como una preocupación de rendimiento.

Mi búsqueda también mostró WikiVS: MySQL vs. PostgreSQL: COUNT (*) .

Puede leer detenidamente los otros resultados que encontré usando Google: rendimiento postgresql count (*)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.