Hay 2 partes en mi pregunta.
- ¿Hay alguna forma de especificar el tamaño inicial de una base de datos en PostgreSQL?
- Si no lo hay, ¿cómo lidiar con la fragmentación cuando la base de datos crece con el tiempo?
Recientemente migré de MSSQL a Postgres, y una de las cosas que hicimos en el mundo de MSSQL al crear una base de datos fue especificar el tamaño inicial de la base de datos y el registro de transacciones. Esto redujo la fragmentación y aumentó el rendimiento, especialmente si el tamaño "normal" de la base de datos se conoce de antemano.
El rendimiento de mi base de datos disminuye a medida que aumenta el tamaño. Por ejemplo, la carga de trabajo a la que lo someto normalmente toma 10 minutos. A medida que crece la base de datos, esta vez aumenta. Hacer un ANÁLISIS DE VACÍO, VACÍO COMPLETO y VACÍO COMPLETO no parece resolver el problema. Lo que resuelve el problema de rendimiento es detener la base de datos, fragmentar la unidad y luego hacer un ANÁLISIS COMPLETO DE VACÍO para que el rendimiento de mi prueba vuelva a los 10 minutos originales. Esto me lleva a sospechar que la fragmentación es lo que me está causando dolor.
No he podido encontrar ninguna referencia para reservar espacio de tablas / bases de datos en Postgres. O estoy usando la terminología incorrecta y, por lo tanto, no encuentro nada, o hay una forma diferente de mitigar la fragmentación del sistema de archivos en Postgres.
Cualquier puntero?
La solución
Las respuestas proporcionadas ayudaron a confirmar lo que había comenzado a sospechar. PostgreSQL almacena la base de datos en varios archivos y esto es lo que permite que la base de datos crezca sin preocuparse por la fragmentación. El comportamiento predeterminado es empaquetar estos archivos hasta el borde con datos de tabla, lo cual es bueno para tablas que rara vez cambian pero es malo para tablas que se actualizan con frecuencia.
PostgreSQL utiliza MVCC para proporcionar acceso concurrente a los datos de la tabla. Bajo este esquema, cada actualización crea una nueva versión de la fila que se actualizó (esto podría ser a través de la marca de tiempo o el número de versión, ¿quién sabe?). Los datos antiguos no se eliminan de inmediato, sino que se marcan para su eliminación. La eliminación real ocurre cuando se realiza una operación de VACÍO.
¿Cómo se relaciona esto con el factor de relleno? El factor de relleno predeterminado de la tabla de 100 empaqueta completamente las páginas de la tabla, lo que a su vez significa que no hay espacio dentro de la página de la tabla para contener filas actualizadas, es decir, las filas actualizadas se colocarán en una página de tabla diferente de la fila original. Esto es malo para el rendimiento, como lo demuestra mi experiencia. Como mis tablas de resumen se actualizan con mucha frecuencia (hasta 1500 filas / seg), opté por establecer un factor de relleno de 20, es decir, el 20% de la tabla será para datos de fila insertados y el 80% para datos de actualización. Si bien esto puede parecer excesivo, la gran cantidad de espacio reservado para las filas actualizadas significa que las filas actualizadas permanecen dentro de la misma página que la original y que la página de la tabla no está llena cuando se ejecuta el demonio de vacío automático para eliminar las filas obsoletas.
Para "arreglar" mi base de datos, hice lo siguiente.
- Establezca el factor de relleno de mis tablas de resumen en 20. Puede hacerlo en el momento de la creación pasando un parámetro a CREATE TABLE o después del hecho a través de ALTER TABLE. Emití el siguiente comando plpgsql:
ALTER TABLE "my_summary_table" SET (fillfactor = 20);
- Emitió un VACÍO COMPLETO, ya que esto escribe una versión completamente nueva del archivo de la tabla y por lo tanto, por implicación, escribe un nuevo archivo de la tabla con el nuevo factor de relleno .
Al volver a ejecutar mis pruebas, no veo una degradación del rendimiento incluso cuando la base de datos es tan grande como necesito que sea con muchos millones de filas.
TL; DR: la fragmentación del archivo no fue la causa, fue la fragmentación del espacio de tablas. Esto se mitiga ajustando el factor de relleno de la tabla para adaptarlo a su caso de uso particular.