mysql查询有问题

时间:2010-02-15 13:27:14

标签: php mysql

如何优化此mysql查询:

SELECT * 
FROM messages 
WHERE toid='".$mid."' 
  AND fromid='".$fid."' 
  OR (toid='".$fid."' AND fromid='".$mid."')  
  AND subject != 'something' 
order by id ASC LIMIT 0,5

我需要在一个页面中的用户之间获取消息。此查询ID占用了大量时间和服务器资源。可以用其他方式完成吗?

感谢。

4 个答案:

答案 0 :(得分:2)

如上所述,查询可能背叛了实际意图。似乎所需的条件是

WHERE ( ( toid='".$mid."' AND fromid='".$fid."' )
   OR   (toid='".$fid."'  AND fromid='".$mid."') 
      )
  AND subject != 'something' 

但是,如上所述,查询将仅使用第二个(toid和fromid)子句应用主题条件 注意,在上面,内括号是无关的;从来没有那么通常是一个好主意,包括它们以更明确地显示预期的表达。

在任何一种情况下,由于OR子句和NOT EQUAL谓词,此查询是一个“硬[er]”查询解析。 OR子句通常使服务器合并来自两个子查询的结果(尽管其他策略是可能的)。 NOT EQUAL谓词不能通过索引查找来解析(但是覆盖索引在某些情况下确实有帮助),因为它将行程保存到主表/其他索引以评估手头的行是否满足谓词)

独立于这个可能的逻辑问题,添加索引将有多个键可以帮助解决这个问题。我想建议如下:

  • toid,fromId,subject
  • toid,fromid

还包括主题的索引的兴趣是允许通过部分扫描索引来解析查询,而不是必须查找主题。此索引将用作此查询的覆盖索引。

请注意,添加索引会降低INSERT,UPDATE和DELETE操作的性能。

编辑关于(toid,fromid,subject)索引的可用性
首先,我们承认我们只需要一个建议的索引,即如果我们有(toid,fromid,subject)索引,那么(toid,fromid)将是多余的(尽管如果主题是相对的,可能更有效率)长栏) 这就是说,查询在主题上使用NOT EQUAL谓词的事实不必排除在(toid,fromid,subject)索引中使用主题数据。原因是主题上的[不等于]条件可以在索引中解析(不需要匹配/合并或查找,即类似于某些“覆盖”逻辑)

答案 1 :(得分:1)

正如zerkms指出的那样,在这种情况下你不能为主题做索引。在评论中查看他的建议。

为两个ID添加一个索引:

CREATE INDEX ids_index ON messages (fromid, toid);

并将查询拆分为两个。

答案 2 :(得分:1)

在货币对上添加一个索引(toidfromid)。这将允许它使用索引来查找相关消息并加快查询速度。注意,各列上的索引可能仍然会留下许多要扫描的消息,即那些消息往/来自其中一个人到另一个人。使用该对将索引扫描找到的消息限制为两个人之间的消息。

答案 3 :(得分:1)

鉴于您希望有一些逻辑来阻止用户向自己发送消息,或许这样:

WHERE toid IN ($mid, $fid) AND fromid IN ($mid, $fid) AND subject <> 'something'

(toid, fromid)上放一个索引,我觉得这应该很好。