PostgreSQLでテーブルの行数を速く取得する方法

まず、
create table test (id serial primary key, data text);
でテーブルを作成する。
そして、データをインポートする。
カウント関数を呼び出す


lenovo=# select count(*) from test;
count

                • -

4194304
(1 row)


Time: 1040.870 ms

遅いじゃないか

ネットで調べて、いろんな方法がありますが、triggerを使うとか。
面倒くさいと思います。

ほかの方法、pg_classを利用する。試してみると、


lenovo=# select reltuples::integer from pg_class where relname='test';
reltuples

                    • -

4194304
(1 row)


Time: 14.990 ms

正確じゃん。

でも…


lenovo=# insert into test (data) values ('b');
INSERT 0 1
Time: 6.013 ms
lenovo=# select reltuples::integer from pg_class where relname='test';
reltuples

                    • -

4194304
(1 row)


Time: 0.954 ms
lenovo=#

ダメなんだか…
この方法を使う前にvacuumは必要だと聞いた。

そして、私はpgAdminを使うときの何かを思い出した。
スキーマ→public→テーブル→test
右の統計情報に、有効タプルがあります。
pg_classのデータと違って、それは正確だな…

やつはどこにこの情報を取得できるのかな

私はPostgreSQLのステートメントログをオンに設定して、pg_stat_user_tablesから取得できると知りました


lenovo=# select n_live_tup from pg_stat_user_tables where relname='test' and sch
emaname='public';
n_live_tup

                      • -

4194305
(1 row)


Time: 16.763 ms
lenovo=#

これ、はやい。それに、正確だ。

lenovo=# insert into test (data) values ('b');
INSERT 0 1
Time: 1.272 ms
lenovo=# select n_live_tup from pg_stat_user_tables where relname='test' and schemaname='public';
n_live_tup

                      • -

4194306
(1 row)


Time: 14.855 ms
lenovo=#

前に言った問題もない。

なお、ほかの問題があるけど
日本語が下手ので説明はちょっと難しいに感じる
これは結果:


lenovo=# begin transaction;
BEGIN
Time: 0.669 ms
lenovo=# select n_live_tup from pg_stat_user_tables where relname='test' and schemaname='public';
n_live_tup

                      • -

4194306
(1 row)


Time: 16.083 ms
lenovo=# insert into test (data) values ('b');
INSERT 0 1
Time: 0.580 ms
lenovo=# select n_live_tup from pg_stat_user_tables where relname='test' and schemaname='public';
n_live_tup

                      • -

4194306
(1 row)


Time: 2.081 ms
lenovo=# select count(*) from test;
count

                • -

4194307
(1 row)


Time: 1062.131 ms
lenovo=# rollback;
ROLLBACK
Time: 44.899 ms
lenovo=# select n_live_tup from pg_stat_user_tables where relname='test' and schemaname='public';
n_live_tup

                      • -

4194306
(1 row)


Time: 15.594 ms
lenovo=# select count(*) from test;
count

                • -

4194306
(1 row)


Time: 1059.174 ms
lenovo=#

なお何か問題があれば、気軽にツイッターで@sorayukinoyumeへどうぞ。

では。
雷鳴