- 締切済み
POSTGRESQL 検索スピードが遅い
テーブル結合検索、インデックス使えない原因を Aテーブルは200000件のデータがあり、Bテーブルは4000000件のデータがあります。 テーブルA(ヘッダ) A001 NUMBER(10) NOT NULL, A002 NUMBER(8) NOT NULL, A003 CHARACTER(2) NOT NULL, ... PRIMARY KEY(A001) INDEX A1(A002, A003) テーブルB(明細) B001 NUMBER(10) NOT NULL, B002 NUMBER(3) NOT NULL, B003 NUMBER(7) NOT NULL, ... PRIMARY KEY(B001,B002) INDEX A1(B001) SELECT A.A001, B.B003 FROM A, B WHERE A.A001 = B.B001 AND A.A002 >= 20090728 AND A.A002 <= 20090801 AND A.A003 = '01' 実行計画を見ると、Bテーブルのインデックスが使わなかった。 同じSQLで、条件だけ変わると、Bテーブルのインデックスが使った。 SELECT A.A001, B.B003 FROM A, B WHERE A.A001 = B.B001 AND A.A002 >= 20090728 AND A.A002 <= 20090731 AND A.A003 = '01' 原因を知りたいです。 また、他のHPからテーブルの結合の説明がありました、 直積結合の回避 * 直積結合は、結合対象の2つのテーブルの全レコードの組み合わせを戻す処理 * SQLが複雑で、結合条件や絞込み条件に漏れがあると直積結合が選択されるかも tableA = 1000 件、 tableB = 2 万件 の直積結合 1,000 * 20,000 = 20,000,000 2000 万件処理されてしまう が、結果が正しいと気付かない事も。 データ量が増加すれば、致命的な性能劣化に 参考URL: http://www.slideshare.net/kwappa/20090107-postgre-sqlsql-presentation 上記のこと教えていただきたいんです、お願いします。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- yamada59
- ベストアンサー率74% (29/39)
補足
explain analyze select a.* from ar06kakh a , ar07kakm b where a.ar06001 = b.ar07001 and a.ar06005 >= 20060830 and a.ar06005 <= 20060831 and a.ar06009 = '01' 上記の条件で実行計画をやると、下記の結果が出てきます。 "Nested Loop (cost=0.00..12432.40 rows=1022 width=344) (actual time=37.445..4186.452 rows=6636 loops=1)" " -> Index Scan using ar06_key13 on ar06kakh a (cost=0.00..93.60 rows=46 width=344) (actual time=0.046..43.635 rows=336 loops=1)" " Index Cond: ((ar06005 >= 20060830::numeric) AND (ar06005 <= 20060831::numeric) AND (ar06009 = '01'::bpchar))" " -> Index Scan using ar07_key17 on ar07kakm b (cost=0.00..257.28 rows=876 width=8) (actual time=5.605..12.306 rows=20 loops=336)" " Index Cond: (b.ar07001 = a.ar06001)" "Total runtime: 4188.728 ms" explain analyze select a.* from ar06kakh a , ar07kakm b where a.ar06001 = b.ar07001 and a.ar06005 >= 20060830 and a.ar06005 <= 20060901 and a.ar06009 = '01' 同じSQL、検索期間だけ変わると、下記のような結果が出てきます。 "Hash Join (cost=6147.61..362891.32 rows=72833 width=344) (actual time=543.516..166040.292 rows=9678 loops=1)" " Hash Cond: (b.ar07001 = a.ar06001)" " -> Seq Scan on ar07kakm b (cost=0.00..302154.25 rows=4192225 width=8) (actual time=29.452..106880.430 rows=4192225 loops=1)" " -> Hash (cost=5958.64..5958.64 rows=3278 width=344) (actual time=203.584..203.584 rows=500 loops=1)" " -> Index Scan using ar06_key13 on ar06kakh a (cost=0.00..5958.64 rows=3278 width=344) (actual time=0.229..189.109 rows=500 loops=1)" " Index Cond: ((ar06005 >= 20060830::numeric) AND (ar06005 <= 20060901::numeric) AND (ar06009 = '01'::bpchar))" "Total runtime: 166043.673 ms" 因みに、索引は下記のようです。 ar06_key0:AR06001 … ar06_key13:AR06005、AR06009 ar07_key0:AR07001、AR07002 … ar07_key17:AR07001 また、AR06005のデータは日付を「YYYYMMDD」の形式のNUMERICです。 AR06005の日付毎にデータの件数は大体同じぐらいです(100~200件)。 AR06001のAR07KAKMのデータが1~300件ぐらいです。