3

これは私のテーブルスキーマです

Column       |          Type          |                      Modifiers                      
-------------+------------------------+------------------------------------------------------
id           | integer                | not null default nextval('message_id_seq'::regclass)
date_created | bigint                 |
content      | text                   |
user_name    | character varying(128) |
user_id      | character varying(128) |
user_type    | character varying(8)   |
user_ip      | character varying(128) |
user_avatar  | character varying(128) |
chatbox_id   | integer                | not null
Indexes:
    "message_pkey" PRIMARY KEY, btree (id)
    "idx_message_chatbox_id" btree (chatbox_id)
    "indx_date_created" btree (date_created)
Foreign-key constraints:
    "message_chatbox_id_fkey" FOREIGN KEY (chatbox_id) REFERENCES chatboxes(id) ON UPDATE CASCADE ON DELETE CASCADE

これはクエリです

SELECT * 
FROM message 
WHERE chatbox_id=$1 
ORDER BY date_created 
OFFSET 0 
LIMIT 20;

($ 1は実際のIDに置き換えられます)

かなりうまく動作しますが、370万レコードに達すると、すべてのSELECTクエリが大量のCPUとRAMを消費し始め、システム全体がダウンします。現在のすべてのメッセージを一時的にバックアップし、そのテーブルを切り捨てる必要があります。約200万件のレコードがあれば、すべて問題ないので、何が起こっているのかわかりません。

デフォルトのオプションでPostresqlServer9.1.5を使用しています。


EXPLAINANALYZEの出力を更新します

Limit  (cost=0.00..6.50 rows=20 width=99) (actual time=0.107..0.295 rows=20 loops=1)
->  Index Scan Backward using indx_date_created on message  (cost=0.00..3458.77 rows=10646 width=99) (actual time=0.105..0.287 rows=20 loops=1)
Filter: (chatbox_id = 25065)
Total runtime: 0.376 ms
(4 rows)

サーバー仕様を更新する

Intel Xeon 5620 8x2.40GHz+HT
12GB DDR3 1333 ECC
SSD Intel X25-E Extreme 64GB

最終的解決

最後に、300万を超えるメッセージを送信できます。wildplasserが提案したようにpostgresql構成を最適化し、AHが提案したように新しいインデックスを作成する必要があります。

4

2 に答える 2

8

PostgreSQLにそのクエリのより良いインデックスを与えることを試みることができます。私はこのようなものを提案します:

create index invent_suitable_name on message(chatbox_id, date_created);

また

 create index invent_suitable_name on message(chatbox_id, date_created desc);
于 2012-11-24T18:40:56.477 に答える
3

のインデックスを追加してみてくださいchatbox_id, date_created。この特定のクエリでは、最大のパフォーマンスが得られます。

この場合、postgresが「大量のCPUとRAMを消費し始める」ときは、詳細を取得してみてください。これはバグである可能性があります(デフォルトの構成では、postgresは通常多くのRAMを消費しません)。

UPDパフォーマンスが悪いという理由で私の推測:

ある時点で、正確な統計を収集するためのフルスキャンのためにテーブルが大きくなります。別のANALYZEPostgresqlがテーブルの悪い統計を取得した後。その結果、次のような悪い計画が立てられました。

  1. のインデックススキャンchatbox_id;
  2. トップ20を取得するために返されたレコードの順序。

ステップ1で返されたデフォルトの構成と大量のレコードのため、postgresはディスク上のファイルの並べ替えを強制されました。その結果、パフォーマンスが低下します。

UPD2EXPALIN ANALYZE0.376 ms時間と良い計画を示しています。パフォーマンスの悪いケースについて詳しく教えてください。

于 2012-11-24T21:47:53.480 に答える