私は1.83 GHzのIntel Core Duo Mac Miniに1GBのRAMとMac OS X 10.5.8のPostgreSQL 8.3を実行しています。私はPostgreSQLデータベースに巨大なグラフを保存しています。 160万のノードと3000万のエッジで構成されています。PostgreSQL:データベースを最適化して巨大なグラフを保存する方法
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);
テーブルエッジのデータが
id link
1 234
1 88865
1 6
2 365
2 12
...
はだから、ID yに発信リンクX IDを持つノードごとに記憶するようになります。私のようなデータベーススキーマです。
すべての発信リンクを検索するための時間がOK:私は、ノードへの着信リンクを検索する場合は、データベースが100倍以上遅い
=# 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)
(受信の結果として得られる数であるが私は
を経由してビットマップスキャンを使用しないのPostgresを強制しようとした=# 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)
:リンクは外部リンクの数)よりもわずか5〜10倍高いです0
が、着信リンクのクエリの速度が改善されなかった。
=# 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)
また、私は512メガバイトに24メガバイトから私の共有バッファを増加させたが、それは助けにはなりませんでした。だから私は発信と着信リンクのクエリがそのような非対称な振る舞いを示すのはなぜだろうか?インデックスの選択に何か問題がありますか?または、ID xのノードのすべての受信リンクを保持する3番目のテーブルを作成する方がよいでしょうか?しかし、それはかなりのディスク容量を浪費します。しかし、私はSQLデータベースを初めて使っているので、ここで何か基本的なものが欠けているかもしれません。
これはおそらく何も変更しませんが、最初のクエリは 'select from edges where id = 4620'の代わりに 'id = 4620 edges from id = 4620'です。最初のクエリでは、データセットに関係なく即時回答が期待されます。 –
"ANALYZE;を実行しましたか?"または "VACUUM ANALYZE;"最近あなたのデータベースに? – tommym
Jiri、あなたは正しいです。最初のクエリにはタイプミスがありました。私は今それを修正しました。しかし、それは問題を変えない。 – asmaier