【问题标题】:Performance joining rows where date is between a start and end date日期介于开始日期和结束日期之间的性能连接行
【发布时间】:2015-03-14 02:46:12
【问题描述】:

我有 2 个表,每个表有几千行,我需要根据 2 个日期时间之间的日期时间加入它们。

select SQL_NO_CACHE * from A 
left outer join R on R.ActivityDate > A.StartDate and R.ActivityDate < A.EndDate;

目前查询速度很慢。我尝试添加索引,但根据解释的输出没有使用它们。这种查询的适当索引策略是什么?使用 between doesn't 代替 似乎没有什么不同。

如果执行直接连接,查询速度会快 13 倍(返回的行数减少 7%),但从逻辑上讲,我需要返回不匹配的行。当附加行数如此之低时,我不希望 2 种连接类型之间的差异如此之大。为什么外部连接这么慢?

感谢任何帮助或想法。

mysql> describe A;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| StartDate | datetime     | NO   |     | NULL    |       |
| EndDate   | datetime     | NO   |     | NULL    |       |
| Data      | varchar(100) | NO   |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> describe R;
+--------------+----------+------+-----+---------+-------+
| Field        | Type     | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+-------+
| ActivityDate | datetime | NO   |     | NULL    |       |
| Leads        | int(11)  | NO   |     | NULL    |       |
+--------------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)

【问题讨论】:

  • 使用&lt; 和/或&gt; 通常不会使用索引。
  • 我不确定您是否会得到任何改进,但您是否尝试过BETWEEN 而不是&gt;&lt;
  • 我尝试过。我将把它添加到问题中。
  • 为什么表没有 auto_increment ID 字段?

标签: mysql join inner-join outer-join


【解决方案1】:

无论匹配如何,执行 LEFT JOIN 都会强制显示 A 中的所有行

STRAIGHT JOIN 或 INNER JOIN 只会产生匹配 ON 子句的行

【讨论】:

  • 逻辑上我需要返回不匹配的行,因为即使 R 中没有匹配的行,我也需要显示来自 A 的数据。
  • 为什么表没有 auto_increment ID 字段?
  • 我已经删除了这个问题的真实表格。 A 有一个自动增量 ID。
【解决方案2】:

请尝试以下方法:

select SQL_NO_CACHE 
   * 
from A 
left outer join R 
  on ((R.ActivityDate - A.StartDate) * (R.ActivityDate - A.EndDate)) / 
      (CASE WHEN ABS((R.ActivityDate - A.StartDate) * (R.ActivityDate - A.EndDate)) = 0 
            THEN 1 
            ELSE ABS((R.ActivityDate - A.StartDate) * (R.ActivityDate - A.EndDate)) 
       END) = -1

上面的 on 子句在逻辑上等于您的问题中提出的那个。

仅当满足(R.ActivityDate &gt; A.StartDate) and (R.ActivityDate &lt; A.EndDate) 条件时,产品(R.ActivityDate - A.StartDate) * (R.ActivityDate - A.EndDate) 为负的原因。

之所以如此,是因为上述条件(R.ActivityDate - A.StartDate) &gt; 0 and (R.ActivityDate - A.EndDate) &lt; 0的小转变。

由于您的查询中没有&gt; &lt; 比较,请尝试执行时间是否会有所改善。

希望对你有帮助。

【讨论】:

  • 这很有趣,但性能大致相同,稍微慢了一点。
  • 谢谢你在你的情况下尝试这个,也为了你的回复:)问候。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多