通話の詳細レコードを格納するための数億行の小さなデータベースがあります。次のようにパーティショニングをセットアップします。
http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html
そして、それは今までかなりうまく機能しているように見えました。正しいパーティションに挿入するためのルールを持つマスターテーブル「acmecdr」があり、データを選択するときに正しいテーブルが使用されるようにするための制約をチェックします。パーティションの 1 つの例を次に示します。
cdrs=> \d acmecdr_20130811
Table "public.acmecdr_20130811"
Column | Type | Modifiers
-------------------------------+---------+------------------------------------------------------
acmecdr_id | bigint | not null default
...snip...
h323setuptime | bigint |
acmesipstatus | integer |
acctuniquesessionid | text |
customers_id | integer |
Indexes:
"acmecdr_20130811_acmesessionegressrealm_idx" btree (acmesessionegressrealm)
"acmecdr_20130811_acmesessioningressrealm_idx" btree (acmesessioningressrealm)
"acmecdr_20130811_calledstationid_idx" btree (calledstationid)
"acmecdr_20130811_callingstationid_idx" btree (callingstationid)
"acmecdr_20130811_h323setuptime_idx" btree (h323setuptime)
Check constraints:
"acmecdr_20130811_h323setuptime_check" CHECK (h323setuptime >= 1376179200 AND h323setuptime < 1376265600)
Inherits: acmecdr
予想どおりSET constraint_exclusion = on
、正しいパーティションが自動的に優先され、そこにインデックスがあるため、インデックス スキャンは 1 回だけになります。
でも:
cdrs=> explain analyze select * from acmecdr where h323setuptime > 1376179210 and h323setuptime < 1376179400;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Result (cost=0.00..1435884.93 rows=94 width=1130) (actual time=138857.660..138858.778 rows=112 loops=1)
-> Append (cost=0.00..1435884.93 rows=94 width=1130) (actual time=138857.628..138858.189 rows=112 loops=1)
-> Seq Scan on acmecdr (cost=0.00..1435863.60 rows=1 width=1137) (actual time=138857.584..138857.584 rows=0 loops=1)
Filter: ((h323setuptime > 1376179210) AND (h323setuptime < 1376179400))
-> Index Scan using acmecdr_20130811_h323setuptime_idx on acmecdr_20130811 acmecdr (cost=0.00..21.33 rows=93 width=1130) (actual time=0.037..0.283 rows=112 loops=1)
Index Cond: ((h323setuptime > 1376179210) AND (h323setuptime < 1376179400))
Total runtime: 138859.240 ms
(7 rows)
したがって、すべてのパーティションをスキャンしているわけではなく、関連するパーティション (インデックス スキャンで非常に高速) とマスター テーブル (私が見た例では正常なようです) のみをスキャンしていることがわかります。しかしマスターテーブルのseqスキャンの高コストは異常なようです。特にマスターテーブルにはレコードが含まれていないため、その理由はわかりません。
cdrs=> select count(*) from only acmecdr;
count
-------
0
(1 row)
明らかな何かが欠けていない限り、このクエリは迅速なはずです。しかし、そうではありません-約2分かかりますか?これはまったく正常ではないようです (サーバーが遅い場合でも)。
私は次に何を試すべきかについてのアイデアがありませんので、誰かが正しい方向への提案や指針を持っていれば、それは非常に高く評価されます.