すべての詳細行をプルバックしてクライアント側でカウントを行うよりも、データベースからカウントを返す方がはるかに高速です。
また、1 回のクエリで 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 としてエイリアス化されたサブクエリは、1 時間ごとに 1 行ずつ、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
確かに、これは現在よりもはるかに多くのクエリ テキストです。
これをコードに組み込むには、日付リテラルの 3 つの出現箇所を「%s」に置き換え、sprintf を使用して 3 つの出現箇所を書式設定された日付文字列に置き換えます。(3 つのオカレンスすべてに同じ値が渡されます。)