CLUSTER
Si tiene la intención de utilizar CLUSTER
, la sintaxis mostrada no es válida.
create CLUSTER ticket USING ticket_1_idx;
Ejecutar una vez:
CLUSTER ticket USING ticket_1_idx;
Este puede ayuda mucho con conjuntos de resultados más grandes. No tanto para una sola fila devuelta.
Postgres recuerda qué índice usar para llamadas posteriores. Si su tabla no es de solo lectura, el efecto se deteriora con el tiempo y debe volver a ejecutarla a ciertos intervalos:
CLUSTER ticket;
Posiblemente solo en particiones volátiles. Ver más abajo.
Sin embargo , si tiene muchas actualizaciones, CLUSTER
(o VACUUM FULL
) en realidad puede ser malo para el rendimiento. La cantidad correcta de hinchazón permite UPDATE
para colocar nuevas versiones de fila en la misma página de datos y evita la necesidad de extender físicamente el archivo subyacente en el sistema operativo con demasiada frecuencia. Puede usar un FILLFACTOR
ajustado cuidadosamente para obtener lo mejor de ambos mundos:
- Factor de relleno para un índice secuencial que es PK
pg_repack
CLUSTER
toma un bloqueo exclusivo en la tabla, lo que puede ser un problema en un entorno multiusuario. Citando el manual:
Cuando se agrupa una tabla, un ACCESS EXCLUSIVE
el bloqueo se adquiere en él. Esto evita cualquier otra operación de la base de datos (tanto lecturas como escrituras ) de operar en la mesa hasta que el CLUSTER
ha terminado.
Énfasis en negrita mío. Considere la alternativa pg_repack
:
A diferencia de CLUSTER
y VACUUM FULL
funciona en línea, sin tener un bloqueo exclusivo en las tablas procesadas durante el procesamiento. pg_repack es eficiente para arrancar, con un rendimiento comparable al uso de CLUSTER
directamente.
y:
pg_repack necesita tomar un bloqueo exclusivo al final de la reorganización.
La versión 1.3.1 funciona con:
PostgreSQL 8.3, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4
La versión 1.4.2 funciona con:
PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10
Consulta
La consulta es lo suficientemente simple como para no causar ningún problema de rendimiento per se.
Sin embargo, unas palabras sobre corrección :El BETWEEN
construcción incluye fronteras Su consulta selecciona todo el 19 de diciembre, más registros desde el 20 de diciembre, 00:00 horas. Eso es extremadamente improbable requisito. Lo más probable es que realmente quieras:
SELECT *
FROM ticket
WHERE created >= '2012-12-19 0:0'
AND created < '2012-12-20 0:0';
Rendimiento
En primer lugar, pregunta:
¿Por qué está seleccionando escaneo secuencial?
Su EXPLAIN
la salida muestra claramente un escaneo de índice , no una exploración de tabla secuencial. Debe haber algún tipo de malentendido.
Si se le presiona mucho para obtener un mejor rendimiento, es posible que pueda mejorar las cosas. Pero la información de fondo necesaria no está en la pregunta. Las posibles opciones incluyen:
-
Solo puede consultar las columnas requeridas en lugar de
*
para reducir el costo de transferencia (y posiblemente otros beneficios de rendimiento). -
Podrías mirar partición y coloque intervalos de tiempo prácticos en tablas separadas. Agregue índices a las particiones según sea necesario.
-
Si la partición no es una opción, otra técnica relacionada pero menos intrusiva sería agregar uno o más índices parciales .
Por ejemplo, si consulta principalmente el mes actual , podría crear el siguiente índice parcial:CREATE INDEX ticket_created_idx ON ticket(created) WHERE created >= '2012-12-01 00:00:00'::timestamp;
CREATE
un nuevo índice justo antes el comienzo de un nuevo mes. Puede automatizar fácilmente la tarea con un trabajo cron. Opcionalmente,DROP
índices parciales para meses anteriores. -
Mantenga el índice total además para
CLUSTER
(que no puede operar en índices parciales). Si los registros antiguos nunca cambian, la partición de tablas ayudaría mucho en esta tarea, ya que solo necesita volver a agrupar las particiones más nuevas. Por otra parte, si los registros nunca cambian, probablemente no necesiteCLUSTER
.
Si combina los dos últimos pasos, el rendimiento debería ser asombroso.
Conceptos básicos de rendimiento
Puede que te falte uno de los básicos. Se aplican todos los consejos de rendimiento habituales:
- https://wiki.postgresql.org/wiki/Slow_Query_Questions
- https://wiki.postgresql.org/wiki/Performance_Optimization