Postgres 9.4 kullanıyorum.
messages
Aş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_id
sadece 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_id
Olabilir null, null mesajlar parent_id
tü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_id
ve posted_at
ve söz etmedi metadata
JSON 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 BY
alt sorgudaki tamamen işe yaramaz. Ayrıca, bağlantılı plan gönderilen sorgunun bir sonucu olamaz -metadata
örneğin , bundan bahsedilmez .