Saya menggunakan postgres 9.4.
The messages
memiliki skema berikut: pesan milik FEED_ID, dan memiliki posted_at, juga pesan dapat memiliki pesan orang tua (dalam kasus balasan).
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)
Saya ingin mengembalikan semua pesan yang dipesan share_count
, tetapi untuk masing-masing parent_id
, saya hanya ingin mengembalikan satu pesan. yaitu, jika beberapa pesan memiliki yang sama parent_id
, maka hanya yang terbaru ( posted_at
) yang dikembalikan. The parent_id
dapat null, pesan dengan nol parent_id
semua harus kembali.
Permintaan yang saya gunakan adalah:
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;
Inilah http://sqlfiddle.com/#!15/588e5/1/0 , dalam SQL Fiddle, saya telah mendefinisikan skema, kueri yang tepat, dan hasil yang diharapkan.
Tetapi kinerja permintaan lambat begitu tabel pesan menjadi besar. Saya mencoba menambahkan beberapa indeks penyortiran, tetapi sepertinya tidak menggunakan indeks. Inilah penjelasannya: http://explain.depesz.com/s/Sv2
Bagaimana saya bisa membuat indeks yang benar?
feed_id
dan posted_at
dan Anda tidak menyebutkan metadata
sama sekali, yang tampaknya merupakan tipe JSON? Harap perbaiki pertanyaan Anda agar konsisten. Anda pilih> 500k baris dalam CTE ... Berapa banyak baris dalam tabel? Berapa persentase baris yang biasanya Anda pilih dalam CTE? Berapa persentase baris yang dimiliki parent_id IS NULL
? Pertimbangkan info dalam tag [kinerja-postgresql] untuk pertanyaan kinerja.
parent_id
? (minimal / rata-rata)
metadata
. Saat ini tabel pesan memiliki 10 juta data, tetapi bertambah cepat. Saya pikir untuk memisahkan ke dalam tabel partisi untuk setiap feed_id. Karena saya hanya mengambil per id umpan. persentase parent_id null vs bukan null adalah sekitar 60% / 40%. pengambilan tipikal adalah sekitar 1-2% dari tabel. (sekitar 100K pesan) Kinerja untuk 100K adalah sekitar 1s, tetapi sekali sampai 500K + itu menggunakan indeks bitmap dan biasanya membutuhkan 10s.
ORDER BY
dalam subquery sama sekali tidak berguna. Lebih lanjut, rencana tertaut tidak dapat merupakan hasil dari permintaan yang diposting - tidak ada penyebutanmetadata
, misalnya.