使用postgresql的ORDER BY,OFFSET和LIMIT优化SELECT查询

Tan*_*yen 3 postgresql

这是我的表架构

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建议创建一个新索引

A.H*_*.H. 8

您可以尝试为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)

  • @laoshanlung:目前你有*两个*indizes每个*包含*one*字段.我的提议创建*one*index覆盖*两个*字段.从性能角度来看,这非常不同. (4认同)