postgres 9.4를 사용하고 있습니다.
의 messages
스키마는 다음과 같습니다. 메시지는 feed_id에 속하고 posts_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
null 일 수 있으며 null이있는 메시지 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에서 스키마, 정확한 쿼리 및 예상 결과를 정의했습니다.
그러나 메시지 테이블이 커지면 쿼리 성능이 느려집니다. 여러 정렬 색인을 추가하려고 시도했지만 색인을 사용하지 않는 것 같습니다. 설명은 다음과 같습니다. http://explain.depesz.com/s/Sv2
올바른 색인을 만들려면 어떻게해야합니까?
feed_id
및 posted_at
당신은 언급하지 않았다 metadata
JSON 유형을 것으로 보인다 전혀? 일관성을 유지하기 위해 질문을 복구하십시오. CTE에서> 500k 개 행을 선택합니다. 테이블에 몇 개의 행이 있습니까? CTE에서 일반적으로 몇 퍼센트의 행을 선택합니까? 행의 몇 퍼센트가 parent_id IS NULL
있습니까? 성능 문제 에 대해서는 [postgresql-performance] 태그 의 정보를 고려하십시오 .
parent_id
입니까? (최소 / 평균 / 최대)
metadata
. share_count는 실제로 hstore에있었습니다 . 현재 메시지 테이블의 데이터는 10mil이지만 빠르게 증가합니다. 각 feed_id에 대해 파티션 테이블로 분리한다고 생각합니다. 피드 ID 당만 가져 오기 때문입니다. parent_id null의 비율과 null이 아닌 비율은 약 60 % / 40 %입니다. 일반적인 페치는 테이블의 1-2 % 정도입니다. (약 100K 메시지) 100K의 성능은 약 1 초이지만 한 번 500K +에 도달하면 비트 맵 인덱스를 사용하며 보통 10 초가 걸립니다.
ORDER BY
하위 쿼리에서는 완전히 쓸모가 없습니다. 또한 연결된 계획은 게시 된 쿼리의 결과 일 수 없습니다metadata
. 예를 들어에 대한 언급은 없습니다 .