私は約2,000万行のテーブルを持っています。議論のために、テーブルには2つの列、つまりIDとタイムスタンプがあるとします。私は1日あたりのアイテムの数を取得しようとしています。ここには私の瞬間があります。postgresの大きなテーブルの日付クエリによるグループ化の高速化
SELECT DATE(timestamp) AS day, COUNT(*)
FROM actions
WHERE DATE(timestamp) >= '20100101'
AND DATE(timestamp) < '20110101'
GROUP BY day;
インデックスがない場合、これは私のマシンでは約30秒かかります。ここでは、出力を分析し説明します:
GroupAggregate (cost=675462.78..676813.42 rows=46532 width=8) (actual time=24467.404..32417.643 rows=346 loops=1)
-> Sort (cost=675462.78..675680.34 rows=87021 width=8) (actual time=24466.730..29071.438 rows=17321121 loops=1)
Sort Key: (date("timestamp"))
Sort Method: external merge Disk: 372496kB
-> Seq Scan on actions (cost=0.00..667133.11 rows=87021 width=8) (actual time=1.981..12368.186 rows=17321121 loops=1)
Filter: ((date("timestamp") >= '2010-01-01'::date) AND (date("timestamp") < '2011-01-01'::date))
Total runtime: 32447.762 ms
私はシーケンシャルスキャンを見ているので、私は、日付集計にインデックスに約50%の速度をカット
CREATE INDEX ON actions (DATE(timestamp));
を試してみました。
HashAggregate (cost=796710.64..796716.19 rows=370 width=8) (actual time=17038.503..17038.590 rows=346 loops=1)
-> Seq Scan on actions (cost=0.00..710202.27 rows=17301674 width=8) (actual time=1.745..12080.877 rows=17321121 loops=1)
Filter: ((date("timestamp") >= '2010-01-01'::date) AND (date("timestamp") < '2011-01-01'::date))
Total runtime: 17038.663 ms
私はこの全体的なクエリ最適化ビジネスに慣れていないため、次に何をすべきか分かりません。どのように私はこのクエリをより速く実行させることができたのか?
--edit--
私は指標の限界を打ってるように見えます。これは、このテーブルで実行される唯一のクエリです(ただし、日付の値は変更されます)。テーブルを分割する方法はありますか?または、すべてのカウント値を持つキャッシュテーブルを作成しますか?または他のオプション?
あなたはここに全体の話をしていますか?第1プランと第2プランの間でメモリ設定を変更したようです。それは私のアドバイスだったでしょう。 ;-) –
メモリの設定は変更されていませんが、スキーマの変更ごとにバキューム分析を行っています。私がそれをするべきかどうかわからないが、それは結果に真剣に影響する。 – zaius