避免 MySQL“使用临时”在某些情况下
我有两个表,users
和 followers
:
表 users
:
id INT, PRIMARY_KEY
name VARCHAR
joined INT
该表在 id
和 上建立索引加入
。
表“followers”:
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
到目前为止一切顺利。 (“using 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执行表搜索的顺序,并且在可能的情况下这是不可能的,是否有另一种方法来摆脱使用临时
?
I have two tables, users
and followers
:
Table users
:
id INT, PRIMARY_KEY
name VARCHAR
joined INT
This table is indexed on id
and joined
.
Table 'followers':
user INT
follows INT
This table is indexed on users
and follows
.
This query finds the names of all users followed by a particular user who joined after a particular time. The results need to be
in reverse chronological order.
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
Now, when user X has a large number of followers, EXPLAIN gives the following:
id key extra
-----------------------------------
u joined Using where
f follows Using index
So far so good. (The 'using where' is due to some other clauses I've removed for brevity).
But, when user X has a small number of followers, this happens:
id key extra
-----------------------------------
f follows Using temporary, using filesort
u joined Using where
If I omit the ORDER BY
, I get:
id key extra
-----------------------------------
f follows
u joined Using where
The MySQL optimiser seems to be inspecting the number of rows it has to deal with, and if its small, doing thefollowers
table first. It seems to ignore the ORDER BY
in its optimisation steps, resulting in a slower query due
to the temporary table.
So (finally), my question is: is it possible to force the order in which MySQL performs table searches, and in the likely event this isn't possible, is there another way to get rid of using temporary
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
MySQL确实提供了一个子句“STRAIGHT_JOIN”,它告诉它按照您提供的顺序在表之间进行连接。由于您正在寻找单个特定的“关注者用户”,请将关注者表放在前面并从中加入...尝试类似的操作
这应该强制从“关注者”表开始,特定于用户 ID = X,然后加入到根据从 f.user = X 返回的行,将 users 表设置为 SECONDARY。确保您的 Followers 表有一个索引,其中“user”位于第一个位置(如果您在两列上的索引都是 (follows, user),则它应该是(用户,如下)。您的查询的最小粒度是第一个查询的人。
MySQL DOES offer a clause "STRAIGHT_JOIN" which tells it to do the join between tables in the order you've provided. Since you are looking for a single specific "Follower User" put the follower table up front and join from that... Try something like
This should FORCE Starting with the "Followers" table, specific for user ID = X, then join out to the users table as SECONDARY based on the rows returned from f.user = X. Make sure your Followers table has an index where "user" is in the first position (in case your index on both columns was (follows, user), it SHOULD be (user, follows). The smallest granularity on your query basis is the one person inquiring about... that comes in FIRST.