2月 172014
 

Speaker Deck ってなんだろ?っと思って使って見ようと思ったのがこのエントリーの始まり。GitHub のアカウントでログインして、PDF をアップロードするだけでいいんだね。楽ちんだ。

以前に group by と distinct 速度評価 として調査したのは、次の資料を作るためだった。

「どっちでもいいよね」みたいな事言っている後輩がいたので、んなわけあるかー って調べていたら、意外とどっちでもいいのかもって思い始めた。

9月 252013
 

久々に更新した。 RedHat Enterprise Linux 等の有償ディストリビューションに付いている PostgreSQL を使っているなら、ディストリビューションのライフサイクルが適用されるだろうけど。

End Of Life (EOL) dates

Version EOL Date Release Date
6.3 2003 年 3 月 1998 年 3 月
6.4 2003 年 10 月 1998 年 10 月
6.5 2004 年 6 月 1999 年 6 月
7.0 2005 年 5 月 2000 年 5 月
7.1 2006 年 4 月 2001 年 4 月
7.2 2007 年 2 月 2002 年 2 月
7.3 2007 年 11 月 2002 年 11 月
7.4 2010 年 10 月(延長) 2003 年 11 月
8.0 2010 年 10 月(延長) 2005 年 1 月
8.1 2010 年 11 月 2005 年 11 月
8.2 2011 年 12 月 2006 年 12 月
8.3 2013 年 2 月 2008 年 2 月
8.4 2014 年 7 月 2009 年 7 月
9.0 2015 年 9 月 2010 年 9 月
9.1 2016 年 9 月 2011 年 9 月
9.2 2017 年 9 月 2012 年 9 月
9.3 2018 年 9 月 2013 年 9 月
9.4 2019 年 12 月 2014 年 12 月
9.5 2021 年 1 月 2016 年 1 月

参考 URL: PostgreSQL Release Support Policy

9月 152013
 

後輩が複数件あるデータからユニークなデータを作る時に distinct
を使っていた。 俺は group by
の方が高速だよと何か読んだことがあったのでちょっと驚いた。

とりあえず指摘はしたんだけど、どうにも腑に落ちなかったので、実際にどちらが良いのか自分なりに調べてみた。

共通条件

  • 某クラウド、メモリ 2GB
  • レコード件数 10万件
  • name には 47都道府県名がランダムに入っている ○使用テーブル

条件1:PostgreSQL 7.4 の時

  • EXPLAIN ANALYZE select distinct on (name) name FROM pgtest;
    Unique ->Sort ->Seq Scan on pgtest

    Total runtime: 3223.304 ms

  • EXPLAIN ANALYZE select distinct name FROM pgtest;
    Unique ->Sort ->Seq Scan on pgtest

    Total runtime: 3206.429 ms

  • EXPLAIN ANALYZE select name from pgtest group by name;
    HashAggregate ->Seq Scan on pgtest

    Total runtime: 272.049 ms

条件2:PostgreSQL 7.4 で name にインデックスをはった時

  • EXPLAIN ANALYZE select distinct on (name) name FROM pgtest;
    Unique ->Sort ->Seq Scan on pgtest

    Total runtime: 3219.604 ms

  • EXPLAIN ANALYZE select distinct name FROM pgtest;
    Unique ->Sort ->Seq Scan on pgtest

    Total runtime: 3217.941 ms

  • EXPLAIN ANALYZE select name from pgtest group by name;
    HashAggregate ->Seq Scan on pgtest

    Total runtime: 267.396 ms

条件3:PostgreSQL 8.4 の時

  • EXPLAIN ANALYZE select distinct on (name) name FROM pgtest;
    Unique ->Sort ->Seq Scan on pgtest

    Total runtime: 2785.410 ms

  • EXPLAIN ANALYZE select distinct name FROM pgtest;
    HashAggregate ->Seq Scan on pgtest

    Total runtime: 233.662 ms

  • EXPLAIN ANALYZE select name from pgtest group by name;
    HashAggregate ->Seq Scan on pgtest

    Total runtime: 230.086 ms

条件4:PostgreSQL 8.4 で name にインデックスをはった時

  • EXPLAIN ANALYZE select distinct on (name) name FROM pgtest;
    Unique ->Index Scan using pgtest_idx1 on pgtest

    Total runtime: 267.068 ms

  • EXPLAIN ANALYZE select distinct name FROM pgtest; Unique ->Index
    Scan using pgtest_idx1 on pgtest

    Total runtime: 267.044 ms

  • EXPLAIN ANALYZE select name from pgtest group by name;
    HashAggregate ->Seq Scan on pgtest

    Total runtime:231.749 ms

条件5:PostgreSQL 9.3 の時

  • EXPLAIN ANALYZE select distinct on (name) name FROM pgtest;
    Unique ->Sort ->Seq Scan on pgtest

    Total runtime: 2902.322 ms

  • EXPLAIN ANALYZE select distinct name FROM pgtest;
    HashAggregate ->Seq Scan on pgtest

    Total runtime:239.562 ms

  • EXPLAIN ANALYZE select name from pgtest group by name;
    HashAggregate ->Seq Scan on pgtest

    Total runtime:235.504 ms

条件6:PostgreSQL 9.3 で name にインデックスをはった時

  • EXPLAIN ANALYZE select distinct on (name) name FROM pgtest;
    Unique ->Index Only Scan using pgtest_idx1 on pgtest

    Total runtime: 222.463 ms

  • EXPLAIN ANALYZE select distinct name FROM pgtest;
    HashAggregate ->Seq Scan on pgtest

    Total runtime: 235.667 ms

  • EXPLAIN ANALYZE select name from pgtest group by name;
    HashAggregate ->Seq Scan on pgtest

    Total runtime: 232.319 ms

俺なりの結論としては、バージョンやインデックスに左右されていない group by の方が良い。