MySQLのInnoDBテーブルから、特定の月の誕生日を持つ顧客を抽出する必要があるCRON
タスクがあります。誕生日フィールドにはインデックスが付けられ、タイプはDATE
です。
4月をフィルタリングすると、次のいずれかの方法でCustomersテーブルをクエリできます。
SELECT *
FROM customers
WHERE birthday LIKE "2015/04/%";
または:
SELECT *
FROM customers
WHERE MONTH(birthday) = 4;
あなたはどちらを勧めますか、そしてその理由は?
DATE
を型として使用することの要点は、データベースが効率的にデータをクエリできるようにすることです。これは、数値をINT
ではなくVARCHAR
として保存するのと同じ理由です。これにより、エンジンはインテリジェントな決定を行うことができます。日付にLIKE
演算子を使用すると、 正しいデータ型 を選択したことによるメリットが失われます。
MONTH(birthday)
を使用すると、MySQLはDATE
データ形式に準拠していることがわかっている誕生日列の月の部分を取得できます。 LIKE
を使用すると、文字ごとのパターンマッチングが行われ、かなりコストがかかり、実行速度が遅くなります。
LIKE
で十分であれば、MONTH()
は存在しません。組み込み関数は常に、LIKE
クエリのDATE
よりも優先されます。
私は行きます:
_SELECT *
FROM customers
WHERE MONTH(birthday) = 4;
_
...月単位で選択するのが一般的な方法だからです。 MONTH()
を使用すると、MySQLの組み込み関数が呼び出されますが、LIKE
を使用すると、それが文字として扱われ、比較が行われるため、1つの操作を実行する代わりに、MySQLが2つ実行します。
(より多くのコメントに加えて、冗長な回答。)
WHERE birthday BETWEEN '2015-04-01' AND '2015-04-01' + INTERVAL 1 MONTH
_はINDEX(birthday)
を使用できますが、それは来月生まれる人のみを対象としています。mnth TINYINT UNSIGNED COMMENT 'derived from MONTH(birthday)
があったとしても、INDEX(mnth)
は使用されない可能性があります。これは、テーブルの「大きな」割合が望ましいためです。オプティマイザは、テーブルスキャンが同じくらい高速であると判断する場合があります。WHERE MONTH(birthday) = 4
はおそらく「最良の」答えです。100.000行をテストしました
SELECT * FROM customers WHERE MONTH(birthday) = 4
; ==> 18秒
SELECT * FROM customers WHERE birthday LIKE "2015/04/%"
; ==> 21秒