[pgsql-jp: 41716] Re: union all時のSubquery Scanの処理内容とパフォーマンス改善について

Tomoaki Sato sato @ sraoss.co.jp
2014年 9月 2日 (火) 00:28:09 JST


佐藤です。

From: kato <carrot-s @ agate.plala.or.jp>
Date: Fri, 29 Aug 2014 22:02:25 +0900

> ご回答ありがとうございます。
> 
> PostgreSQLのバージョンは、9.3.1でした。失礼いたしました。
> 
> SQLそのものは都合により提示できかねるため、
> このような内容にてご質問させて頂いた次第です。
> (せっかくご助言頂いたのに、すみません)
> 
> 質問内容が実行計画の読み方、という点で
> 汎用的な内容のため、このような内容でも何か見解を
> 頂けるかも知れないと考えたのですが、やはり厳しいですかね。。。

もとの質問への答えとしては

>>> 上記、[3]が 15061.768ms で完了した後、[1]のSubquery Scanで
>>> 30795.488ms までかかっている認識です。
>>> 結合処理自体は[3]で終わっていると考えているのですが、
>>> [3]→[1]の間ではどのような処理が行われ、時間がかかっているのか?
>>> また、その処理のパフォーマンスを改善する方法があるのか?
>>> ご存知の方がいらっしゃいましたら、ご教示いただければ幸いです。

Subquery Scan は副問い合わせの結果をスキャンする処理を行います。

単に行数が多い (2300 万行) ので時間がかかっているのだと思います。すでに
共有バッファからデータを読み取っており、Subquery Scan のみでどうにかす
るのは難しいと思います。

はじめに SQL や実行計画の全体を知りたかったのは、全体の実行時間において
Subquery Scan がどのくらいを占めているのか、ほかに何かやれるべきことは
ないかを見たかったからです。

> (2014/08/28 19:53), Tomoaki Sato wrote:
>> 佐藤です。
>>
>>> 加藤と申します。
>>> はじめて利用させていただきます。よろしくお願い致します。
>>>
>>> 以下のようなSQLのパフォーマンスを改善しようとしています。
>>> (便宜上、左端に番号を振っています)
>> SQL は省略せずに実行できるもの、実行計画も抜粋ではなく出力されたそのま
>> まを出してくれれば、力になってくれる人がいるかもしれません。
>>
>> あと、
>>
>>> ------------------------------------
>>> OS:RHEL6.4
>>> PostgreSQL Version:9.4.1
>>> ------------------------------------
>> 9.4 はまだリリースされていないので 8.4.1 の間違いですかね。
>>
>>> 01 select ... from
>>> 02 (
>>> 03 (
>>> 04 select aaa
>>> 05 ,...
>>> 06 from tableA
>>> 07 left outer join tableB1
>>> 08 on (...)
>>> 09 left outer join tableC1
>>> 10 on (...)
>>> 11 where tableA.num2 = 0
>>> 12 and ...
>>> 13 )
>>> 14 union all
>>> 15 (
>>> 16 select aaa
>>> 17 ,...
>>> 18 from tableA
>>> 19 left outer join tableB2
>>> 20 on (...)
>>> 21 left outer join tableC2
>>> 22 on (...)
>>> 23 where tableA.num2 <> 0
>>> 24 and ...
>>> 25 )
>>> 26 ) as t
>>> 27 group by ...
>>> 28 order by ...
>>>
>>> #<補足>
>>> #実際は、union all の上と下それぞれ、もっとたくさんの
>>> #テーブルとleft outer joinしていますが、割愛しています。
>>> #また、テーブル tableAはパーティション化しています。
>>>
>>> 上記のSQLにexplain (analyze on, buffers on)をつけて
>>> 実行した結果、上記番号12〜の部分で以下のような実行計画となりました。
>>>
>>> 以下、番号12〜の部分を抜粋します。(こちらも左端に番号[1]...をふっています)
>>>
>>> [1] ->Subquery Scan on "*SELECT* 2" (cost=7583.21.481866.70 rows=2172792
>>> b.width=1092) (actual time=227.093..30795.488 rows=2304000 loops=1)
>>> [2] Buffers: shared hit=50915
>>> [3] ->Hash Left Join (cost=7583.21..460138.78 rows=2172792 width=1092)
>>> (actual time=227.056..15061.768 rows=2304000 loops=1)
>>> [4] Hash Cond: ((tableA_4.num1=tableC2.num1) AND
>>> (tableA_4.num2=tableC2.num2))
>>> [5] Buffers: shared hit=50915
>>> [6] ->Hash Left Join (cost=7559.71.405795.48 rows=2172792 width=1082)
>>> (actual time=226.747..9133.426 rows=2304000 loops=1)
>>> [7] Hash Cond: ((tableA_4.num1=tableB2.num1) AND
>>> ((tableA_4.text1)::text=(tableB2.text1)::text))
>>> [8] Buffers: shared hit=50908
>>> [9] ...
>>>
>>> 上記、[3]が 15061.768ms で完了した後、[1]のSubquery Scanで
>>> 30795.488ms までかかっている認識です。
>>> 結合処理自体は[3]で終わっていると考えているのですが、
>>> [3]→[1]の間ではどのような処理が行われ、時間がかかっているのか?
>>> また、その処理のパフォーマンスを改善する方法があるのか?
>>> ご存知の方がいらっしゃいましたら、ご教示いただければ幸いです。
>>>
>>> ------------------------------------
>>> OS:RHEL6.4
>>> PostgreSQL Version:9.4.1
>>> ------------------------------------


----
Tomoaki Sato <sato @ sraoss.co.jp>
SRA OSS, Inc. Japan


pgsql-jp メーリングリストの案内