1

履歴レコードを保持するテーブルがあります。カウントが更新されるたびに、その時点で新しい値がフェッチされたことを示すレコードが追加されます。テーブル スキーマは次のようになります。

    Column     |           Type           |                             Modifiers
---------------+--------------------------+--------------------------------------------------------------------
 id            | integer                  | not null default nextval('project_accountrecord_id_seq'::regclass)
 user_id       | integer                  | not null
 created       | timestamp with time zone | not null
 service       | character varying(200)   | not null
 metric        | character varying(200)   | not null
 value         | integer                  | not null

ここで、過去 7 日間に毎日更新されたレコードの総数を取得したいと考えています。これが私が思いついたものです:

SELECT
    created::timestamp::date as created_date,
    count(created)
FROM
    project_accountrecord
GROUP BY
    created::timestamp::date
ORDER BY
    created_date DESC
LIMIT 7;

これはゆっくりと実行されます (11406.347ms)。EXPLAIN ANALYZE は以下を提供します。

Limit  (cost=440939.66..440939.70 rows=7 width=8) (actual time=24184.547..24370.715 rows=7 loops=1)
   ->  GroupAggregate  (cost=440939.66..477990.56 rows=6711746 width=8) (actual time=24184.544..24370.699 rows=7 loops=1)
         ->  Sort  (cost=440939.66..444340.97 rows=6802607 width=8) (actual time=24161.120..24276.205 rows=92413 loops=1)
               Sort Key: (((created)::timestamp without time zone)::date)
               Sort Method: external merge  Disk: 146328kB
               ->  Seq Scan on project_accountrecord  (cost=0.00..153671.43 rows=6802607 width=8) (actual time=0.017..10132.970 rows=6802607 loops=1)
 Total runtime: 24420.988 ms

このテーブルには 680 万を少し超える行があります。このクエリのパフォーマンスを向上させるにはどうすればよいですか? 理想的には、1 秒以内に実行して、1 日に数回キャッシュしてバックグラウンドで更新できるようにしたいと考えています。

4

1 に答える 1

2

ここで、クエリはテーブル全体をスキャンし、結果を計算し、最近 7 日間に制限する必要があります。過去 7 日間 (毎日レコードを更新しない場合はそれ以上) のみをスキャンすることで、クエリを高速化できます。

where created_date>now()::date-'7 days'::interval

もう 1 つのアプローチは、過去の結果を追加のテーブルにキャッシュし、現在の日のみをカウントすることです。

于 2013-10-01T10:27:51.397 に答える