在我的应用程序中,我有一个应用程序事件表,用于生成应用程序事件的用户特定提要。因为它是使用OR查询生成的,所以我担心这个使用频繁的查询的性能,我想知道我是否接近这个错误。
在应用程序中,用户可以关注其他用户和组。执行操作时(例如,创建新帖子),将创建feed_item
记录,其中actor_id
设置为用户的ID,subject_id
设置为组ID,其中操作已执行,actor_type
和subject_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 :(得分:1)
你所拥有的是一个叫做独家弧的东西,你就会明白为什么这是一个坏主意。解决此类问题的最佳方法是使Feed项类型动态化:
然后您的查询变为
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条件的原因,从而使自己能够针对性能查询进行编写它
答案 1 :(得分: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
但再次解释分析和基准。
答案 2 :(得分:0)
要确定是否存在性能问题。 PostgreSQL可以为你explain。
我不认为查询需要简化,如果您发现性能问题,那么您可能需要修改索引。