【问题标题】:SQL Joining Autoincrement pseudo parent_idSQL Joining Autoincrement 伪 parent_id
【发布时间】:2014-04-28 23:36:44
【问题描述】:

您好,我有一个简单的实时课程数据表

t_course_live -->
id (INT) (主键 AUTO_INCREMENT)
trade_timestamp 日期时间
费率浮动

id | trade_timestamp     | rate
1  | 2014-04-28 20:53:32 | 1.38629
2  | 2014-04-28 20:53:34 | 1.38623
3  | 2014-04-28 20:53:39 | 1.38625

所以我确保 auto_increment 序列中存在漏洞,并且 trade_timestamps 总是随着 ids => trade_timestamp(id)

我想将每一行与“下一个父母”一起加入。这意味着具有 id+1 的行,因此我可以计算时间戳之间的差异。我的 SQL 方法如下所示,它可以完成这项工作,但花费的时间太长,因为已经有 90 万多个条目。

SELECT ... (do the calculation with t1.trade_timesamp and t2.trade_timestamp) ...
FROM t_course_live t1
LEFT JOIN (
  SELECT t2_inner.*, (t2_inner.id+1) AS next_row 
  FROM t_course_live t2_inner
  WHERE DATE(t2_inner.trade_timestamp) = '2014-04-28'
) AS t2 ON t1.id = t2.next_row
WHERE DATE(t1.trade_timestamp) = '2014-04-28'

使用 EXPLAIN 语句,您会得到:

  id    |   select_type |   table   |   type    |   possible_keys   |   key     |   key_len |   ref     |   rows    |   Extra
    1   |   SIMPLE      |   t1      |   ALL     |   NULL            |   NULL    |   NULL    |   NULL    |   943429  |   Using where
    1   |   SIMPLE      |  t2_inner |   ALL     |   NULL            |   NULL    |   NULL    |   NULL    |   943429  |   Using where; Using join buffer (flat, BNL join)

所以问题是,如何让这个查询更快,将 id 与 id+1 连接起来?如果可能的话,我想不用 parent_id 列。

【问题讨论】:

  • ID 字段上已经有一个索引,我想加入。但是 EXPLAIN 显示,在操作索引字段时,在我的情况下 id+1 然后 sql 不会将其用作索引连接
  • 在示例中,您的时间戳相差约 5 秒。如果它们没有太大差异,您是否只需要按时间戳合并数据?或者您是否只需要合并一天的时间戳,所以说(323, 2014-04-28 23:59:52)(324, 2014-04-29 00:00:08)不会合并?
  • 在 trade_timestamp 上添加索引。请注意,DATE() 不能利用这样的索引,但“trade_timestamp BETWEEN x AND y”可以!如果您仍在苦苦挣扎,请考虑提供适当的 DDL(和/或 sqlfiddle)以及所需的结果集。

标签: mysql sql performance join query-optimization


【解决方案1】:

将此查询重写为:

SELECT ... (do the calculation with t1.trade_timesamp and t2.trade_timestamp) ...
FROM t_course_live t1
LEFT JOIN t_course_live t2
ON t1.id = t2.id+1
WHERE
  t1.trade_timestamp>= '2014-04-28'
  AND t1.trade_timestamp < '2014-04-29'
  and t2.trade_timestamp>= '2014-04-28'
  AND t2.trade_timestamp < '2014-04-29'

使用DATE(column) 函数并加入子查询可防止MySql 使用索引。

我假设已经创建了trade_timestamp 上的索引。

=========== 编辑 =========================

我之前的回答有一个微妙的错误。
上述查询不等同于原始查询,因为这些条件:

  and t2.trade_timestamp>= '2014-04-28'
  AND t2.trade_timestamp < '2014-04-29'

将查询从左连接转换为常规连接。

正确的查询是:

SELECT ... (do the calculation with t1.trade_timesamp and t2.trade_timestamp) ...
FROM t_course_live t1
LEFT JOIN t_course_live t2
ON t1.id = t2.id+1
   AND t2.trade_timestamp>= '2014-04-28'
   AND t2.trade_timestamp < '2014-04-29'
WHERE
  t1.trade_timestamp>= '2014-04-28'
  AND t1.trade_timestamp < '2014-04-29'

【讨论】:

  • 就是答案!好一个!该索引是在trade_timestamp 上创建的。如果没有 DATE 函数,查询需要大约 0,094 秒才能获得 26.000 行。非常感谢您的小费。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 2016-11-26
相关资源
最近更新 更多