[pgsql-jp: 41593] Re: order by での indexの利用について
prod2011 @ yahoo.co.jp
prod2011 @ yahoo.co.jp
2014年 3月 14日 (金) 15:00:06 JST
こんにちは。Prodです。
花田様、高塚様
ご返信ありがとうございます。
こちらからの返信が遅くなり、申し訳ございません。
また、提示したSQLですが、簡略した時に、
簡略化しすぎてしまい、別物の状態になってしまっておりました。
あらためて、SQLを張り付けさせていただきます。
大変申し訳ございません。深くお詫びいたします。
--SQL------------------------------------
SELECT
a.col1
, a.col2
, a.col3
, a.col4
, a.col5
, b.col6
, b.col7 ~ b.col39
FROMtable_a a
INNER JOIN table_b b ON a.col1 = b.col1
where a.col2 = '000001'
AND a.col3 = '1'
AND a.col4 >= '20110313'
AND a.col4 <= '20140313'
ORDER BY
a.col4
,a.col5
,b.col6
offset 0 limit 500
--複合インデックスで以下を設定しております。
table_a : table_a_index2 (col2,col3,col4,col5)
table_b : pk_table_b (col1,col6) ※こちらはテーブルのキー
ここで、order by のb.col6があるとき、ないとき、で全然速度がことなります。
目標としている速度は、2以内秒 です。
explain analyze 結果
-- order by に b.col6 があるとき
QUERY PLAN
Limit (cost=238444.56..238445.81 rows=500 width=422) (actual time=11188.332..11189.201 rows=500 loops=1)
-> Sort (cost=238444.56..240878.37 rows=973526 width=422) (actual time=11188.329..11188.627 rows=500 loops=1)
Sort Key: a.col4, a.col5, b.col6
Sort Method: top-N heapsort Memory: 145kB
-> Hash Join (cost=8309.25..189934.81 rows=973526 width=422) (actual time=412.471..8010.280 rows=1007366 loops=1)
Hash Cond: (b.col1 = a.col1)
-> Seq Scan on table_b b (cost=0.00..52933.17 rows=1054017 width=401) (actual time=0.008..2496.485 rows=1054298 loops=1)
-> Hash (cost=5596.00..5596.00 rows=143940 width=27) (actual time=412.280..412.280 rows=143942 loops=1)
Buckets: 8192 Batches: 4 Memory Usage: 1851kB
-> Seq Scan on table_a a (cost=0.00..5596.00 rows=143940 width=27) (actual time=0.007..222.787 rows=143942 loops=1)
Filter: ((col4 >= 20110313) AND (col4 <= 20140313) AND ((col2)::text = '000001'::text) AND ((col3)::text = '1'::text))
Total runtime: 11191.317 ms
-- order by に b.col6 がないとき
QUERY PLAN
Limit (cost=0.00..1045.56 rows=500 width=422) (actual time=0.137..3.933 rows=500 loops=1)
-> Nested Loop (cost=0.00..2035757.68 rows=973526 width=422) (actual time=0.134..3.262 rows=500 loops=1)
-> Index Scan using table_a_index2 on table_a a (cost=0.00..169939.99 rows=143940 width=27) (actual time=0.110..0.205 rows=72 loops=1)
Index Cond: (((col2)::text = '000001'::text) AND ((col3)::text = '1'::text) AND (col4 >= 20110313) AND (col4 <= 20140313))
-> Index Scan using pk_table_b on table_b b (cost=0.00..12.87 rows=7 width=401) (actual time=0.009..0.018 rows=7 loops=72)
Index Cond: (col1 = a.col1)
Total runtime: 4.541 ms
テーブルの物理サイズです。
table_a 22257664
table_b 347283456
自分で試したときは、Order byを変えると、スピードが変わったために、
Order byでIndexを使っている。使っていない。が原因と思っておりましたが、
ご指摘いただいた、explain から見ると、Order byとかではなく、whereでindexをつかう
使わない。ということが原因だと思います。
しかし、解決策が見つかっておりません。
アドバイスをいただけると、幸いです。
explain等の確認もろくにできておらず、申し訳ございません。
今後は注意いたします。
--
----- Original Message -----
> From: 花田 茂 <hanada @ metrosystems.co.jp>
> To: prod2011 @ yahoo.co.jp; PostgreSQL Japanese Mailing List <pgsql-jp @ ml.postgresql.jp>
> Cc:
> Date: 2014/3/13, Thu 14:48
> Subject: Re: [pgsql-jp: 41589] order by での indexの利用について
>
> 花田です。
>
> (2014/03/13 11:32), prod2011 @ yahoo.co.jp wrote:
>> こんにちは、prodと申します。
>>
>> テーブルを連結してOrder byした後で、limit かけて500件表示
>>
>> といった処理をしていますがデータの取得が遅く、
>> 困っています。
>>
>> 環境は以下です
>>
>> サーバOS:Red Hat Enterprise Linux Server release 5.3
>> Postgresバージョン:PostgreSQL 9.1.2
>>
>> 具体的には以下のようなSQLです
>>
>> select
>> a.col1
>> ,a.col2
>> ,a.col3
>> ,b.col1
>> ,b.col2
>> from table_a a
>> inner join table_b b (a.col1=b.col1)
>> order by a.col1,a.col2,b.col1
>> offset 0 limit 500
>>
>>
>> table_a には a.col1,a.col2 で indexを作成しており、
>> table_b には b.col1 で indexを作成しております。
>> (index は btreeです)
>>
>> このまま実行すると、データの取得に時間がかかり、
>> 困っています。
>>
>>
>> order byからb.col1を除くと、Order byで、
>> a.col1,a.col2のindexを使ってくれるようになり、非常に高速となるのですが、
>> b.col1を order by に追加すると、indexを使ってくれません。
>>
>>
>> order by a.col1,a.col2,b.col1
>> としても、 a.col1,a.col2 のindexは使ってくれる。
>> といったようにはならないものなのでしょうか?
>> また、他の方法でもいいですが、高速かすために良い方法は
>
> INNER JOINの結合条件で a.col1 = b.col1としているので、b.col1はなくても同
> じ結果になりそうな気もしますが…
>
>>
>> ございますでしょうか?
>>
>> 件数:table_a 20万件
>> table_b 100万件
>> 程度です。
>>
>> アドバイスいただけますと、幸いです。
>>
>>
>
> こういったチューニングでは、まずEXPLAIN結果(できればANALYZEオプションつ
> き)を見るのが王道です。テーブル名などは区別がつけばマスキングしてあって
> もよいので、ORDER BY に b.col1を指定した場合としていない場合の EXPLAIN
> ANALYZE 結果を提示できないでしょうか?
>
> また、もし未実施であれば、ANALYZEコマンドで統計情報を更新してみてください。
>
>
> --
> 株式会社メトロシステムズ
> 花田 茂
> Mail : hanada @ metrosystems.co.jp
> Tel : 03-5951-1219
> Fax : 03-5951-2929
>
pgsql-jp メーリングリストの案内