2016-08-25 10 views
2

Myテーブル 'my_logs'には約20,000,000レコードがあり、数日以内に各日付にいくつのログがあるか調べたいと思います。MYSQLクエリで時間帯を効率的に変換する最良の方法

私は、クエリの説明だけで完了するために私にミリ秒を取る、それは良いことだ

SELECT DATE_FORMAT(created_at, '%Y-%m-%d') as date, 
     COUNT(*) as count 
    FROM my_logs 
    WHERE created_at BETWEEN '2016-07-01' AND '2016-07-04' 
    GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d') 

の下にこのクエリ

+------------+---------+ | date | count | +------------+---------+ | 2016-07-01 | 1623 | | 2016-07-02 | 1280 | | 2016-07-03 | 2032 | +------------+---------+

のような結果が欲しい

+------------+---------+-------+-----------------------------+ |select_type | table | type | possible_keys | +------------+---------+-------+-----------------------------+ | SIMPLE | my_logs| index | index_my_logs_on_created_at | +------------+---------+-------+-----------------------------+

+-----------------------------+---------+----------+ | key | key_len | rows | +-----------------------------+---------+----------+ | index_my_logs_on_created_at | 10 | 23458462 | +-----------------------------+---------+----------+

+-----------------------------------------------------------+ | Extra | +-----------------------------------------------------------+ | Using where; Using index; Using temporary; Using filesort | +-----------------------------------------------------------+

しかし、私は私の国での時間に合わせて、各レコードのタイムゾーンを変換する必要があり、私は「日」情報によってグループに必要なので、私は列自体を変換する必要があります。

両方

SELECT COUNT(*) 
    FROM my_logs 
    WHERE DATE_ADD(created_at, INTERVAL 8 HOUR) BETWEEN '2016-07-01' AND '2016-07-04' 
    GROUP BY DATE_FORMAT(DATE_ADD(created_at, INTERVAL 8 HOUR), '%Y-%m-%d') 

SELECT COUNT(*) 
    FROM my_logs 
    WHERE CONVERT_TZ(created_at, "+00:00", "+08:00") BETWEEN '2016-07-01' AND '2016-07-04' 
    GROUP BY DATE_FORMAT(CONVERT_TZ(created_at, "+00:00", "+08:00"), 

'%Y-%m-%d' では)

クエリを完了するために12Sについての私を取る、それが遅い耐え難いです!

(説明トップでクエリと同じである)


私はそれが一般的な問題だと思うが、私はそれに対処するための良い方法を見つけることができない、誰もがより効率的に持っていませんそれを行う方法?ありがとう!

+1

['convert_tz'](http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_convert-tz)は、あるタイムゾーンから別のタイムゾーンに変換します。 –

+0

どちらの場合にもクエリプラン( 'EXPLAIN'出力)を提供できますか? – Vatev

+0

出力を追加します!ありがとう。実際には、私はすでに私が望む出力を持っていますが、私の問題は効率についてです。タイムゾーンの問題を検討した後、私は簡単に元気でなければならないと考える効率的な方法を見つけることができません。 –

答えて

1

TIMESTAMPDATETIMEのどちらのデータ型を使用しましたか? (ただし、無視します)

インデックス付きの列(created_at)をすべての関数(CONVERT_TZ())内に「非表示」しないでください。 WHERE句では索引を使用できないため、代わりに表をスキャンする必要があります。この修正は簡単です:

WHERE created_at >= '2016-07-01' - INTERVAL 8 HOUR 
    AND created_at < '2016-07-04' - INTERVAL 8 HOUR 

(またはCONVERT_TZを使用)。私が4日から深夜を含むバグも修正しました。注:+ INTERVAL...さえも事実上の関数です。

SELECTGROUP BYの式は、パフォーマンスにとってはあまり重要ではありません。

+0

素晴らしい!したがって、WHERE句の日付範囲を変換し、GROUP句のカラムを変換するのが最善の方法です!それは私の問題を解決する!ありがとう –

関連する問題