这是我的表架构
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
Run Code Online (Sandbox Code Playgroud)
这是查询
SELECT *
FROM message
WHERE chatbox_id=$1
ORDER BY date_created
OFFSET 0
LIMIT 20;
Run Code Online (Sandbox Code Playgroud)
($ 1将被实际ID替换)
它运行得很好,但当它达到370万条记录时,所有SELECT查询开始消耗大量CPU和RAM,然后整个系统停机.我必须暂时备份所有当前消息并截断该表.我不知道发生了什么,因为当我有大约2百万条记录时一切正常
我使用Postresql Server 9.1.5默认选项.
更新EXPLAIN ANALYZE的输出
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)
Run Code Online (Sandbox Code Playgroud)
更新服务器规范
Intel Xeon 5620 8x2.40GHz+HT
12GB DDR3 1333 ECC
SSD Intel X25-E Extreme 64GB
Run Code Online (Sandbox Code Playgroud)
最终解决方案
最后我可以超过300万条消息,我必须像wildplasser建议的那样优化postgresql配置,并根据AH建议创建一个新索引
您可以尝试为PostgreSQL提供更好的查询索引.我建议这样的事情:
create index invent_suitable_name on message(chatbox_id, date_created);
Run Code Online (Sandbox Code Playgroud)
要么
create index invent_suitable_name on message(chatbox_id, date_created desc);
Run Code Online (Sandbox Code Playgroud)