Io corro PostgreSQL 8.3 su un 1,83 GHz Intel Core Duo Mac Mini con 1GB di RAM e Mac OS X 10.5.8. Ho conservato un enorme grafico nel mio database PostgreSQL. Consiste di 1,6 milioni di nodi e 30 milioni di spigoli. Il mio schema del database è simile:PostgreSQL: Come ottimizzare il mio database per l'archiviazione e l'interrogazione di un enorme grafico
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);
I dati nella tabella i bordi assomiglia
id link
1 234
1 88865
1 6
2 365
2 12
...
Quindi memorizza per ogni nodo con id x il link in uscita per id y.
Il tempo per la ricerca tutti i link in uscita è ok:
=# 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)
Tuttavia, se cerco per i collegamenti in entrata a un nodo, il database è più di 100 volte più lento (anche se il numero risultante di entrata link è il solo 5-10 volte superiore al numero di link in uscita):
=# 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)
ho cercato di forzare Postgres non utilizzare una scansione bitmap tramite
=# set enable_bitmapscan = false;
ma la velocità della query per i link in entrata non è migliorata:
=# 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)
ho anche aumentato il mio buffer condivisi da 24MB a 512MB, ma non ha aiutato. Quindi mi chiedo perché le mie query per i link in uscita e in entrata mostrano un comportamento asimmetrico simile? C'è qualcosa di sbagliato nella mia scelta di indici? O dovrei creare meglio una terza tabella contenente tutti i link in entrata per un nodo con id x? Ma sarebbe uno spreco di spazio su disco. Ma dato che sono nuovo nei database SQL forse mi manca qualcosa di base qui?
Probabilmente non cambia nulla, ma la tua prima query è 'seleziona l'id dai bordi dove id = 4620' invece di 'seleziona il link dai bordi dove id = 4620'. Con la prima query mi aspetterei una risposta immediata indipendentemente dal set di dati. –
hai eseguito "ANALIZZA;" o "VACUUM ANALYZE;" sul tuo database ultimamente? – tommym
Jiri, avevi ragione. La prima query ha avuto un errore di battitura. L'ho corretto ora. Ma non cambia il problema. – asmaier