MySQL在有限的查询中左键连接

MySQL在有限的查询中左键连接,mysql,join,Mysql,Join,我注意到我在一个相当大的表上执行的某个查询在服务器处于高负载时变得非常慢: SELECT large.*, users.username FROM large LEFT JOIN users ON large.user_id = users.id ORDER BY large.abc LIMIT 30 (对large.user\u id和users.id都进行了索引。) 因此,在进一步检查后,我意识到这是由于连接查询造成的,因为删除连接查询使其变得即时。同样,重写查询的速度也一样快 SEL

我注意到我在一个相当大的表上执行的某个查询在服务器处于高负载时变得非常慢:

SELECT large.*, users.username 
FROM large
LEFT JOIN users ON large.user_id = users.id
ORDER BY large.abc 
LIMIT 30
(对
large.user\u id
users.id
都进行了索引。)

因此,在进一步检查后,我意识到这是由于连接查询造成的,因为删除连接查询使其变得即时。同样,重写查询的速度也一样快

SELECT t.*, users.username 
FROM (
  SELECT * FROM large ORDER BY large.abc LIMIT 30
) as t 
LEFT JOIN users ON t.user_id = users.id

这是什么原因?第一个查询是否在排序和限制之前连接所有行,并且使用第二个查询是解决此问题的最佳/唯一方法?

尝试根据此语法重新排序查询

订购前应进行连接

   SELECT large.*, users.username FROM large LEFT JOIN users ON large.user_id = users.id ORDER BY large.abc LIMIT 30

请尝试根据此语法对查询重新排序

订购前应进行连接

   SELECT large.*, users.username FROM large LEFT JOIN users ON large.user_id = users.id ORDER BY large.abc LIMIT 30

我可以提出一些建议并尝试一下,然后根据我的SQL FIDLE I让我知道吗

CREATE INDEX large_abc_index ON large(abc);
第一个查询似乎更简单,并且使用了正确的键。 我使用explain命令来解释这里的查询。

我可以提出一些建议并尝试一下,然后根据我的SQL FIDLE I让我知道吗

CREATE INDEX large_abc_index ON large(abc);
第一个查询似乎更简单,并且使用了正确的键。 我使用explain命令来解释这里的查询。

在第一次查询中,您将把
large
中的每一行加入到它对应的用户中,对
large
中现在加入的所有行进行排序,然后丢弃除30行以外的所有行。在第二个查询中,您对
large
进行排序,丢弃除30个之外的所有数据,然后将
large
子集加入到
用户中。因此,关键的区别在于连接了多少行

我希望看到这些查询的查询计划,但我怀疑第二个查询速度更快,因为临时表的可读性大大低于第一个查询(它有“大量”行),而磁盘分页操作(它只有30行)

通常,子选择比较慢,因为它们绕过了优化器的连接算法选择,并且必须完全依赖于解析查询,但在这种情况下,因为我们知道子选择只有30行,所以它似乎比内置的连接优化器更好


我怀疑如果您从子选择中删除
限制30
,并将其放在外部查询中,您将看到比第一个查询更差的性能。但是,同样地,
EXPLAIN
的输出将大大有助于解开这个谜团。

在您的第一个查询中,您将
large
中的每一行都连接到相应的用户,对
large
中现在连接的所有行进行排序,然后丢弃除30行以外的所有行。在第二个查询中,您对
large
进行排序,丢弃除30个之外的所有数据,然后将
large
子集加入到
用户中。因此,关键的区别在于连接了多少行

我希望看到这些查询的查询计划,但我怀疑第二个查询速度更快,因为临时表的可读性大大低于第一个查询(它有“大量”行),而磁盘分页操作(它只有30行)

通常,子选择比较慢,因为它们绕过了优化器的连接算法选择,并且必须完全依赖于解析查询,但在这种情况下,因为我们知道子选择只有30行,所以它似乎比内置的连接优化器更好


我怀疑如果您从子选择中删除
限制30
,并将其放在外部查询中,您将看到比第一个查询更差的性能。但是,同样地,
EXPLAIN
的输出将大大有助于解开这个谜团。

您的第一个查询甚至不应该运行,因为它是错误的syntax,正如@TinTran所说,语法是错误的。您是在加入之前订购的。@TinTran我的错误,修复了
large
用户之间的关系?多对多或1对多或多对1或1对1?我这样问是因为我猜如果order by有更多的行要处理,它会更慢。第二个查询在加入前限制为仅30行。第一个查询甚至不应该运行,因为它是错误的语法,如@TinTran所说,语法是错误的。您是在加入之前订购的。@TinTran我的错误,修复了
large
用户之间的关系?多对多或1对多或多对1或1对1?我这样问是因为我猜如果order by有更多行要处理,它会更慢..第二个查询在加入前限制为仅30行。你在问题中没有提到这一点。也许可以尝试在您的环境中使用explain命令来查看它在做什么。我唯一能想到的另一个方法是,将大型表索引为两列索引,如abc和userid一起索引。这将使第一个查询变慢。至少这是sqlfiddle.com上解释的。你在问题中没有提到这一点。也许可以尝试在您的环境中使用explain命令来查看它在做什么。我唯一能想到的另一个方法是,将大型表索引为两列索引,如abc和userid一起索引。这将使第一个查询变慢。至少这是sqlfiddle.com中解释的。