J'utilise postgres 9.4.
Le messages
a le schéma suivant: les messages appartiennent à feed_id, et a posted_at, les messages peuvent également avoir un message parent (en cas de réponses).
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)
Je souhaite renvoyer tous les messages commandés par share_count
, mais pour chacun parent_id
, je souhaite renvoyer un seul message. c'est-à-dire, si plusieurs messages ont le même parent_id
, alors seul le dernier ( posted_at
) est retourné. Le parent_id
peut être nul, les messages avec null parent_id
doivent tous retourner.
La requête que j'ai utilisée est:
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;
Voici le http://sqlfiddle.com/#!15/588e5/1/0 , dans le SQL Fiddle, j'ai défini le schéma, la requête exacte et le résultat attendu.
Mais les performances de la requête sont lentes une fois que la table des messages devient volumineuse. J'ai essayé d'ajouter plusieurs index de tri, mais il ne semble pas utiliser l'index. Voici l'explication: http://explain.depesz.com/s/Sv2
Comment puis-je créer un index correct?
feed_id
et posted_at
et vous ne l'avez pas mentionné metadata
du tout, qui semble être un type JSON? Veuillez réparer votre question pour la rendre cohérente. Vous sélectionnez> 500k lignes dans le CTE ... Combien de lignes sont dans le tableau? Quel pourcentage de lignes sélectionnez-vous généralement dans le CTE? Quel est le pourcentage de lignes parent_id IS NULL
? Considérez les informations dans la balise [postgresql-performance] pour les questions de performances.
parent_id
? (min / moy / max)
metadata
. Actuellement, le tableau des messages contient des données de 10 mil, mais augmente rapidement. Je pense me séparer en tables de partition pour chaque feed_id. Étant donné que je ne récupère que par identifiant de flux. le pourcentage de parent_id nul vs non nul est d'environ 60% / 40%. une extraction typique représente environ 1 à 2% du tableau. (environ 100K messages) Les performances pour 100K sont d'environ 1s, mais une fois à 500K +, il utilise un index bitmap et prend normalement 10s.
ORDER BY
dans la sous-requête est totalement inutile. De plus, le plan lié ne peut pas être le résultat de la requête publiée - il n'est pas fait mentionmetadata
, par exemple.