【问题标题】:Will be this on condition in outer join faster than where clause?外连接中的这个条件会比 where 子句更快吗?
【发布时间】:2021-05-03 22:34:06
【问题描述】:

这是我的桌子

CREATE TABLE log_table (
  `user_id` VARCHAR(5),
  `date_time` DATETIME,
  `event_name` VARCHAR(10),
  `trivial` int
);

INSERT INTO log_table
  (`user_id`, `date_time`, `event_name`, `trivial`)
VALUES
  ('001', '2020-12-10 10:00:02', 'c', 3),
  ('001', '2020-12-10 10:00:01', 'b', 9),
  ('001', '2020-12-10 10:00:40', 'e', 2),
  ('001', '2020-12-10 10:00:20', 'd', 6),
  ('001', '2020-12-10 10:00:00', 'a', 1),
  ('002', '2020-12-09 10:00:10', 'C', 9),
  ('002', '2020-12-10 10:00:50', 'D', 0),
  ('002', '2020-12-10 10:00:02', 'A', 2),
  ('002', '2020-12-10 10:00:09', 'B', 4);

(创建于DB Fiddle

我想找到一个触发事件名称的人(任何人)并检索该用户当天的所有记录。

user_id date_time event_name trivial trivial_new
001 2020-12-10 10:00:00 a 1 13
001 2020-12-10 10:00:01 b 9 19
001 2020-12-10 10:00:02 c 3 21
001 2020-12-10 10:00:20 d 6 20
001 2020-12-10 10:00:40 e 2 11
002 2020-12-09 10:00:02 A 2 15
002 2020-12-10 10:00:09 B 4 15
002 2020-12-10 10:00:10 C 9 15
002 2020-12-10 10:00:50 D 0 13

这是我的代码:

SELECT t_left.*
FROM   log_table AS t_left
       RIGHT JOIN (SELECT user_id,
                          date_time
                   FROM   log_table
                   WHERE  BINARY event_name = 'B'
                   LIMIT  1) AS t_right
               ON t_left.user_id = t_right.user_id
                  AND Substring_index(t_left.date_time, ' ', 1) =
                      Substring_index(t_right.date_time, ' ', 1)
ORDER  BY date_time 

在右表中,只有一条记录满足event_nameB 的条件,即ID 为002 的用户。然后我将其与左表连接,条件是他们的user_ids相等,日期为2020-12-10,删除其他id不同的用户001,以及同一个人的事件发生在2020-12-10之外的记录。

一切正常。

然后我修改了我的代码以检查它是否会像我预期的那样运行(确实如此,请参阅here):

SELECT t_left.*
FROM   log_table AS t_left
       RIGHT JOIN (SELECT user_id,
                          date_time
                   FROM   log_table
                   WHERE  BINARY event_name = 'B'
                   LIMIT  1) AS t_right
               ON t_left.user_id = t_right.user_id
WHERE  Substring_index(t_left.date_time, ' ', 1) =
       Substring_index(t_right.date_time, ' ', 1)
ORDER  BY date_time 

在这种情况下,我只需按一个条件连接表并过滤该用户的日期以获得正确的记录。

我阅读了一些答案 hereherehere,其中大多数示例都以常量为条件,有些人说 join 会更快,而其他人则表示编译器将优化子句并因此提高速度会是一样的。

我想知道在我的情况下,第一个是否会更快?

有什么在线平台可以比较速度吗?

【问题讨论】:

  • 并不是说它会更快,但我更喜欢使用DATE(t_left.date_time) 而不是SUBSTRING_INDEX(t_left.date_time, ' ', 1) 来提取日期。
  • 只有当您可以使用内连接而不是右连接时,这些查询与输入的功能相同,即如果右表永远不会有不匹配的行。您的 where 仅适用于具有非空左表日期的行,因此您可以只使用内部联接。正确加入的意义何在?如果您需要右连接,则您的第二个查询是错误的——并且性能没有实际意义。 PS请:在询问和反映研究之前进行研究。在询问 SQL 性能之前,先研究它并研究询问它。 PS请把所有需要问的东西都放在你的帖子中,而不仅仅是一个小提琴。
  • @philipxy 感谢您的建议。我 8 年前学习了 SQL,并且刚刚开始使用它。其他地方的答案让我不知所措。
  • *请改写为使用LEFT JOIN而不是RIGHT JOIN。)
  • @RickJames 好的,让我看看。谢谢。

标签: mysql where-clause outer-join right-join


【解决方案1】:

ON 应该用来说明表格之间的关系。

WHERE 应该用于过滤。

对于普通的JOIN (INNER JOIN),它们的实现方式相同。

对于左/右,它们可能会产生很大的不同。

【讨论】:

    【解决方案2】:

    如果假设第二个查询是最终查询结构,则您不再需要使用 RIGHT JOIN,尤其如此,因为您匹配的是 WHERE 中的日期,而不是 ON.. 中的日期。取消右连接(或左连接)。实际上,由于您正在对仅提取右侧表的特定数据的子查询进行右连接,因此几乎没有任何理由进行右连接,如果您使用左连接代替,您会得到更多的结果差异。此外,根据我的经验,JOIN (INNER JOIN) 通常比左/右连接快得多。

    另一件事是,在性能方面,索引会产生很多差异。在您当前的示例中,没有索引,因此我建议您这样做。我从@Rick James 的page here 那里学到了很多关于索引的知识。

    这是一个基于您的示例日期的小提琴,其中包括您最初的尝试和更多:

    1. RIGHT JOIN .. ON ... AND
    2. RIGHT JOIN .. ON ... WHERE
    3. LEFT JOIN .. ON ... AND
    4. LEFT JOIN .. ON ... WHERE
    5. 添加索引
    6. EXPLAIN 前后索引。

    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=1b244deb6fad0dda0bf4aaf701e6bac2

    PS:在小提琴中,我将日期提取更改为使用DATE()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      相关资源
      最近更新 更多