makoto_blog

パパさん_blog

プログラミング勉強メモや雑記など。

SQL実行計画を読めると何が嬉しいのか 実践1

参考サイト

gihyo.jp

書籍:SQL実践入門 もご参考に。

実行計画の比較

最近、実行計画の読み方を勉強しています。
でも、読めると何が嬉しいのかがいまいちわかりません。

makotodb=> select * from items;
 item_id | shop_id |              item_name               | price 
---------+---------+--------------------------------------+-------
 10001   | 10000   | pc                                   | 40000
 10002   | 10000   | モニタ                               | 12000
 10003   | 10000   | マウス                               |  5000
 20001   | 20000   | ジュース                             |   120
 20002   | 20000   | あんまん                             |   100
 20003   | 20000   | チョコ                               |   150
(6 rows)

このテーブルから、shop_idが20000の店舗に値上げを指示します。

select item_id
     , shop_id
     , item_name
     , price
  from items
 where shop_id = '10000'
 union all
 select item_id
     , shop_id
     , item_name
     , price * 1.5
  from items
 where shop_id = '20000'
;
 item_id | shop_id |              item_name               | price 
---------+---------+--------------------------------------+-------
 10001   | 10000   | pc                                   | 40000
 10002   | 10000   | モニタ                               | 12000
 10003   | 10000   | マウス                               |  5000
 20001   | 20000   | ジュース                             | 180.0
 20002   | 20000   | あんまん                             | 150.0
 20003   | 20000   | チョコ                               | 225.0
(6 rows)

このクエリの実行計画は以下の通りです。

                               QUERY PLAN                               
------------------------------------------------------------------------
 Append  (cost=0.00..2.23 rows=6 width=212)
   ->  Subquery Scan on "*SELECT* 1"  (cost=0.00..1.11 rows=3 width=82)
         ->  Seq Scan on items  (cost=0.00..1.07 rows=3 width=54)
               Filter: (shop_id = '10000'::bpchar)
   ->  Seq Scan on items items_1  (cost=0.00..1.09 rows=3 width=82)
         Filter: (shop_id = '20000'::bpchar)
(6 rows)

Seq というのがフルスキャンの事なのですが、2回発生していることがわかります。
ディスクI/Oはコストになるので以下のクエリに変えてみます。

select item_id
     , shop_id
     , item_name
     , case when shop_id = '20000' then price * 1.5
            else price end
  from items
;

最初のクエリと同じ結果が得られます。
実行計画は以下の通りです。

                      QUERY PLAN                      
------------------------------------------------------
 Seq Scan on items  (cost=0.00..1.12 rows=6 width=82)
(1 row)

フルスキャンが1回に減っています。

これは簡単な例なので実行計画を見なくてもunionを選択することはないと思うのですが、実行計画を読めると嬉しいことの1つはこういう事なのかなと思いました。

スキャン多いよね、、減らす方法を考えよう

っていう風に思えること。