- - PR -
postgresの副問い合わせについて
1
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2005-11-22 11:01
はじめまして ここに投稿させて頂くのは初めてです。
今回ASP.NETとpostgresで開発を行っているのですが postgresのSQLにつてい教えて下さい。 今あるテーブルからある条件で2件より少ないレコードを 条件としてデータを抽出するSQLを作成したのですが、 とてもコストが高く使える状態ではありません。 inを使った副問い合わせは遅いということでEXISTSもつか ったのですがどうもコストは同じになってしまいます。 SQL: select jh.ky_ubin1,jh.ky_ubin2,jh.ky_add1,jh.ky_add2, jh.ky_name1,jh.ky_name2, se.section_name,jh.syain_cd,sm.syain_name,jm.maru_cd,jm.syohin_name, jm.h_tanka,jm.suryo,(jm.suryo*jm.h_tanka) as price,jh.seiri_no,jm.gyo_no, jm.mise_cd,ha.hanbai_name,jh.nen,JH.jyutyu_ymd,JH.denout_flg from (jyu_h as jh join jyu_m as jm on (jh.nen = jm.nen and jh.mise_cd = jm.mise_cd and jh.seiri_no = jm.seiri_no and jh.keijyo_kbn = jm.keijyo_kbn) left join syain_mst as sm on (jh.mise_cd = sm.mise_cd and jh.syain_cd = sm.syain_cd) left join hanbai_mst as ha on (jh.hanbai_cd = ha.hanbai_cd) left join section_mst as se on (sm.mise_cd = se.mise_cd and sm.section_cd = se.section_cd)) where exists (select a.nen,a.mise_cd,a.seiri_no,a.del_flg from (select j.nen,j.mise_cd,j.seiri_no,j.del_flg,count(*) as count1 from jyu_h as j where j.del_flg = 0 and j.mise_cd = 3 and j.nen =2005 and j.seiri_no = 'Y-48' group by j.nen,j.mise_cd,j.seiri_no,j.del_flg) a where a.count1 < 2 and a.nen = jh.nen and a.mise_cd = jh.mise_cd and a.seiri_no = jh.seiri_no and a.del_flg = jh.del_flg) inを使用したときのSQL select jh.ky_ubin1,jh.ky_ubin2,jh.ky_add1,jh.ky_add2, jh.ky_name1,jh.ky_name2, se.section_name,jh.syain_cd,sm.syain_name,jm.maru_cd,jm.syohin_name, jm.h_tanka,jm.suryo,(jm.suryo*jm.h_tanka) as price,jh.seiri_no,jm.gyo_no, jm.mise_cd,ha.hanbai_name,jh.nen,JH.jyutyu_ymd,JH.denout_flg from (jyu_h as jh join jyu_m as jm on (jh.nen = jm.nen and jh.mise_cd = jm.mise_cd and jh.seiri_no = jm.seiri_no and jh.keijyo_kbn = jm.keijyo_kbn) left join syain_mst as sm on (jh.mise_cd = sm.mise_cd and jh.syain_cd = sm.syain_cd) left join hanbai_mst as ha on (jh.hanbai_cd = ha.hanbai_cd) left join section_mst as se on (sm.mise_cd = se.mise_cd and sm.section_cd = se.section_cd)) where (jh.nen,jh.mise_cd,jh.seiri_no,jh.del_flg) in (select a.nen,a.mise_cd,a.seiri_no,a.del_flg from (select j.nen,j.mise_cd,j.seiri_no,j.del_flg,count(*) as count1 from jyu_h as j where j.del_flg = 0 and j.mise_cd = 3 and j.nen =2005 and j.seiri_no = 'Y-48' group by j.nen,j.mise_cd,j.seiri_no,j.del_flg) a where a.count1 < 2) QUERY PLAN Merge Join (cost=853263.97..854028.33 rows=149674 width=520) Merge Cond: (("outer".section_cd = "inner".section_cd) AND ("outer".mise_cd = "inner".mise_cd)) -> Sort (cost=1.44..1.48 rows=15 width=103) Sort Key: se.section_cd, se.mise_cd -> Seq Scan on section_mst se (cost=0.00..1.15 rows=15 width=103) -> Sort (cost=853262.53..853636.71 rows=149674 width=417) Sort Key: sm.section_cd, sm.mise_cd -> Merge Join (cost=760647.57..763266.97 rows=149674 width=417) Merge Cond: ("outer".hanbai_cd = "inner".hanbai_cd) -> Sort (cost=760645.86..761020.04 rows=149674 width=341) Sort Key: jh.hanbai_cd -> Merge Join (cost=683742.89..684540.30 rows=149674 width=341) Merge Cond: (("outer".mise_cd = "inner".mise_cd) AND ("outer".syain_cd = "inner".syain_cd)) -> Sort (cost=2.73..2.85 rows=46 width=86) Sort Key: sm.mise_cd, sm.syain_cd -> Seq Scan on syain_mst sm (cost=0.00..1.46 rows=46 width=86) -> Sort (cost=683740.16..684114.34 rows=149674 width=255) Sort Key: jh.mise_cd, jh.syain_cd -> Hash Join (cost=594979.46..623714.60 rows=149674 width=255) Hash Cond: ("outer".seiri_no = "inner".seiri_no) Join Filter: (("inner".nen = "outer".nen) AND ("inner".mise_cd = "outer".mise_cd) AND ("inner".keijyo_kbn = "outer".keijyo_kbn)) -> Seq Scan on jyu_m jm (cost=0.00..10505.47 rows=300147 width=108) -> Hash (cost=593802.30..593802.30 rows=50062 width=147) -> Seq Scan on jyu_h jh (cost=0.00..593802.30 rows=50062 width=147) Filter: (subplan) SubPlan -> Subquery Scan a (cost=5.85..5.87 rows=1 width=44) -> Aggregate (cost=5.85..5.87 rows=1 width=44) Filter: (count(*) < 2) -> Group (cost=5.85..5.87 rows=1 width=44) -> Sort (cost=5.85..5.86 rows=1 width=44) Sort Key: nen, mise_cd, seiri_no, del_flg -> Index Scan using testindex on jyu_h j (cost=0.00..5.84 rows=1 width=44) Index Cond: ((nen = 2005::numeric) AND (nen = $0) AND (mise_cd = 3::numeric) AND (mise_cd = $1) AND (seiri_no = 'Y-48'::character varying) AND (seiri_no = $2)) Filter: ((del_flg = 0::numeric) AND (del_flg = $3)) -> Sort (cost=1.71..1.77 rows=22 width=76) Sort Key: ha.hanbai_cd -> Seq Scan on hanbai_mst ha (cost=0.00..1.22 rows=22 width=76) インデックスはnen,mise_cd,del_flg,seiri_noとはってはいるの ですがどこでコストをとっているのかいろいろ調べてみてはいるの ですがよくわかりません。postgresは初めて使用するのでこれから また調べてみようと思いますが何かわかる方がおられましたらよろ しくお願いします。 |
|
投稿日時: 2005-11-22 11:41
とりあえずJOINするキーにすべてJOINする条件の組み合わせでインデックスが作成されているか確認されてはどうでしょうか。
コストはほとんどJOINとソートのコストの様なので適切なインデックスが作成されていれば、かなりコストは改善するはずです。 |
|
投稿日時: 2005-11-22 11:44
バージョンを書かれていないので分かりませんが、PostgreSQL で副問合せが非常に遅かったことは有名ですが、その問題は 7.4 で修正されたように思います。
|
|
投稿日時: 2005-11-22 13:23
返答ほんとうにありがとうございます。
訂正事項がありましてDBの方なんですが PowerGresでバージョンは7.3.6となっています。 結合についての質問なのですが、 >JOINするキーにすべてJOINする条件の組み合わせでインデックスが作成されているか確認され>てはどうでしょうか。 というのは例えば テーブル:TABA 列:a,b,c テーブル:TABB 列:d,e,f テーブル:TABC 列:g,h,i とあった時にテーブルTABA,TABBをa,b c,dで結合した場合 TABA に対してインデックスをa,b TABB に対してインデックスをc,d この二つを結合したものにTABCを結合するとして たとえば a,b g,h が結合するとすると TABC に対してインデックスをg,hと作成すればよいという ことでしょうか? 宜しくお願いします。 |
1