两个(带子查询)或一个查询在where子句中选择max(date)。 MySQL的

时间:2013-10-10 14:24:10

标签: mysql performance

我需要创建一个表并存储一些事件的缓存状态。所以我将只做两个操作:

1)插入事件的id,它的状态以及该记录存储在db中的时间;

2)获取具有特定事件ID的最后一条记录。

有几种方法可以获得结果(状态):

方法1:

SELECT status FROM status_log a
WHERE a.event_id = 1
ORDER BY a.update_date DESC
LIMIT 1

方法2:

SELECT status FROM status_log a
WHERE a.update_date = (
  SELECT max(b.update_date) FROM status_log b
  WHERE b.event_id = 1
)  AND a.event_id = 1

所以我有两个问题:

  1. 使用哪个查询
  2. 要设置为update_date字段的哪个字段类型(int或timestamp)

2 个答案:

答案 0 :(得分:1)

实际上,您的第二个查询无法解决问题'查找事件#1'的最新更新日期 - 因为可能有许多不同的事件具有相同的最新update_date。因此,就语义而言 - 您应该使用第一个查询。 (编辑后已修复

如果您要通过event_id索引创建索引,则第一个查询将生效,并且此列将具有良好的基数(即WHERE子句将使用该索引过滤足够少的行)。但是,这可以通过向索引添加列update_date来改进 - 但这只有在有许多行具有相同event_id(许多行足以使MySQL使用第二个索引部分)时才有意义 - 并且再次使用第一个索引部分内的基数良好。

但在实践中 - 我的建议只是一个理论,你必须用EXPLAIN语法和你自己的实际数据测量来解决这个问题。

对于数据类型 - 通常的做法是使用适当的数据类型(即日期时间/时间戳表示时间点的东西)

答案 1 :(得分:1)

使用哪个查询

我相信第一个应该更快。无论如何,只需对它们运行EXPLAIN,你就会发现自己。

您应该使用的索引是:

ALERT TABLE status_log ADD INDEX(event_id, update_date)

现在......您是否注意到这些查询不相同?第二个将返回具有最大日期的所有event_id的所有状态。

要设置为update_date字段的哪个字段类型(int或timestamp)

如果您有一个名为update_date的字段,我无法想象为什么int会起到同样的作用。将问题改为在datetimetimestamp之间进行选择,则答案符合要求。如果您只想知道数据库中的记录何时更新,请使用时间戳。如果update_date引用您域模型中的实体,请转到datetime。您很可能需要在日期执行计算(添加时间,删除时间,提取一个月等),因此使用unix时间戳(我认为应该几乎只写)将导致额外的计算时间,因为您我必须将timestamp转换为datetime,然后对该结果执行该功能。