1GB RAM 및 Mac OS X 10.5.8이 장착 된 1.83GHz Intel Core Duo Mac Mini에 PostgreSQL 8.3을 실행하고 있습니다. 내 PostgreSQL 데이터베이스에 거대한 그래프가 저장되어 있습니다. 160 만 개의 노드와 3 천만 개의 에지로 구성됩니다.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
...
은 그래서 아이디 Y에 나가는 링크 X ID 각 노드에 대한 저장과 같습니다처럼 내 데이터베이스 스키마입니다.
모든 나가는 링크를 검색하기위한 시간은 괜찮 :
=# 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)
그러나, 나는이 노드로 들어오는 링크를 검색하면, 데이터베이스 (100 배 이상 느리지 만 수신의 결과 수 내가
,627,211,714,288,458,321를 통해 비트 맵 검색을 사용하지 포스트 그레스를 강제로 시도=# 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가있는 노드에 대해 들어오는 모든 링크를 포함하는 세 번째 테이블을 생성해야합니까? 그러나 그것은 디스크 공간을 낭비하게 만듭니다. 하지만 SQL 데이터베이스에 익숙하지 않으므로 여기에 기본적인 것을 놓치고 있을까요?
아마도 아무 것도 변경하지 않지만 첫 번째 쿼리는 'id = 4620 에지에서 링크 선택'대신 'id = 4620 인 에지에서 ID 선택'입니다. 첫 번째 쿼리를 사용하면 데이터 세트에 관계없이 즉시 응답을 기대할 수 있습니다. –
"ANALYZE;를 실행하십시오." 또는 "VACUUM ANALYZE;" 최근에 데이터베이스에? – tommym
지리, 네가 옳았다. 첫 번째 쿼리에는 오타가있었습니다. 나는 지금 그것을 바로 잡았다. 하지만 문제는 변하지 않습니다. – asmaier