我正在使用postgres 9.4。
的messages
具有以下模式:消息属于FEED_ID,并且具有posted_at,还消息可以具有(在答复的情况)的父消息。
Table "public.messages"
Column | Type | Modifiers
------------------------------+-----------------------------+-----------
message_id | character varying(255) | not null
feed_id | integer |
parent_id | character varying(255) |
posted_at | timestamp without time zone |
share_count | integer |
Indexes:
"messages_pkey" PRIMARY KEY, btree (message_id)
"index_messages_on_feed_id_posted_at" btree (feed_id, posted_at DESC NULLS LAST)
我想返回按排序的所有消息share_count
,但对于每个parent_id
,我只想返回一条消息。即,如果多个消息具有相同的parent_id
,则仅posted_at
返回最新的消息()。在parent_id
可以为空,以空消息parent_id
都应该回报。
我使用的查询是:
WITH filtered_messages AS (SELECT *
FROM messages
WHERE feed_id IN (7)
AND (posted_at >= '2015-01-01 04:00:00.000000')
AND (posted_at < '2015-04-28 04:00:00.000000'))
SELECT *
FROM (SELECT DISTINCT ON(COALESCE(parent_id, message_id)) parent_id,
message_id,
posted_at,
share_count
FROM filtered_messages
ORDER BY COALESCE(parent_id, message_id), posted_at DESC NULLS LAST
) messages
ORDER BY share_count DESC NULLS LAST, posted_at DESC NULLS LAST;
这是http://sqlfiddle.com/#!15/588e5/1/0,在SQL Fiddle中,我已经定义了架构,确切的查询和预期的结果。
但是,一旦message表变大,查询的性能就会变慢。我尝试添加多个排序索引,但似乎没有使用该索引。这是解释:http : //explain.depesz.com/s/Sv2
如何创建正确的索引?
feed_id
并且posted_at
您根本没有提及metadata
,这似乎是JSON类型?请修复您的问题以使其一致。您选择CTE中的> 500k行...表中有多少行?您通常在CTE中选择百分之几的行?行的百分比是parent_id IS NULL
多少?考虑[postgresql-performance]标记中的信息以获取有关性能的问题。
parent_id
?(最低/平均/最高)
metadata
。目前,消息表中的数据为1000万,但增长很快。我认为要为每个feed_id分成分区表。由于我只提取每个Feed ID。parent_id null与not null的百分比约为60%/ 40%。典型的提取量约为表格的1-2%。(大约10万条消息)100K的性能大约为1s,但是一旦达到500K +,它将使用位图索引,通常需要10s。
ORDER BY
子查询中的完全没用。此外,链接的计划不能是已发布查询的结果-metadata
例如,没有提及。