2011-04-22 14 views
7

Soy totalmente novato con postgresql pero tengo una buena experiencia con mysql. Estaba leyendo la documentación y descubrí que postgresql tiene un tipo de matriz. Estoy bastante confundido ya que no puedo entender en qué contexto este tipo puede ser útil dentro de un rdbms. ¿Por qué tendría que elegir este tipo en lugar de usar una relación clásica de uno a muchos?¿Cuál es la utilidad del tipo de matriz?

Gracias de antemano.

Respuesta

4

Los he usado para facilitar el trabajo con árboles (como los hilos de comentarios). Puede almacenar la ruta desde la raíz del árbol a un único nodo en una matriz, cada número en la matriz es el número de rama para ese nodo. A continuación, se pueden hacer cosas como esta:

SELECT id, content 
FROM nodes 
WHERE tree = X 
ORDER BY path -- The array is here. 

PostgreSQL comparará elemento a elemento matrices de la manera natural por lo que se ORDER BY path volcar el árbol en un orden de visualización lineal sensible; luego, verifique la longitud de path para determinar la profundidad de un nodo y eso le da la sangría para obtener la representación correcta.

El enfoque anterior le lleva de la base de datos a la página representada con una pasada a través de los datos.

PostgreSQL también tiene geometric types, simple key/value types, y admite la construcción de varios otros composite types.

Por lo general, es mejor utilizar tablas de asociación tradicionales, pero no hay nada de malo en tener más herramientas en su caja de herramientas.

+0

Muchas gracias. Ahora está más claro. :) –

1

He estado utilizándolos con éxito para agregar referencias de árboles recursivos utilizando activadores.

Por ejemplo, supongamos que tiene un árbol de categorías y desea buscar productos en cualquiera de las categorías (1,2,3) o cualquiera de sus subcategorías.

Una forma de hacerlo es usar una fea declaración with recursive. Al hacerlo, se generará un plan rellenado con uniones merge/hash en tablas completas y materializaciones ocasionales.

with recursive categories as (
select id 
from categories 
where id in (1,2,3) 
union all 
... 
) 
select products.* 
from products 
join product2category on... 
join categories on ... 
group by products.id, ... 
order by ... limit 10; 

Otra es comprobar la validez de agregar los datos necesarios:

categories (
    id int, 
    parents int[] -- (array_agg(parent_id) from parents) || id 
) 

products (
    id int, 
    categories int[] -- array_agg(category_id) from product2category 
) 

index on categories using gin (parents) 

index on products using gin (categories) 

select products.* 
from products 
where categories && array(
     select id from categories where parents && array[1,2,3] 
    ) 
order by ... limit 10; 

Un problema con el enfoque anterior es que las estimaciones de fila para el operador & & son correos no deseados. (La selectividad es una función secundaria que aún no se ha escrito, y da como resultado filas de 1/200, independientemente de los valores en sus agregados). Dicho de otra manera, es muy posible que termine con un escaneo de índice donde un escaneo seq sería correcto

Para solucionarlo, aumenté las estadísticas en la columna indexada a gin y periódicamente busco en pg_stats para extraer estadísticas más apropiadas. Cuando un vistazo superficial a esas estadísticas revelan que usando & & para los valores especificados devolverá un plan incorrecto, reescribo las ocurrencias aplicables de & & con arrayoverlap() (este último tiene una selectividad de stub de 1/3), p.:

select products.* 
from products 
where arrayoverlap(cat_id, array(
     select id from categories where arrayoverlap(parents, array[1,2,3]) 
    )) 
order by ... limit 10; 

(Lo mismo ocurre con el operador @ < ...)

+0

+1. Hola Denis. Muchas gracias por el tiempo que me has dedicado. Tu respuesta ha sido muy útil. ;) –

+0

Sin embargo, en 9.2 y superior, el '' index_scan'' será enormemente superior en términos de rendimiento en comparación con el rendimiento anterior a 9.2 debido a las nuevas capacidades INDEX-only encontradas de 9.2+. – Sean

Cuestiones relacionadas