web-dev-qa-db-ja.com

MySQLパフォーマンス-単一の値に対する「IN」節と等号(=)

これは非常に単純な質問で、答えは「問題ではない」と想定していますが、とにかく質問しなければなりません...

PHPで作成された一般的なSQLステートメントがあります。

_$sql = 'SELECT * FROM `users` WHERE `id` IN(' . implode(', ', $object_ids) . ')';
_

以前の有効性チェック(_$object_ids_は、少なくとも1つの項目とすべての数値を含む配列)を想定しているので、代わりに次のようにする必要がありますか?

_if(count($object_ids) == 1) {
    $sql = 'SELECT * FROM `users` WHERE `id` = ' . array_shift($object_ids);
} else {
    $sql = 'SELECT * FROM `users` WHERE `id` IN(' . implode(', ', $object_ids) . ')';
}
_

または、チェックのオーバーヘッドcount($object_ids)は、実際のSQLステートメントに何が保存されるか(もしあれば)価値がありませんか?

35
JudRoman

それらのどちらも実際には大きな問題ではありません。データベースとの通信におけるネットワーク遅延は、count($object_ids)オーバーヘッドまたは=INオーバーヘッドのどちらをはるかに上回ります。私はこれを時期尚早の最適化のケースと呼んでいます。

実際のボトルネックがどこにあるかを知るために、アプリケーションをプロファイルして負荷テストする必要があります。

17
mellamokb

他の回答のほとんどは、結論を出すものではなく、推測にすぎません。したがって、 @ Namphibianの回答からの良いアドバイス に基づいて、OPのクエリと同様のクエリでEXPLAINを実行しました。

結果は以下のとおりです。


_= 1_を含むクエリの場合はEXPLAIN

Explain for a query with <code>= 1</code>


EXPLAININ(1)を使用したクエリの場合:

Explain for a query with <code>IN(1)</code>


EXPLAININ(1,2,3)を使用したクエリの場合:

Explain for a query with <code>IN(1,2,3)</code>


ご覧のとおり、この種のクエリでは、MySQLはIN(1)を_= 1_と同じになるように最適化します。 @ mesの回答 は、より複雑なクエリでは必ずしもそうとは限らないことを示しているようです。

だから、EXPLAINを自分で実行するのが面倒だった人は、もう知っています。そして、はい、自分のクエリでEXPLAINを実行して、この方法で処理されることを確認できます。 :-)

52
J.D.

MySQLステートメントの間に違いはなく、MySQLオプティマイザーはINを=に変換します。気にしないでください。

24
Konerak

Explainステートメントを使用して2つのクエリを実行します。これにより、MySQLの動作が表示されます。 MySQLの最適化に焦点を当てるのは、MySQLがクエリを内部で実行することです。実行されるクエリを最適化するのは少し時期尚早です。

たとえばインデックスがない場合、これらのクエリはどちらもパフォーマンスが非常に悪くなる可能性があります。 MySQLのEXPLAINステートメントはここでは重要です。そのため、実行速度の遅いクエリに到達すると、EXPLAINステートメントでその理由が示されます。

10
Namphibian

私は内部的にmysqlがIN (6)クエリを= 6クエリとまったく同じように扱うので、気にする必要がないと思います(ちなみにこれは時期尚早の最適化と呼ばれます)。

3

Explainステートメントでクエリを実行すると、結果は次のようになります enter image description here

「等しい」演算子の方が優れていることは明らかです。13行をスキャンし、「IN」演算子はすべての行をスキャンします

0
mes