web-dev-qa-db-ja.com

MySQL:LIKEまたはMONTHを使用して日付列をフィルターしますか?

MySQLのInnoDBテーブルから、特定の月の誕生日を持つ顧客を抽出する必要があるCRONタスクがあります。誕生日フィールドにはインデックスが付けられ、タイプはDATEです。

4月をフィルタリングすると、次のいずれかの方法でCustomersテーブルをクエリできます。

SELECT * 
FROM customers 
WHERE birthday LIKE "2015/04/%";

または:

SELECT * 
FROM customers 
WHERE MONTH(birthday) = 4;

あなたはどちらを勧めますか、そしてその理由は?

4
doc_id

DATEを型として使用することの要点は、データベースが効率的にデータをクエリできるようにすることです。これは、数値をINTではなくVARCHARとして保存するのと同じ理由です。これにより、エンジンはインテリジェントな決定を行うことができます。日付にLIKE演算子を使用すると、 正しいデータ型 を選択したことによるメリットが失われます。

MONTH(birthday)を使用すると、MySQLはDATEデータ形式に準拠していることがわかっている誕生日列の月の部分を取得できます。 LIKEを使用すると、文字ごとのパターンマッチングが行われ、かなりコストがかかり、実行速度が遅くなります。

LIKEで十分であれば、MONTH()は存在しません。組み込み関数は常に、LIKEクエリのDATEよりも優先されます。

10
LowlyDBA

私は行きます:

_SELECT * 
FROM customers 
WHERE MONTH(birthday) = 4;  
_

...月単位で選択するのが一般的な方法だからです。 MONTH()を使用すると、MySQLの組み込み関数が呼び出されますが、LIKEを使用すると、それが文字として扱われ、比較が行われるため、1つの操作を実行する代わりに、MySQLが2つ実行します。

5
Ahmad Abuhasna

(より多くのコメントに加えて、冗長な回答。)

  • 2つの例は同一ではありません-1つは2015年に限定されています。他はそうではありません。
  • _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はおそらく「最良の」答えです。
4
Rick James

100.000行をテストしました

SELECT * FROM customers WHERE MONTH(birthday) = 4; ==> 18秒

SELECT * FROM customers WHERE birthday LIKE "2015/04/%"; ==> 21秒

1
agokeren