ねもぷらす

ふぁいんでぃんぐねもの日記。プログラミングとか育児とか

なぜ一括集計が出来ないのか

ファイル読み込みなら可能なのに、DBだと出来ない謎…
テーブル結合して UPDATE って出来ないのかな??


と思ってごそごそしてたら、UPDATE の WHERE節でテーブル結合できるっぽいね☆

  • IDテーブル
CREATE TABLE owner (
    id bigint NOT NULL,
    create_date timestamp with time zone NOT NULL,
    name text NOT NULL
);
  • 統計テーブル
CREATE TABLE summary (
    id bigint NOT NULL,
    update_date timestamp with time zone NOT NULL,
    count integer
);
  • UPDATE文
UPDATE summary SET count = count + 10 WHERE summary.id = owner.id;
  • コスト ( EXPLAIN )
# EXPLAIN SELECT * FROM owner, summary WHERE owner.id = summary.id ;
                               QUERY PLAN                               
------------------------------------------------------------------------
 Merge Join  (cost=173.99..291.06 rows=7475 width=68)
   Merge Cond: ("outer".id = "inner".id)
   ->  Sort  (cost=69.16..71.63 rows=990 width=48)
         Sort Key: "owner".id
         ->  Seq Scan on "owner"  (cost=0.00..19.90 rows=990 width=48)
   ->  Sort  (cost=104.83..108.61 rows=1510 width=20)
         Sort Key: summary.id
         ->  Seq Scan on summary  (cost=0.00..25.10 rows=1510 width=20)
(8 rows)


# EXPLAIN UPDATE summary SET count = count + 10 WHERE summary.id = owner.id;
                               QUERY PLAN                               
------------------------------------------------------------------------
 Merge Join  (cost=173.99..309.75 rows=7475 width=26)
   Merge Cond: ("outer".id = "inner".id)
   ->  Sort  (cost=69.16..71.63 rows=990 width=8)
         Sort Key: "owner".id
         ->  Seq Scan on "owner"  (cost=0.00..19.90 rows=990 width=8)
   ->  Sort  (cost=104.83..108.61 rows=1510 width=26)
         Sort Key: summary.id
         ->  Seq Scan on summary  (cost=0.00..25.10 rows=1510 width=26)
(8 rows)


…うーんコストが高い希ガス
ちなみに全部のレコードを持つとどうだろ???

CREATE TABLE all_table (
    id bigint NOT NULL,
    create_date timestamp with time zone NOT NULL,
    name text NOT NULL,
    update_date timestamp with time zone NOT NULL,
    count integer
);
# EXPLAIN SELECT * FROM all_table ;
                         QUERY PLAN                          
-------------------------------------------------------------
 Seq Scan on all_table  (cost=0.00..18.60 rows=860 width=60)
(1 row)

# EXPLAIN UPDATE all_table SET count = count + 10 where id = 1;
                        QUERY PLAN                         
-----------------------------------------------------------
 Seq Scan on all_table  (cost=0.00..20.76 rows=5 width=66)
   Filter: (id = 1)
(2 rows)

…まぁそりゃそうだぁな…やるまでもなかった…
外部結合とかしとけば早いのかな…ガチガチにしたくないけど、MySQLだと外部結合自体なかったような気がするので、高速化は可能だと思うのですがーーーー上記は悪い例。というか考えなさすぎ。。
何がいけないのか…*1

*1:しいて言えば環境が悪い!室温が低すぎるヨ〜室内なのに息が白いwww