避免 MySQL“使用临时”在某些情况下

发布于 2024-12-25 04:51:42 字数 1434 浏览 5 评论 0原文

我有两个表,usersfollowers

users

id          INT, PRIMARY_KEY
name        VARCHAR
joined      INT

该表在 id上建立索引加入

表“followers”:

user        INT
follows     INT 

此表根据 usersfollows 建立索引。

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

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 the
followers 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

み青杉依旧 2025-01-01 04:51:42

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

这应该强制从“关注者”表开始,特定于用户 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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文