【问题标题】:SQL Left Join. Taking too long.SQL 左连接。花费太长时间。
【发布时间】:2013-07-26 14:25:24
【问题描述】:

好的,这是我的表模式。
我有 2 张桌子。说表 A 和表 B。表 A 的主键是 PriKeyA bigint(50),表 B 的主键是 PriKeyB varchar(255)。 PriKeyA 和 PriKeyB 都包含相同类型的数据。
这个问题需要的表A的相关字段是Last_login_date_in_A(日期),表B是主键本身。
我需要做的是,在 A 中获取那些不在表 B 的 PriKeyB 列中的 PriKeyA,并且 Last_login_date_in_A 列应该从当前日期起超过 30 天。基本上我需要表 A 和表 B 的差异以及特定条件(即本问题中的日期)
这是我的 SQL 命令

: SELECT A.PriKeyA from A  
 LEFT JOIN B ON A.PriKeyA = B.PriKeyB   
 WHERE B.PriKeyB IS NULL and DATEDIFF(CURRENTDATE,Last_login_date_in_A)>30;

但是,当我运行这个 MySQL 命令时,它需要非常长的时间(大约 3 小时)。表 A 的大小为 2,50,000,表 B 的大小分别为 42,000 条记录。我认为由于 PriKeyA 和 PriKeyB 是不同的数据类型,可能会出现此问题。所以我也在查询中使用了CAST(PriKeyB as unsigned)。但这也没有用。性能略有改善。

可能会出现什么问题?我以前用过左连接,他们从来没有用过这么长时间。

【问题讨论】:

  • 我怀疑问题出在数据类型上,特别是在查询期间对每一行执行转换。
  • 但是类型转换不应该解决这个问题吗?
  • 您的数据库在硬件上运行。那里没有神奇的独角兽,如果你至少不使用 InnoDB 并且如果你不优化 MySQL 的设置,那么你就找错了树。此外,当您想知道为什么某件事需要太长时间时,请始终使用EXPLAIN,并且 MySQL 会告诉您它认为应该做什么,同时推断您要求的数据。
  • @OleGooner 每次比较都会进行转换/转换,有 2500000*42000 次比较(减去优化器可以通过其他条件削减的比较),会有一些转换......
  • 您可以创建一个临时表,并提前完成转换,您可以在该表上执行连接,因为较小的表只会导致 47k 强制转换。遗憾的是,索引计算列在 MySQL 上不起作用:-/

标签: mysql sql join left-join primary-key


【解决方案1】:

查询的费用似乎是由于以下原因:

  • A 的 PK 和 B 的 PK 的 SQL 数据类型不同。
  • 表 A 可能在 Last_login_date_in_A 上没有索引

这意味着必须一次检查表 A 中的所有行,以确定 > 30 天前的条件是否为真。如果 A 有 2,500,000 行(正如您在 A 的行数中放置逗号的方式所证明的那样)而不是 250,000 行,则尤其如此。

在 Last_login_date_in_A 上添加索引可能会对您有所帮助,但由于需要更新附加索引,也会稍微减慢表的插入/更新/删除语句时间。

此外,您应该利用文档来解释 MySQL 为您的查询实际选择的查询计划:MySQL query plan documentation

【讨论】:

  • 是 2,50,000。印度就是这样写的。
猜你喜欢
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 2014-02-16
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多