0

我有两张桌子,users并且followers

users

id          INT, PRIMARY_KEY
name        VARCHAR
joined      INT

该表在id和上编制索引joined

表“追随者”:

user        INT
follows     INT 

该表在users和上编制索引follows

此查询查找在特定时间后加入的特定用户后跟的所有用户的名称。结果需要按时间倒序排列。

SELECT u.name 
FROM users u, followers f
WHERE f.user = X
AND f.follows = u.id
AND u.joined > 1234
ORDER BY u.joined DESC

现在,当用户 X 有大量关注者时,EXPLAIN 给出以下内容:

id      key             extra
-----------------------------------
u       joined          Using where
f       follows         Using index

到现在为止还挺好。(“使用 where”是由于我为简洁起见删除了其他一些子句)。

但是,当用户 X 的关注者数量较少时,会发生这种情况:

id      key             extra
-----------------------------------
f       follows         Using temporary, using filesort
u       joined          Using where

如果我省略ORDER BY,我会得到:

id      key             extra
-----------------------------------
f       follows         
u       joined          Using where

MySQL 优化器似乎正在检查它必须处理的行数,如果它很小,则 followers首先执行表。它似乎ORDER BY在其优化步骤中忽略了 ,导致由于临时表而导致查询速度较慢。

所以(最后),我的问题是:是否可以强制 MySQL 执行表搜索的顺序,并且在可能的情况下这是不可能的,还有其他方法可以摆脱using temporary吗?

4

1 回答 1

2

MySQL 确实提供了一个子句“STRAIGHT_JOIN”,它告诉它按照您提供的顺序在表之间进行连接。由于您正在寻找一个特定的“关注者用户”,因此将关注者表放在前面并从中加入......尝试类似

SELECT STRAIGHT_JOIN
      u.name
  from
     followers f
        join Users u
           on f.follows = u.id
          and u.joined > 1234
  where
     f.user = X
  order by 
     u.joined DESC

这应该 FORCE 从特定于用户 ID = X 的“Followers”表开始,然后根据从 f.user = X 返回的行作为 SECONDARY 加入用户表。确保您的 Followers 表有一个索引,其中“用户" 在第一个位置(如果您在两列上的索引都是(关注,用户),它应该是(用户,关注)。基于您的查询的最小粒度是查询...的人首先出现.

于 2012-01-05T18:28:16.960 回答