MySQL/MariaDB の NOW() と SYSDATE(): 違いは何か? この落とし穴に注意してください!
最近、OracleデータベースにおけるSYSDATE()とCURRENT_DATE()の違いに関する長い記事を読みました。以前、MySQLにおけるNOW()とSYSDATE()の違いについて調べたことを思い出しました。これらの関数は非常によく似ており、多くの場合(ほとんどの場合?)、違いに気づくのは難しいでしょう。しかし、全く同じではありません。どちらをいつ使うべきかについて、簡単なガイドをご紹介します。
2 つのうちより単純な方、そしておそらく皆さんが期待するであろう方は SYSDATE() です。SYSDATE() は、処理が実行された瞬間のタイムスタンプ(日付だけでなく)を返します。
MariaDB [(なし)]> sysdate() を選択します。 +---------------------+ | sysdate() | +---------------------+ | 2024-01-27 18:09:04 | +---------------------+
とても簡単です。では(しゃれではありません!)NOW()とSYSDATE()を比較してみましょう。
MariaDB [(なし)]> now()、sysdate() を選択します。 +---------------------+---------------------+ | now() | sysdate() | +---------------------+---------------------+ | 2024-01-27 18:09:50 | 2024-01-27 18:09:50 | +---------------------+---------------------+
うーん…同じですか?!?
その違いを説明する例を以下に示します。
MariaDB [(なし)]> now()、sleep(10)、sysdate() を選択します。 +---------------------+-----------+---------------------+ | now() | sleep(10) | sysdate() | +---------------------+-----------+---------------------+ | 2024-01-27 18:11: 12 | 0 | 2024-01-27 18:11: 22 | +---------------------+-----------+---------------------+
違いは次のとおりです。NOW() はクエリが開始された時刻です。トリガーまたはストアドプロシージャ内であれば、コードの実行が開始された時刻です。SYSDATE() は常に実行された瞬間の時刻を返します。
なぜNOW()が必要なのでしょうか?巨大なテーブル(数百万行)を処理していて、24時間以上経過したすべてのレコードを選択したいとしましょう。次のような処理が可能です。
big_table から record_id を選択します。WHERE date_entered < NOW() - 間隔 1 DAY;
NOW() はクエリの先頭で一度実行され、各行の比較にその値を使用します。しかし、このコードを SYSDATE() に変更すると、すべての行に対して SYSDATE() を実行するため、実行速度が大幅に低下します。処理量が増えるだけでなく、行1で24時間前のデータだったものが行10,000,000では異なる場合があり、一貫性のない結果になる可能性があります。
小規模なデータセットや簡単なクエリなどでは、これらの要素は影響しない可能性があり、コード上ではそれほど予測が難しくても問題にならないかもしれません。しかし、大規模なデータセットでは、これらの違いに注意する必要があります。
ちなみに、MySQL と MariaDB はどちらも、必要に応じて SYSDATE() を NOW() とまったく同じように動作させるオプションを提供しています。