2013-04-25 63 views
0

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

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

为了做到这一点,是它更好地:

1)生成了“阻止列表”,每当用户通过登录查询Blocked一次,并把它保存在$_SESSION登录(和它重新查询他们做出改变他们的“阻止列表”和任何时间重新保存至$_SESSION),然后查询这样:

NOT IN ($commaSeparatedListFromSession)

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

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

+0

继续子选择。让数据库做好自己擅长的事情:即尽早过滤。另外,一个好的数据库不会因为你将它重新构建为JOIN而变得更慢。因此,除非您发现数据库无法以更直观的形式处理查询,否则请勿这样做。 – 2013-04-26 15:14:21

回答

0

请勿使用$_SESSION作为proper caching system的替代品。您投入$_SESSION的垃圾越多,您就越需要为每个请求加载更多垃圾。

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

0

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

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

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

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

  1. 您的数据库可以重新使用SQL对所有用户造成了性能提升检索意见和这样的系统。
  2. 您的阻止列表大部分时间都是空的,因此您不会为大多数用户添加任何处理时间。
0

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

如果你能写这个

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

+0

有趣的解决方案!这实际上比用**覆盖的**索引进行子查询要快吗? – ProgrammerGirl 2013-04-25 17:56:15

+0

是的,这比做子查询要快。 – Manu 2013-04-25 18:01:18

+0

它如何比做子查询更快?此外,不应该是'IS NULL;'在最后而不是'IS NOT NULL';如果你想显示除被阻止的用户以外的每个人? – ProgrammerGirl 2013-04-25 19:11:32