[MySQL]
嘘があっても泣かない。
そもそも now() と sysdate() ではなにが違うのか? NOW() が、ステートメントを実行開始する時刻を返すのと違い、 SYSDATE() は、それが実行された時刻を返します(MySQL5.0以降?)
11.5. 日付時刻関数 http://dev.mysql.com/doc/refman/5.1/ja/date-and-time-functions.html
によると
SYSDATE() は、それが実行された時間を戻します。これは NOW() の動作によって異なり、ステートメントが 実行を開始する時間を示す定数時間を戻します。( ストアド ルーチンまたはトリガ内で、NOW() はルーチン またはトリガ文が実行を開始する時間を戻します。) そのほか、 SET TIMESTAMP 文は NOW() によって戻された値に影響を及ぼしますが、SYSDATE() によって 戻された値には影響しません。つまり、バイナリログのタイムスタンプ設定は、SYSDATE() の呼び出しには 効果をもたらさないということになります。
なんのこっちゃ?って感じですが、そのすぐ下の例を見るとすこし分かった気になります。
mysql> select now(), sleep(2), now(); +---------------------+----------+---------------------+ | now() | sleep(2) | now() | +---------------------+----------+---------------------+ | 2007-08-14 12:17:25 | 0 | 2007-08-14 12:17:25 | +---------------------+----------+---------------------+ 1 row in set (2.00 sec) mysql> select sysdate(), sleep(2), sysdate(); +---------------------+----------+---------------------+ | sysdate() | sleep(2) | sysdate() | +---------------------+----------+---------------------+ | 2007-08-14 12:17:28 | 0 | 2007-08-14 12:17:30 | +---------------------+----------+---------------------+ 1 row in set (2.01 sec)
つまり、where 句で SYSDATE() を使うと、レコード数回 SYSDATE() が実行されるらしく、遅くなります。たとえば、16000レコードのデータに対して
select count(*) from event_master \ where event_start_datetime < subdate (now(),1 );
select count(*) from event_master \ where event_start_datetime < subdate (sysdate(),1 );
を実行した場合、
という結果になりました。安直に考えれば、sysdate の代わりに now を使うと、 2倍程度の高速化になることになります(大雑把すぎますが。逆に考えれば、16000回も実行してもこの程度しか差がないとも言えます)ともあれ、特別な理由がない限り、sysdate()よりも now() を使った方がよさそうです。
またパフォーマンスだけでなく、レプリケーション利用時にも注意が必要です。
11.5. 日付時刻関数 http://dev.mysql.com/doc/refman/5.1/ja/date-and-time-functions.html SYSDATE() は同じステートメントの中でも、異なる値を戻すことができ、ま た SET TIMESTAMP に影響を受けないため、これは非決定性であり、従ってス テートメントに基づくバイナリ ロギングが使用されている場合、複製は安全 でないということになります。これが問題になる場合は、行ベースのロギング を使用するか、または --sysdate-is-now オプションでサーバを起動して、 SYSDATE() が NOW() のエイリアスになるようにしてください。
や
5.4.1.6. レプリケーションとシステム機能 http://dev.mysql.com/doc/refman/5.1/ja/replication-features-functions.html
を読んでわかるように、sysdate() では、レプリケーション環境で、整合性が取れなくなります。逆にこれを利用して、レプリケーションの同期遅延を計るぜ!ってことをやる方もおられるようです。
行ベースのロギングを使用している場合には、この点の心配はありません
の記載があるように、binlog_format を ROW にするとレプリケーションセーフになるようですが試してません。基本的に sysdate() じゃなきゃだめだ!ってことはないと思うので、sysdate() ではなく、now() を使った方がよさそうです。すでにsysdate()でプログラムを書いちゃったよ!という場合でも
[mysqld] sysdate-is-now
を追加するか、--sysdate-is-nowオプション付きで mysqld を起動すれば、now() が sysdate() の代わりに利用されますので、プログラムの修正なしに対応が可能です。