Postgres 9.4 kullanıyorum.
messagesAşağıdaki şema vardır: mesajlar FEED_ID aittir ve posted_at vardır, ayrıca mesajlar (cevapların durumunda) bir üst mesajı olabilir.
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)
Tarafından sipariş edilen tüm mesajları iade etmek istiyorum share_count, ancak her biri için parent_idsadece bir mesaj geri dönmek istiyorum. örneğin, birden fazla ileti aynı ise parent_id, yalnızca en son gelen ileti ( posted_at) döndürülür. parent_idOlabilir null, null mesajlar parent_idtüm iade gerektiği.
Kullandığım sorgu:
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;
İşte http://sqlfiddle.com/#!15/588e5/1/0 , SQL Fiddle'da şemayı, tam sorguyu ve beklenen sonucu tanımladım.
Ancak iletiler tablosu büyüdükçe sorgunun performansı yavaşlar. Birden çok sıralama dizini eklemeyi denedim, ancak dizini kullanmak gibi görünmüyor. İşte açıklama: http://explain.depesz.com/s/Sv2
Nasıl doğru dizin oluşturabilirim?
feed_idve posted_atve söz etmedi metadataJSON türü gibi görünüyor, hangi hiç? Tutarlı hale getirmek için lütfen sorunuzu onarın. CTE'de> 500 bin satır seçin ... Tabloda kaç satır var? CTE'de tipik olarak yüzde kaç satır seçersiniz? Satırların yüzde kaçı var parent_id IS NULL? Performans soruları için [postgresql-performance] etiketindeki bilgileri göz önünde bulundurun .
parent_id? (min / ort / maks)
metadata. Şu anda mesajlar tablosunda 10 mil veri var, ancak hızla artıyor. Her feed_id için bölüm tabloları ayırmak düşünüyorum. Yalnızca feed kimliği başına getirildiğimden. parent_id null yerine null değil yüzdesi yaklaşık% 60 /% 40'tır. tipik bir getirme tablonun yaklaşık% 1-2'sidir. (100K civarında mesajlar) 100K performansı 1s civarındadır, ancak bir kez 500K + 'ya ulaşır, bitmap dizini kullanır ve normalde 10s alır.
ORDER BYalt sorgudaki tamamen işe yaramaz. Ayrıca, bağlantılı plan gönderilen sorgunun bir sonucu olamaz -metadataörneğin , bundan bahsedilmez .