Estou usando o postgres 9.4.
O messages
esquema tem o seguinte: messages pertence a feed_id e postou_at, também as mensagens podem ter uma mensagem pai (no caso de respostas).
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)
Quero retornar todas as mensagens ordenadas por share_count
, mas para cada uma parent_id
, quero retornar apenas uma mensagem. ou seja, se várias mensagens tiverem o mesmo parent_id
, somente a última ( posted_at
) será retornada. O parent_id
pode ser nulo, todas as mensagens com nulo parent_id
devem retornar.
A consulta que usei é:
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;
Aqui está o http://sqlfiddle.com/#!15/588e5/1/0 , no SQL Fiddle, eu defini o esquema, a consulta exata e o resultado esperado.
Mas o desempenho da consulta é lento quando a tabela de mensagens aumenta. Tentei adicionar vários índices de classificação, mas ele não parece usar o índice. Aqui está a explicação: http://explain.depesz.com/s/Sv2
Como posso criar um índice correto?
feed_id
e posted_at
você não mencionou metadata
nada, o que parece ser do tipo JSON? Repare sua pergunta para torná-la consistente. Você seleciona> 500k linhas na CTE ... Quantas linhas estão na tabela? Qual porcentagem de linhas você normalmente seleciona na CTE? Qual a porcentagem de linhas parent_id IS NULL
? Considere as informações na tag [postgresql-performance] para perguntas sobre desempenho.
parent_id
? (min / avg / max)
metadata
. Atualmente, a tabela de mensagens possui 10 mil dados, mas aumenta rapidamente. Eu acho que para separar em tabelas de partição para cada feed_id. Como estou buscando apenas por ID do feed. a porcentagem de parent_id null vs not null é de cerca de 60% / 40%. uma busca típica é de cerca de 1-2% da tabela. (em torno de 100 mil mensagens) O desempenho para 100 mil é de cerca de 1s, mas quando chega a 500 mil +, ele usa o índice de bitmap e normalmente leva 10 segundos.
ORDER BY
a subconsulta é totalmente inútil. Além disso, o plano vinculado não pode ser resultado da consulta lançada - não há mençãometadata
, por exemplo.