让数据库返回一个计数会快得多,而不是拉回所有详细信息行并在客户端进行计数。
您可以在一个查询中提取整整 24 小时的计数,这(可能)比对数据库进行 24 次往返以获取单个计数要高效得多。
c_blacklist(timestamp)
如果您有一个索引,甚至更好的覆盖索引,也可能会提高(查询的)性能c_blacklist(timestamp,reason)
。
如果timestamp
列是 datatype TIMESTAMP
,那么我们可以做一些简单的算术来推导出“小时”,并按每个“小时”计算。
SELECT FROM_UNIXTIME((UNIX_TIMESTAMP(cb.`timestamp`) DIV 3600) * 3600) AS `cb_hour`
, COUNT(1) AS cb_count
FROM `c_blacklist` cb
WHERE cb.`timestamp` >= DATE_ADD('2012-06-26 18:00',INTERVAL -1 DAY)
AND cb.`timestamp` < '2012-06-26 18:00'
AND cb.`reason` = 'hardbounce'
GROUP BY FROM_UNIXTIME((UNIX_TIMESTAMP(cb.`timestamp`) DIV 3600) * 3600)
ORDER BY FROM_UNIXTIME((UNIX_TIMESTAMP(cb.`timestamp`) DIV 3600) * 3600)
如果时间戳列是 datatype DATETIME
,使用不同的表达式来获取小时可能会更快:
SELECT DATE_FORMAT(cb.`timestamp`,'%Y-%m-%d %H:00:00') AS `cb_hour`
, COUNT(1) AS cb_count
FROM `c_blacklist` cb
WHERE cb.`timestamp` >= DATE_ADD('2012-06-26 18:00',INTERVAL -1 DAY)
AND cb.`timestamp` < '2012-06-26 18:00'
GROUP BY DATE_FORMAT(cb.`timestamp`,'%Y-%m-%d %H:00:00')
ORDER BY DATE_FORMAT(cb.`timestamp`,'%Y-%m-%d %H:00:00')
此查询将有“间隙”,其中没有要计算的行,也就是说,它们不会返回零计数。
这可以通过提供一个返回“小时”的每个值的行源来解决,然后对结果集执行左连接。在以下语句中,别名为 h 的子查询返回 24 行,每小时一行。我们将其用作针对“结果”查询(从上方)进行左连接的驱动行源。任何我们没有匹配到的地方,我们都会得到一个 NULL 来计数。我们可以通过一个简单的函数调用将 NULL 替换为零。
SELECT h.hour AS cb_hour
, IFNULL(c.cb_count,0) AS cb_count
FROM (SELECT DATE_ADD('2012-06-26 18:00',INTERVAL -1*d.i HOUR) AS `hour`
FROM (SELECT 00 AS i UNION ALL SELECT 01 UNION ALL SELECT 02 UNION ALL SELECT 03
UNION ALL SELECT 04 UNION ALL SELECT 05 UNION ALL SELECT 06 UNION ALL SELECT 07
UNION ALL SELECT 08 UNION ALL SELECT 09 UNION ALL SELECT 10 UNION ALL SELECT 11
UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15
UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19
UNION ALL SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23
ORDER BY 1 DESC
) d
) h
LEFT
JOIN (SELECT FROM_UNIXTIME((UNIX_TIMESTAMP(cb.`timestamp`) DIV 3600) * 3600) AS `cb_hour`
, COUNT(1) AS cb_count
FROM `c_blacklist` cb
WHERE cb.`timestamp` >= DATE_ADD('2012-06-26 18:00',INTERVAL -1 DAY)
AND cb.`timestamp` < '2012-06-26 18:00'
AND cb.`reason` = 'hardbounce'
GROUP BY FROM_UNIXTIME((UNIX_TIMESTAMP(cb.`timestamp`) DIV 3600) * 3600)
ORDER BY FROM_UNIXTIME((UNIX_TIMESTAMP(cb.`timestamp`) DIV 3600) * 3600)
) c
ON c.cb_hour = h.hour
ORDER BY h.hour
当然,这比您目前拥有的查询文本要多得多。
要将其放入我的代码中,我会将出现的三个日期文字替换为“%s”,并使用 sprintf 将出现的三个日期替换为格式化的日期字符串。(所有三个事件都传递了相同的值。)