2010-06-23 18 views
8

Tengo una tabla bastante grande (20M registros) que tiene un índice de 3 columnas y una columna de matriz. La columna de matriz se actualiza diariamente (al agregar nuevos valores) para todas las filas. También hay inserciones, pero no tanto como hay actualizaciones.PostgreSQL lento en una tabla grande con matrices y muchas actualizaciones

Los datos en la matriz representan las medidas diarias correspondientes a las tres teclas, algo como esto: [[date_id_1, my_value_for_date_1], [date_id_2, my_value_for_date_2]]. Se usa para dibujar un gráfico de esos valores diarios. Supongamos que quiero visualizar el valor de la clave (a, b, c) con el tiempo, lo hago SELECT values FROM t WHERE a = my_a AND b = my_b AND c = my_c. Luego uso la matriz values para dibujar el gráfico.

El rendimiento de las actualizaciones (que suceden a granel una vez al día) ha empeorado considerablemente con el tiempo.

Usando PostgreSQL 8.3.8.

¿Puede darme algún indicio de dónde buscar una solución? Podría ser cualquier cosa, desde modificar algunos parámetros en postgres hasta moverlos a otra base de datos (supongo que una base de datos no relacional sería más adecuada para esta tabla en particular, pero no tengo mucha experiencia con ellos).

+1

http://archives.postgresql.org/pgsql-performance/ –

+1

@Milen Gracias por la pista. Soy un gran admirador de StackOverflow y lo prefiero a través de listas de correo o foros especializados.Aunque estoy de acuerdo en que esos aún tienen su lugar, y definitivamente iría allí si no pudiera encontrar ayuda en SO. – ibz

+0

Ver también https://stackoverflow.com/questions/3361291/slow-simple-update-query-on-postgresql-database-with-3-million-rows – rogerdpack

Respuesta

16

Me gustaría echar un vistazo al FILLFACTOR de la tabla. Por defecto está configurado en 100, podría bajarlo a 70 (para empezar). Después de esto, tienes que hacer un VACÍO LLENO para reconstruir la tabla.

ALTER TABLE tablename SET (FILLFACTOR = 70); 
VACUUM FULL tablename; 
REINDEX TABLE tablename; 

Esto da ACTUALIZACIÓN la oportunidad de colocar la copia actualizada de una fila en la misma página que el original, que es más eficiente que colocarlo en una página diferente. O si su base de datos ya está algo fragmentada a partir de muchas actualizaciones anteriores, es posible que ya esté suficientemente espaciada. Ahora su base de datos también tiene la opción de hacer HOT updates, asumiendo que la columna que está actualizando no está involucrada en ningún índice.

+0

Según lo veo, HOT es una forma de evitar actualizar el índice cuando se realiza una ACTUALIZACIÓN. ¿Derecha? Si es así, ¿por qué mi rendimiento disminuirá * con el tiempo *? Mis índices se estaban actualizando de la misma manera hace 4 meses que ahora, pero mi rendimiento ha disminuido considerablemente desde entonces. – ibz

+3

La disminución del rendimiento puede ocurrir porque las nuevas versiones de un registro (debido a la actualización) se colocarán en una página diferente. Cuando tenga muchos registros, también tendrá muchas páginas. Poner una nueva versión lejos de la versión original tendrá un impacto en los planes de consulta. Use EXPLAIN para ver qué pasa. También considere CLUSTER para almacenar sus registros en el mismo orden en que los índices almacenan su información. Tienes que jugar con el factor de relleno, los registros actualizados deben estar cerca de los originales. –

+0

Ya veo. Entonces, cada vez que hago una consulta, ¿tiene que pasar por las filas muertas también antes de llegar a la que yo quiero? Esto es lo que quieres decir (simplificado)? Eso significa que el factor de relleno debería ayudar. ¿Las actualizaciones de HOT están relacionadas con el factor de relleno? ¿Cómo activo las actualizaciones HOT una vez que cambio el fillfactor? – ibz

2

No estoy seguro si las matrices son el camino a seguir aquí.

¿Por qué no almacenar estos en una tabla separada (un valor más claves por fila) entonces la actualización en masa será la actividad de inserción pura.

1

Bueno, un índice de 3 columnas no es nada de qué preocuparse. Eso no necesariamente lo hace mucho más lento. Pero esa matriz de matriz podría ser el problema. Usted dice que está agregando valores a esa columna de matriz diariamente. Al agregar, ¿quiere decir agregar valores a todos los 20 millones? registros en la tabla? ¿O solo algunos discos?

La situación no está del todo clara para mí, pero sugeriría buscar formas de deshacerse de esa columna de matriz. Por lo que es una mesa separada, por ejemplo. Pero, esto depende de su situación y podría no ser una opción. Podría ser solo yo, pero siempre me siento 'sucio' con una columna así en una de mis mesas. Y la mayoría de las veces hay una solución mejor para el problema que está tratando de resolver con esa matriz de matriz. Dicho esto, ciertamente hay situaciones en las que dicha columna es válida, pero en este momento, no puedo pensar en ninguna. Ciertamente no en una mesa con un 20 mln. número de registros.

+2

Estoy agregando elementos a algunas de las matrices, no todas 20 mln. Solía ​​tener una mesa diferente, pero eso la hace ENORME y el rendimiento es mucho peor. Decidió desnormalizar y almacenar datos en esas matrices, lo que hizo una gran mejora para seleccionar y no empeoró las actualizaciones al principio (aunque parece que empeoran con el tiempo). – ibz

+0

¿Podría explicar más sobre la naturaleza de los datos que están en la tabla, y en la matriz, y la relación entre ellos? Todavía podría haber una mejor solución. :) – pyrocumulus

+0

Se agregaron más detalles. Ver el segundo párrafo. Sin embargo, no estoy seguro de que realmente importe. – ibz

2

El problema está en las actualizaciones. Cambie el esquema de la matriz en función de múltiples filas por día, y el problema de rendimiento desaparecerá.

Puede agregar rollups a arreglos, más adelante, con algún tipo de cronjob, pero evite las actualizaciones.

+0

"rollups to arrays" sería muy lento si tuviera que construir las matrices desde cero (pasar por cada día, por cada combinación de a, b, c). – ibz

Cuestiones relacionadas