2

通話の詳細レコードを格納するための数億行の小さなデータベースがあります。次のようにパーティショニングをセットアップします。

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分かかりますか?これはまったく正常ではないようです (サーバーが遅い場合でも)。

私は次に何を試すべきかについてのアイデアがありませんので、誰かが正しい方向への提案や指針を持っていれば、それは非常に高く評価されます.

4

0 に答える 0