- PR -

postgresの副問い合わせについて

1
投稿者投稿内容
未記入
大ベテラン
会議室デビュー日: 2005/03/23
投稿数: 105
投稿日時: 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は初めて使用するのでこれから
また調べてみようと思いますが何かわかる方がおられましたらよろ
しくお願いします。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2005-11-22 11:41
とりあえずJOINするキーにすべてJOINする条件の組み合わせでインデックスが作成されているか確認されてはどうでしょうか。
コストはほとんどJOINとソートのコストの様なので適切なインデックスが作成されていれば、かなりコストは改善するはずです。
あんとれ
ぬし
会議室デビュー日: 2004/01/14
投稿数: 556
投稿日時: 2005-11-22 11:44
バージョンを書かれていないので分かりませんが、PostgreSQL で副問合せが非常に遅かったことは有名ですが、その問題は 7.4 で修正されたように思います。
未記入
大ベテラン
会議室デビュー日: 2005/03/23
投稿数: 105
投稿日時: 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

スキルアップ/キャリアアップ(JOB@IT)