0

私は7.4を実行しているPostgres DBを持っています(ええ、私たちはアップグレードの真っ最中です)

日次、月次、年次、および生涯のレコード数を取得するための 4 つの個別のクエリがあります。

SELECT COUNT(field)
FROM database
WHERE date_field
    BETWEEN DATE_TRUNC('DAY' LOCALTIMESTAMP) 
    AND DATE_TRUNC('DAY' LOCALTIMESTAMP) + INTERVAL '1 DAY'

DAY月の場合は、クエリ内の単語をMONTH期間ごとに置き換えるだけです。

1 つのクエリで目的の結果をすべて取得する方法と、推奨される最適化についてのアイデアを探しています。

前もって感謝します!

注: date_field はタイムゾーンなしのタイムスタンプです

アップデート:

申し訳ありませんが、追加のクエリ制約を使用してレコードを除外しています。date_field 比較の要点を伝えたかっただけです。混乱を招いて申し訳ありません

4

3 に答える 3

1

そのために、準備されたステートメントと単純な統計 (record_count_t) テーブルを使用する考えがあります。

-- DROP TABLE IF EXISTS record_count_t;
-- DEALLOCATE record_count;
-- DROP FUNCTION updateRecordCounts();

CREATE TABLE record_count_t (type char, count bigint);
INSERT INTO record_count_t (type) VALUES ('d'), ('m'), ('y'), ('l');

PREPARE record_count (text) AS
UPDATE record_count_t SET count =
(SELECT COUNT(field)
FROM database
WHERE
CASE WHEN $1 <> 'l' THEN
    DATE_TRUNC($1, date_field) = DATE_TRUNC($1, LOCALTIMESTAMP)
ELSE TRUE END)
WHERE type = $1;

CREATE FUNCTION updateRecordCounts() RETURNS void AS
$$
    EXECUTE record_count('d');
    EXECUTE record_count('m');
    EXECUTE record_count('y');
    EXECUTE record_count('l');
$$
LANGUAGE SQL;

SELECT updateRecordCounts();
SELECT type,count FROM record_count_t;

統計を更新する必要がある場合は、いつでも updateRecordCounts() 関数を使用してください。

于 2011-05-25T19:50:13.360 に答える
0

これをこれ以上最適化することは不可能だと思います。

日次/月次/年次の統計を収集している場合、私が想定しているように、1 つのオプション (もちろん、アップグレード後) はwith ステートメントと関連する結合です。

with daily_stats as (
(what you posted)
),
monthly_stats as (
(what you posted monthly)
),
etc.
select daily_stats.stats,
       monthly_stats.stats,
       etc.
stats
left join yearly_stats on ...
left join monthly_stats on ...
left join daily_stats on ...

ただし、実際には本番環境で各クエリを個別に実行するよりもパフォーマンスが低下します。これは、ミドルウェアでも同様に実行できる左結合を DB に導入するためです (つまり、日次、月次、年次、最後に表示)生涯統計)。(完全なテーブルスキャンを回避するため、良くない場合。)

あたかも物事を維持することで、貴重な DB リソースを節約して、実際のデータの読み取りと書き込みを処理できます。トレードオフ (データベースとアプリ間のネットワーク トラフィックの減少) は、ほとんどの場合、それだけの価値はありません。

于 2011-05-25T19:17:34.800 に答える