2012-08-03 17 views
13

Digamos que tenemos una tabla con 6 millones de registros. Hay 16 columnas enteras y pocas columnas de texto. Es una tabla de solo lectura, por lo que cada columna entera tiene un índice. Cada registro es alrededor de 50-60 bytes.Postgresql - rendimiento del uso de una matriz en la base de datos grande

El nombre de la tabla es "Artículo"
El servidor es: 12 GB de RAM, 1,5 TB SATA, 4 NÚCLEOS. Todo el servidor para postgres.
Hay muchas más tablas en esta base de datos por lo que la RAM no cubre toda la base de datos.

Quiero agregar a la tabla "Artículo" una columna "a_elements" (tipo de matriz de enteros grandes) Cada registro no tendría más de 50-60 elementos en esta columna.

Después de eso me gustaría crear GIN índice en esta columna y consulta típica debería tener este aspecto:

select * from item where ...... and '{5}' <@ a_elements; 

tengo también el segundo, más clásico, opción.

no añada a_elements columna a elemento de la tabla, pero crear elementos de una tabla con dos columnas:

  • id_item
  • id_element

Esta tabla tendría alrededor de 200 millones de registros.

Puedo hacer particiones en estas tablas por lo que el número de registros se reduciría a 20 mln en los elementos de la tabla y 500 K en el ítem de la tabla.

La segunda opción de consulta se parece a esto:

select item.* 
from item 
    left join elements on (item.id_item=elements.id_item) 
where .... 
and 5 = elements.id_element 

Me pregunto qué opción sería mejor en el punto de vista del rendimiento. ¿Posgres puede usar muchos índices diferentes con índice GIN (opción 1) en una sola consulta?

Necesito tomar una buena decisión porque la importación de estos datos me llevará 20 días.

+1

¡Hola! ¿Y cuál es tu decisión final? Tengo casi la misma situación. –

Respuesta

10

creo que usted debe utilizar una tabla de elements:

  • Postgres sería capaz de utilizar las estadísticas para predecir el número de filas coincidirá antes de ejecutar la consulta, por lo que sería capaz de utilizar el mejor plan de consulta (es más importante si sus datos no están distribuidos uniformemente);

  • podrá localizar datos de consulta utilizando CLUSTER elements USING elements_id_element_idx;

  • cuando se lanzará Postgres 9.2, entonces podrá aprovechar los escaneos indexados solamente;

Pero he hecho algunas pruebas para el 10M elementos:

create table elements (id_item bigint, id_element bigint); 
insert into elements 
    select (random()*524288)::int, (random()*32768)::int 
    from generate_series(1,10000000); 

\timing 
create index elements_id_item on elements(id_item); 
Time: 15470,685 ms 
create index elements_id_element on elements(id_element); 
Time: 15121,090 ms 

select relation, pg_size_pretty(pg_relation_size(relation)) 
    from (
    select unnest(array['elements','elements_id_item', 'elements_id_element']) 
     as relation 
) as _; 
     relation  | pg_size_pretty 
---------------------+---------------- 
elements   | 422 MB 
elements_id_item | 214 MB 
elements_id_element | 214 MB 



create table arrays (id_item bigint, a_elements bigint[]); 
insert into arrays select array_agg(id_element) from elements group by id_item; 

create index arrays_a_elements_idx on arrays using gin (a_elements); 
Time: 22102,700 ms 

select relation, pg_size_pretty(pg_relation_size(relation)) 
    from (
    select unnest(array['arrays','arrays_a_elements_idx']) as relation 
) as _; 
     relation  | pg_size_pretty 
-----------------------+---------------- 
arrays    | 108 MB 
arrays_a_elements_idx | 73 MB 

Así que en las otras matrices de mano son más pequeños y tienen menor índice. Haría algunas pruebas de elementos de 200M antes de tomar una decisión.

Cuestiones relacionadas