2

在我的一个 PHP/MySQL 站点上,每个用户都可以阻止站点上的所有其他用户。这些块存储在一个Blocked表中,每一行代表谁进行了阻塞以及谁是块的目标。这些列被索引以便更快地检索用户的整个“阻止列表”。

对于每个用户,我们必须从任何搜索结果中排除出现在其阻止列表中的任何用户。

为了做到这一点,最好是:

1)在用户登录时生成“阻止列表”,方法是在登录时查询Blocked一次并将其保存到$_SESSION(并在他们更改“阻止列表”并将其重新保存到时重新查询$_SESSION) ,然后这样查询:

NOT IN ($commaSeparatedListFromSession)

或者

2)通过对每个用户的搜索查询使用子查询,直接在查询中“实时”排除被阻止的用户:

NOT IN (SELECT userid FROM Blocked WHERE Blocked.from = $currentUserID)?

4

3 回答 3

2

如果网站是 PHP 并且每个用户的阻止列表少于 100 个,我会将其存储在一个表中,在更改/登录时将其加载到 $_SESSION。您可以在每个页面加载时轻松地将其从 SQL 加载到然而,局部变量。

我将存储在 $_SESSION 中的是一个标志“has_blocklist_contents”,它将决定您是否应该在页面加载时加载或检查阻止列表。

我认为使用 PHP 过滤掉它们可能更聪明,而不是在所有查询中使用 NOT IN。

我想以这种方式实现有两个原因:

  1. 您的数据库可以为系统上的所有用户重复使用 SQL,从而提高检索评论等的性能。
  2. 您的阻止列表大部分时间都是空的,因此您不会为大多数用户增加任何处理时间。
于 2013-04-25T16:48:36.980 回答
1

我认为有第三种解决方案。在我看来,这将是更好的方法。

如果你能写这个

NOT IN (SELECT userid FROM Blocked WHERE Blocked.from = $currentUserID)

那么你肯定可以写这个。

....
SomeTable st
LEFT JOIN
Blocked b
ON( st.userid = b.userid AND Blocked.from = $currentUserID)
WHERE b.primaryKey IS NULL;

我希望你明白我上面的查询的意思。这样您就可以两全其美,即您不必运行 2 个查询,也不必将数据保存在$_SESSION

于 2013-04-25T17:40:17.633 回答
0

不要将$_SESSION用作适当的缓存系统的替代品。您堆积的垃圾$_SESSION越多,您必须为每个请求加载的越多。

如果您不小心调整数据库,则使用子选择排除可能会非常缓慢。确保您的索引涵盖所有WHERE条件。

于 2013-04-25T16:47:37.220 回答