Estoy ejecutando PostgreSQL 8.3 en un Intel Core Duo Mac Mini de 1,83 GHz con 1 GB de RAM y Mac OS X 10.5.8. Tengo un gran gráfico guardado en mi base de datos PostgreSQL. Consta de 1,6 millones de nodos y 30 millones de bordes. Mi esquema de base es como:PostgreSQL: Cómo optimizar mi base de datos para almacenar y consultar un enorme gráfico
CREATE TABLE nodes (id INTEGER PRIMARY KEY,title VARCHAR(256));
CREATE TABLE edges (id INTEGER,link INTEGER,PRIMARY KEY (id,link));
CREATE INDEX id_idx ON edges (id);
CREATE INDEX link_idx ON edges (link);
Los datos en los bordes de la mesa parece
id link
1 234
1 88865
1 6
2 365
2 12
...
Así que almacena para cada nodo con id x el enlace de salida de Identificación y.
El tiempo para buscar todos los enlaces salientes es aceptable:
=# explain analyze select link from edges where id=4620;
QUERY PLAN
---------------------------------------------------------------------------------
Index Scan using id_idx on edges (cost=0.00..101.61 rows=3067 width=4) (actual time=135.507..157.982 rows=1052 loops=1)
Index Cond: (id = 4620)
Total runtime: 158.348 ms
(3 rows)
Sin embargo, si la búsqueda de los enlaces entrantes a un nodo, la base de datos es más de 100 veces más lento (aunque el número resultante de entrantes enlaces es sólo 5-10 veces mayor que el número de enlaces salientes):
=# explain analyze select id from edges where link=4620;
QUERY PLAN
----------------------------------------------------------------------------------
Bitmap Heap Scan on edges (cost=846.31..100697.48 rows=51016 width=4) (actual time=322.584..48983.478 rows=26887 loops=1)
Recheck Cond: (link = 4620)
-> Bitmap Index Scan on link_idx (cost=0.00..833.56 rows=51016 width=0) (actual time=298.132..298.132 rows=26887 loops=1)
Index Cond: (link = 4620)
Total runtime: 49001.936 ms
(5 rows)
traté de forzar Postgres no utilizar una exploración de mapa de bits a través de
=# set enable_bitmapscan = false;
pero la velocidad de la consulta para los enlaces entrantes no mejoró:
=# explain analyze select id from edges where link=1588;
QUERY PLAN
-------------------------------------------------------------------------------------------
Index Scan using link_idx on edges (cost=0.00..4467.63 rows=1143 width=4) (actual time=110.302..51275.822 rows=43629 loops=1)
Index Cond: (link = 1588)
Total runtime: 51300.041 ms
(3 rows)
También he aumentado mis buffers compartidos desde 24 MB a 512 MB, pero no sirvió de nada. Entonces, me pregunto por qué mis consultas de enlaces salientes y entrantes muestran un comportamiento tan asimétrico. ¿Hay algún problema con mi elección de índices? ¿O debería crear una tercera tabla que contenga todos los enlaces entrantes para un nodo con id x? Pero eso sería un desperdicio de espacio en el disco. Pero dado que soy nuevo en las bases de datos SQL, quizás me esté perdiendo algo básico aquí.
Probablemente no cambie nada, pero su primera consulta es 'seleccionar id de bordes donde id = 4620' en lugar de 'seleccionar enlace de bordes donde id = 4620'. Con la primera consulta esperaría una respuesta instantánea independientemente del conjunto de datos. –
has ejecutado "ANALIZAR"; o "VACUUM ANALYZE"; en tu base de datos últimamente? – tommym
Jiri, tenías razón. La primera consulta tuvo un error tipográfico. Lo corregí ahora. Pero no cambia el problema. – asmaier