2011-11-30 17 views
5

Tengo un problema de rendimiento con las secuencias DELETE/INSERT en PostgreSQL 9.0. Estoy buscando ideas para mejorar la situación.PostgreSQL DELETE/INSERT throughput issue

En el hardware disponible para nosotros, puedo INSERTAR nuevas filas en una base de datos a una tasa sostenida de 3000/s (uniformemente en 10 tablas) más allá de las filas de 1m en cada tabla que usualmente pruebo. Sin embargo, si cambio a un modo donde ELIMINAR una fila y volver a INSERTARLO con datos diferentes, el rendimiento disminuye en más de un orden de magnitud a 250 filas/s (de nuevo, de manera uniforme en 10 tablas).

No hay restricciones en ninguna tabla. Hay 2 columnas indexadas en cada tabla con un tamaño de índice total (en 1m filas por tabla) de 1GB que se encuentra cómodamente dentro de shared_buffers (2GB). El tamaño total de los datos (en 1m filas por tabla) es de 12GB, que es mucho menor que la RAM total del sistema. Esta es una base de datos en la que podemos reconstruir en caso de emergencia, por lo que corremos con fsync apagado.

Parece que cuando estamos en el modo de llenado, nos beneficiamos de tiempos de búsqueda de disco muy bajos porque se anexan datos. Sin embargo, cuando cambiamos al modo de actualización, hay muchas búsquedas en curso (para eliminar las filas anteriores, presumiblemente). El disco aleatorio busca un costo de ~ 8ms (= ~ 125 por segundo). ¿Hay alguna manera (sin un cambio de hardware) de que podamos mejorar significativamente el rendimiento de las operaciones UPDATE/re-INSERT?

EDIT1: Estoy realizando pruebas de rendimiento en dos plataformas de hardware de especificaciones diferentes. Los números que cité anteriormente eran de la plataforma de especificaciones más altas. Acabo de completar una prueba en la plataforma de especificaciones más baja. En esta prueba inserto nuevas filas lo más rápido posible, registrando la tasa de inserción cada 10 segundos, hasta que he insertado 1 millón de filas. En este punto, mi script de prueba cambia a la actualización de filas aleatorias.

Perf results graph

Este gráfico muestra la velocidad de actualización medido fue de ~ 150 cambios a los 10 cuadros/segundo durante población y la tasa de actualización se < 10 cambios a los 10 cuadros/segundo.

@wildplasser - La máquina es una máquina real, no una máquina virtual. Las 10 tablas tienen el siguiente esquema.

CREATE TABLE objecti_servicea_item1 
(
    iss_scs_id text, 
    iss_generation bigint, 
    boolattr1 boolean, 
    boolattr2 boolean, 
    boolattr3 boolean, 
    boolattr4 boolean, 
    boolattr5 boolean, 
    boolattr6 boolean, 
    boolattr7 boolean, 
    boolattr8 boolean, 
    boolattr9 boolean, 
    boolattr10 boolean, 
    boolattr11 boolean, 
    boolattr12 boolean, 
    boolattr13 boolean, 
    boolattr14 boolean, 
    boolattr15 boolean, 
    boolattr16 boolean, 
    boolattr17 boolean, 
    intattr1 bigint, 
    intattr2 bigint, 
    intattr3 bigint, 
    intattr4 bigint, 
    intattr5 bigint, 
    intattr6 bigint, 
    intattr7 bigint, 
    intattr8 bigint, 
    intattr9 bigint, 
    intattr10 bigint, 
    intattr11 bigint, 
    intattr12 bigint, 
    intattr13 bigint, 
    intattr14 bigint, 
    intattr15 bigint, 
    intattr16 bigint, 
    intattr17 bigint, 
    strattr1 text[], 
    strattr2 text[], 
    strattr3 text[], 
    strattr4 text[], 
    strattr5 text[], 
    strattr6 text[], 
    strattr7 text[], 
    strattr8 text[], 
    strattr9 text[], 
    strattr10 text[], 
    strattr11 text[], 
    strattr12 text[], 
    strattr13 text[], 
    strattr14 text[], 
    strattr15 text[], 
    strattr16 text[], 
    strattr17 text[] 
) 
WITH (
    OIDS=FALSE 
); 
CREATE INDEX objecti_servicea_item1_idx_iss_generation 
    ON objecti_servicea_item1 
    USING btree 
    (iss_generation); 
CREATE INDEX objecti_servicea_item1_idx_iss_scs_id 
    ON objecti_servicea_item1 
    USING btree 
    (iss_scs_id); 

Las "Actualizaciones" que se realizan incluyen el siguiente SQL para cada una de las 10 tablas.

DELETE FROM ObjectI_ServiceA_Item1 WHERE iss_scs_id = 'ObjUID39' 
INSERT INTO ObjectI_ServiceA_Item1 
VALUES ('ObjUID39', '2', '0', NULL, '0' 
, NULL, NULL, NULL, '1', '1', NULL, '0' 
, NULL, NULL, NULL, NULL, '0', '1', '1' 
, '-70131725335162304', NULL, NULL, '-5241412302283462832' 
, NULL, '310555201689715409', '575266664603129486' 
, NULL, NULL, NULL, NULL, NULL, NULL 
, '-8898556182251816700', NULL, '3325820251460628173' 
, '-3434461681822953613' 
, NULL 
, E'{pvmo2mt7dma37roqpuqjeu4p8b,"uo1kjt1b3eu9g5vlf0d02l6iaq\\\\\\",",45kfns1j80gc7fri0dm29hnrjo}' 
, NULL, NULL 
, E'{omjv460do8cb7abn8t3eg5b6ki,"a7hrlninbk1rmu6h3rd4787l7f\\\\\\",",24n3ipfua5spma2vrj2aji98g3}' 
, NULL 
, E'{1821v2n2ermm4jujrucu5tekmm,"ukgst224964uhthkhjj9v189ft\\\\\\",",6dfsaniq9mftvbdr8g1sr8e6as}' 
, E'{c2a9gvf0fnd38m8vprlhkp2n74,"ts86vbat12lfr0d7l4tc29k9uk\\\\\\",",32b5j9r5evmrie4h21hi10dpot}' 
, E'{18pve4cmcbrjiom9bpvoo1l4n0,"hrqcsane6r0n7u2oj79bj605rh\\\\\\",",32q5n18q3qbkuit605fv47270o}' 
, E'{l3bf96shrpnnqgt35m7574t5n4,"cpol4k8296hbdqc9kac79oj0ua\\\\\\",",eqioulmb7vav10lbnc5jg752df}' 
, E'{5fai108h163hpjcv0ofgfi7c28,"ci958009ddak3li7bp37slcs8i\\\\\\",",2itstj01tkprlul8f530uhs6s2}' 
, E'{ueqfkdold8vc84jllr4b2cakt5,"t5vbea4r7tva091pa8j6886t60\\\\\\",",ul82aovhil1lpd290s14vd0p3i}' 
, NULL, NULL, NULL, NULL, NULL) 

Tenga en cuenta que durante la primera fase de mi prueba de rendimiento, el comando ELIMINAR siempre no hará nada.

@Frank Heikens - En la prueba de rendimiento que estoy ejecutando las actualizaciones se están realizando a partir de 10 hilos. Sin embargo, las actualizaciones se asignan a los hilos de una manera que garantiza que múltiples actualizaciones en la misma fila siempre sean manejadas por el mismo hilo.

+0

¿Es esta una VM o una máquina real? También agregue (un fragmento de) la definición de la tabla && query, y el plan de consulta resultante a la pregunta. – wildplasser

+0

¿Revisaste por cerraduras? Múltiples procesos podrían intentar eliminar el mismo registro. –

+0

He editado mi publicación para responder a su comentario. – mchr

Respuesta

3

Este modelo de datos no es una belleza, el BORRAR - INSERTAR cualquiera. ¿Qué pasa con una ACTUALIZACIÓN? Si iss_generation y iss_scs_id no cambian en la ACTUALIZACIÓN, la base de datos puede hacer un HOT update (Tuple de desbordamiento de montón) para aumentar el rendimiento. ACTUALIZAR también se beneficiará de un factor de relleno inferior.

Cuando realiza un BORRADO de un registro, ese registro puede estar en un bloque diferente de donde irá el INSERTAR. El uso de un factor de relleno inferior y el uso de ACTUALIZAR, podría dar a la base de datos la opción de ELIMINAR e INSERTAR el registro actualizado en el mismo bloque en el disco. Esto dará como resultado menos E/S aleatorias.Cuando se puede usar HOT, las cosas mejoran aún más porque no hay necesidad de actualizar los índices.

1

No estoy seguro, pero quizás cambiar el factor de relleno ayudará?

+0

Gracias por la sugerencia. Lo investigaré. – mchr

0

Tenemos éxito con eliminar/copiar de csv en la memoria.