Tôi đang sử dụng postgres 9.4.
Có messages
lược đồ sau: tin nhắn thuộc về feed_id và đã đăng_at, cũng có thể có tin nhắn gốc (trong trường hợp trả lời).
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)
Tôi muốn trả về tất cả các tin nhắn theo thứ tự share_count
, nhưng với mỗi parent_id
tin nhắn, tôi chỉ muốn trả lại một tin nhắn. tức là, nếu nhiều tin nhắn có cùng parent_id
, thì chỉ có tin nhắn mới nhất ( posted_at
) được trả về. Có parent_id
thể là null, tin nhắn có null parent_id
nên trả về tất cả.
Truy vấn tôi đã sử dụng là:
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;
Đây là http://sqlfiddle.com/#!15/588e5/1/0 , trong SQL Fiddle, tôi đã xác định lược đồ, truy vấn chính xác và kết quả mong đợi.
Nhưng hiệu năng của truy vấn chậm khi bảng thông báo trở nên lớn. Tôi đã thử thêm nhiều chỉ mục sắp xếp, nhưng dường như không sử dụng chỉ mục. Đây là lời giải thích: http://explain.depesz.com/s/Sv2
Làm thế nào tôi có thể tạo một chỉ mục chính xác?
feed_id
và posted_at
và bạn hoàn toàn không đề cập đến metadata
, đây có vẻ là một loại JSON? Vui lòng sửa chữa câu hỏi của bạn để làm cho nó phù hợp. Bạn chọn> 500k hàng trong CTE ... Có bao nhiêu hàng trong bảng? Bao nhiêu phần trăm hàng bạn thường chọn trong CTE? Bao nhiêu phần trăm hàng có parent_id IS NULL
? Xem xét thông tin trong thẻ [postgresql-Performance] cho các câu hỏi về hiệu suất.
parent_id
? (tối thiểu / avg / max)
metadata
. Hiện tại bảng tin nhắn có 10 triệu dữ liệu, nhưng tăng nhanh. Tôi nghĩ sẽ tách thành các bảng phân vùng cho mỗi feed_id. Vì tôi chỉ tìm nạp trên mỗi id nguồn cấp dữ liệu. tỷ lệ phần trăm của cha_id null so với không null là khoảng 60% / 40%. một lần tìm nạp thông thường là khoảng 1-2% của bảng. (khoảng 100 nghìn tin nhắn) Hiệu suất cho 100K là khoảng 1 giây, nhưng một khi đạt tới 500K +, nó sử dụng chỉ số bitmap và thường mất 10 giây.
ORDER BY
trong truy vấn con là hoàn toàn vô dụng. Hơn nữa, kế hoạch được liên kết không thể là kết quả của truy vấn được đăng - chẳng hạn, không có đề cập đếnmetadata
.