MysqlでNOW()を使うとキャッシュに乗らないのを解決したい

   

MySQLではキャッシュの機構がたくさんついています。

その中でも、クエリキャッシュを有効に使えれば、速度は早くなります。ただし、【全く同じクエリ】でなければキャッシュに乗りません。select対象のテーブルがInsertまたはUpdateされてもキャッシュには乗りません。

というところで、気になるのがNOW()の扱いです。以下のように使うことが多いです。

select * from test where date > now();

これは、【今の日付よりも後の日付のものをセレクトする】というSQLです。NOW()は現在の時刻を返却してくれる関数です。時分秒まで返却してくれます。

結論から言うと、キャッシュされません。その回避方法も考えます。

MySqlのバージョンは5.1.73です。

 

■まずはキャッシュに乗らないことを確認する【前提】

以下のクエリを実行して、キャッシュの状況を確認します。

show status like '%cache%';

 

で、今回キャッシュに乗るかどうかの確認をするselect文は以下の通りです。

クエリ 今の日付よりも前のview_dateのものを抽出します。

select * from test where view_date < now();

view_dateには 2014-06-18 のように年月日まで書いてあります。

 

○対象クエリ実行前のキャッシュの状態

Qcache_hits 0
Qcache_inserts 0
Qcache_lowmem_prunes 0
Qcache_not_cached 2

 

○一回目実行した時のキャッシュの状態

Qcache_hits 0
Qcache_inserts 0
Qcache_lowmem_prunes 0
Qcache_not_cached 3

 

○二回目実行した時のキャッシュの状態

Qcache_hits 0
Qcache_inserts 0
Qcache_lowmem_prunes 0
Qcache_not_cached 4

 

というようにキャッシュヒットはしていません。キャッシュに挿入もされていません。not_cachedの値が増えていくだけでした。

以下の様なクエリでもキャッシュには乗りませんでした。

select * from test where view_date < date_format(now(),'%Y-%m-%d');

そもそもNOW()とか付いているとキャッシュは効かないということですね。

 

■解決策

以下の様なクエリだとキャッシュに乗るのを確認しています。

select * from test where view_date < '2014-06-18';

プログラム上で、日付を計算してやったほうがキャッシュに乗るということですね。

あと、完全にリアルタイムである必要がないのであれば以下のように時分秒を固定値にすることで、一定期間キャッシュさせることも可能です。

select * from test where view_date < '2014-06-18 xx:xx:59';

 

■一般的によく言われていること

あんまりmysql上で、複雑な結合やWhere、単純でもGroupByやOrder、Countなどはしないほうがいいです。プログラム側でやったほうが速いですよー。

 

という感じのナレッジ的なやつでした。

megane

megane

最近、個人事業主から法人へと進化しました。 エンジニア歴13年位です。PHPとかMysqlを使ってWebシステムを構築します。 Javaも書きます。 CakePHPも使います。 サーバのチューニングもごりごりやります。 あと、お肉と自動車が好きです。Twitterとか申請どうぞ。

 - mysql ,