Я використовую постгреси 9.4.
Схема messages
має таку схему: повідомлення належать до feed_id, а також розмістив post_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 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? Будь ласка, відремонтуйте своє запитання, щоб воно було послідовним. Ви вибираєте> 500k рядків у CTE ... Скільки рядків у таблиці? Який відсоток рядків ви обираєте зазвичай в CTE? Який відсоток рядків має parent_id IS NULL
? Розгляньте інформацію у тезі [postgresql-performance] для питань щодо ефективності.
parent_id
? (хв. / сер / макс.)
metadata
. В даний час таблиця повідомлень містить 10 мільйонів даних, але швидко збільшується. Я думаю, щоб розділити таблиці розділів для кожного feed_id. Оскільки я отримую лише один ідентифікатор каналу. відсоток parent_id null vs null становить близько 60% / 40%. типовий збір становить близько 1-2% таблиці. (близько 100K повідомлень) Продуктивність для 100K становить близько 1 с, але колись вона доходить до 500K +, вона використовує растровий індекс і зазвичай займає 10 секунд.
ORDER BY
в підзапиті абсолютно марно. Крім того, пов'язаний план не може бути результатом розміщеного запиту - наприклад, немає жодної згадкиmetadata
.