【发布时间】:2010-10-11 23:24:56
【问题描述】:
这篇文章需要花费大量时间来输入,因为我试图尽可能清楚,所以如果仍然不清楚,请多多包涵。
基本上,我拥有的是数据库中的一个帖子表,用户可以在其中添加隐私设置。
ID | owner_id | post | other_info | privacy_level (int value)
从那里,用户可以添加他们的隐私详细信息,允许所有 [privacy_level = 0)、朋友 (privacy_level = 1)、没有人 (privacy_level = 3) 或特定的人或过滤器 (privacy_level = 4) 查看)。对于指定特定人员的隐私级别 (4),查询将在子查询中引用表“post_privacy_includes_for”,以查看用户(或用户所属的过滤器)是否存在于表中的一行中。
ID | post_id | user_id | list_id
此外,用户可以通过排除某些人来阻止他们在更大的组中查看他们的帖子(例如,将其设置为所有人都可以查看,但对跟踪用户隐藏)。为此,添加了另一个参考表“post_privacy_exclude_from” - 它看起来与“post_privacy_includes_for”的设置相同。
我的问题是这无法扩展。完全没有。目前,大约有 1-2 百万个帖子,其中大部分设置为所有人都可以查看。对于页面上的每个帖子,它必须检查是否有一行将帖子排除在显示给用户之外 - 这在可以填充 100-200 个帖子的页面上移动非常慢。最多可能需要 2-4 秒,尤其是在向查询中添加了其他约束时。
这也创建了非常庞大和复杂的查询,只是......尴尬。
SELECT t.*
FROM posts t
WHERE ( (t.privacy_level = 3
AND t.owner_id = ?)
OR (t.privacy_level = 4
AND EXISTS
( SELECT i.id
FROM PostPrivacyIncludeFor i
WHERE i.user_id = ?
AND i.thought_id = t.id)
OR t.privacy_level = 4
AND t.owner_id = ?)
OR (t.privacy_level = 4
AND EXISTS
(SELECT i2.id
FROM PostPrivacyIncludeFor i2
WHERE i2.thought_id = t.id
AND EXISTS
(SELECT r.id
FROM FriendFilterIds r
WHERE r.list_id = i2.list_id
AND r.friend_id = ?))
OR t.privacy_level = 4
AND t.owner_id = ?)
OR (t.privacy_level = 1
AND EXISTS
(SELECT G.id
FROM Following G
WHERE follower_id = t.owner_id
AND following_id = ?
AND friend = 1)
OR t.privacy_level = 1
AND t.owner_id = ?)
OR (NOT EXISTS
(SELECT e.id
FROM PostPrivacyExcludeFrom e
WHERE e.thought_id = t.id
AND e.user_id = ?
AND NOT EXISTS
(SELECT e2.id
FROM PostPrivacyExcludeFrom e2
WHERE e2.thought_id = t.id
AND EXISTS
(SELECT l.id
FROM FriendFilterIds l
WHERE l.list_id = e2.list_id
AND l.friend_id = ?)))
AND t.privacy_level IN (0, 1, 4))
AND t.owner_id = ?
ORDER BY t.created_at LIMIT 100
(模拟查询,类似于我现在在 Doctrine ORM 中使用的查询。这是一团糟,但你明白我在说什么。)
我想我的问题是,您将如何处理这种情况来优化它?有没有更好的方法来设置我的数据库?我愿意完全放弃我目前建立的方法,但我不知道该怎么做。
谢谢大家。
更新:修复查询以反映我为上述隐私级别定义的值(我忘记更新它,因为我简化了值)
【问题讨论】:
-
您可能应该在查询中添加一些换行符和缩进,因为它是非常难以阅读的。
-
privacy_level = 7 是什么意思?
-
对不起,我更新了查询以反映示例中的值(在实际应用中,隐私值不同)
标签: php mysql optimization doctrine