如果你有一个索引created
作为前导列,MySQL也许能够进行反向扫描。如果您有 24 小时内没有任何事件,则您可能会返回不属于该期间的行。为了确保您在该时间段内获得一行,您确实需要包含一个下限created
专栏也是这样的:
SELECT * FROM `eventos`
WHERE ...
AND `created` < FROM_UNIXTIME( {$timestamp} )
AND `created` >= DATE_ADD(FROM_UNIXTIME( {$timestamp} ),INTERVAL -24 HOUR)
ORDER BY `created` DESC
LIMIT 1
我认为这里性能的关键是一个索引created
作为前导列,以及 WHERE 子句中引用的所有(或大多数)其他列,并确保查询使用该索引。
如果您需要不同的时间间隔(低至秒),则可以轻松推广此方法。
SELECT * FROM `eventos`
WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL 0*{$nsecs} SECOND)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*{$nsecs} SECOND)
ORDER BY `created` DESC
LIMIT 1
从您的代码来看,24 小时周期似乎以任意时间为界...如果时间函数返回例如1341580800 ('2012-07-06 13:20'),那么您的十个经期都将从当天的 13:20 到第二天的 13:20。
(注意:如果您的参数是 unix 时间戳整数,请确保数据库能够正确解释它。)
在单个查询中提取十行可能会更有效。如果保证“时间戳”是唯一的,则可以制作这样的查询,但查询文本将比您现在拥有的复杂得多。我们可能会在每个周期内获取 MAX(timestamp_) ,然后将其连接回来以获取行......但这会非常混乱。
如果我要尝试拉出所有十行,我可能会尝试使用UNION ALL
方法,不是很漂亮,但至少可以调整。
SELECT p0.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL 0*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p0
UNION ALL
SELECT p1.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p1
UNION ALL
SELECT p2.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -3*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p2
UNION ALL
SELECT p3.*
FROM ...
同样,这可以概括为将秒数作为参数传递。将 HOUR 替换为 SECOND,并将“24”替换为具有秒数的绑定参数。
虽然有点啰嗦,但应该可以正常运行。
将其返回到单个结果集中的另一种非常混乱且复杂的方法是使用内联视图来获取十个周期的结束时间戳,如下所示:
SELECT p.period_end
FROM (SELECT DATE_ADD(t.t_,INTERVAL -1 * i.i_* {$nsecs} SECOND) AS period_end
FROM (SELECT FROM_UNIXTIME( {$timestamp} ) AS t_) t
JOIN (SELECT 0 AS i_
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) i
) p
然后将其加入到您的表中...
ON `created` < p.period_end
AND `created` >= DATE_ADD(p.period_end,INTERVAL -1 * {$nsecs} SECOND)
并为每个周期 GROUP BY p.period_end 拉回 MAX(created),将其包装在内联视图中。
然后将其连接回您的表以获取每一行。
但这确实非常非常混乱,难以理解,而且不可能比您已经在做的更快(或更有效)。您可以做出的最大改进是运行 9 个查询所需的时间。