2010-02-23 16 views
1

在我的應用程序中,我有一個應用程序事件表,用於生成應用程序事件的用戶特定提要。因爲它是使用OR查詢生成的,所以我擔心這個大量使用的查詢的性能,並且想知道我是否正在接近這個錯誤。或使用Postgresql查詢性能和策略

在應用程序中,用戶可以關注其他用戶和組。執行操作時(例如,創建新帖子),會創建一個feed_item記錄,其中actor_id設置爲用戶的ID,subject_id設置爲執行操作的組ID,actor_typesubject_type設置爲模型的類名稱。由於用戶可以同時關注組和用戶,因此我需要生成一個查詢來檢查actor_id和subject_id,並且需要選擇不同的記錄以避免重複。由於它是一個OR查詢,我不能使用正常的索引。而且由於每次執行操作時都會創建一條記錄,所以我希望這張表格能夠很快記錄很多記錄。

下面是當前查詢(在following表連接用戶feeders,又名,用戶和組)

SELECT DISTINCT feed_items.* FROM "feed_items" 
INNER JOIN "followings" 
ON (
(followings.feeder_id = feed_items.subject_id 
AND followings.feeder_type = feed_items.subject_type) 
OR 
(followings.feeder_id = feed_items.actor_id 
AND followings.feeder_type = feed_items.actor_type) 
) 
WHERE (followings.follower_id = 42) ORDER BY feed_items.created_at DESC LIMIT 30 OFFSET 0 

所以我的問題:

  • 由於這是一個頻繁使用的查詢,是這裏有性能問題?

  • 是否有任何明顯的方法來簡化或優化我錯過的?

回答

0

要了解是否存在性能問題,請對其進行測量。 PostgreSQL可以爲你提供explain

我不認爲查詢需要簡化,如果你發現性能問題,那麼你可能需要修改你的索引。

1

你有什麼被稱爲獨家弧,你正在看到爲什麼這是一個壞主意。對於這類問題,最好的方法是使飼料項目類型動態:

  • 源項目:標識,類型(A或S對演員或主題),亞型(取代actor_type和SUBJECT_TYPE)

,然後你的查詢變得

SELECT DISTINCT fi.* 
FROM feed_items fi 
JOIN followings f ON f.feeder_id = fi.id AND f.feeder_type = fi.type AND f.feeder_subtype = fi.subtype 

或相似。

這可能並不完全或完全代表您需要做的事情,但其原理是正確的:您需要通過更改數據模型來消除OR條件的原因,從而有助於使正在寫入的高性能查詢反對。

+0

這似乎是使用這種方法,我需要爲每個動作創建兩個供稿項目,每個供演員和主題使用,然後過濾掉重複項,因爲當演員和主題都被跟蹤時,會返回重複項。除非我完全脫離基礎,否則我大概需要同時擁有'action_id'並執行類似於'SELECT feed_items。* FROM feed_items WHERE feed_items.action_id IN(SELECT DISTINCT fi.action_id FROM feed_items fi JOIN關注f ON f。 feeder_id = fi.id AND f.feeder_type = fi.type AND f.feeder_subtype = fi.subtype)'是正確的嗎?它比OR更好嗎? – user279603 2010-02-23 16:43:22

1

解釋分析和時間查詢,看看是否有問題。

麻生太郎,你可以嘗試表達查詢作爲工會

SELECT x.* FROM 
(
SELECT feed_items.* FROM feed_items 
INNER JOIN followings 
ON followings.feeder_id = feed_items.subject_id 
    AND followings.feeder_type = feed_items.subject_type 
WHERE (followings.follower_id = 42) 
UNION 
SELECT feed_items.* FROM feed_items 
INNER JOIN followings 
followings.feeder_id = feed_items.actor_id 
AND followings.feeder_type = feed_items.actor_type) 
WHERE (followings.follower_id = 42) 
) AS x 
ORDER BY x.created_at DESC 
LIMIT 30 

但再解釋分析和標杆。