MySQLのサブセレクトパフォーマンスの質問?
-
19-08-2019 - |
質問
MySQLのサブセレクトパフォーマンスに関するアドバイスが必要です。変更できない理由により、JOINを使用してクエリフィルタを作成することはできません。WHEREには別のAND句しか追加できません。
パフォーマンスとは:
select tasks.*
from tasks
where
some criteria
and task.project_id not in (select id from project where project.is_template = 1);
比較対象:
select tasks.*
from tasks, project
where
some criteria
and task.project_id = project.id and project.is_template <> 1;
is_template = 1のプロジェクトは比較的少数であり、is_template <!> lt; <!> gt;のプロジェクトは多数存在する可能性があることに注意してください。 1。
何も変更せずにフィルターをかけることができない場合、副選択なしで同じ結果を達成する他の方法はありますか?
解決
1つだけの選択が必要なため、2番目の方がより効率的であると考えていますが、確かに、各クエリを説明して結果を確認する必要があります。
EXPLAIN select tasks.*
from tasks
where
some criteria
and task.project_id not in (select id from project where project.is_template = 1);
EXPLAIN select tasks.*
from tasks, project
where
some criteria
and task.project_id = project.id and project.is_template <> 1;
他のヒント
この2つの間にどの程度の差があるかは、<!> quot;いくつかの基準<!> quot;そして、それが提供するインデックスを使用する機会です。ただし、プロジェクトを持たないタスクがある場合、結果の点では同等ではないことに注意してください。 2番目はこれと同等です:
select tasks.*
from tasks
where
some criteria
and task.project_id in (select id from project where project.is_template <> 1);
最初の方がより適切に拡張できると思います:
結合を行うと、mysqlは内部的に、指定された結合条件に従って結合された2つのテーブルで構成される一種の一時テーブルを作成します。結合条件を指定していないので、すべてのプロジェクトに対してリストされたすべてのタスクを含む一時テーブルを作成します。 where句を適用する前にこれを実行することはかなり確信しています(ただし、Explainツールで確認してください)。
結果:それぞれが10個ある場合、10 * 10行= 100になります。これは、数字が大きくなるにつれて大きくなることがわかります。次に、この一時テーブルの場所を適用します。
対照的に、サブクエリは各テーブルから関連する行のみを選択します。
しかし、スケーリングが懸念事項でない限り、私はそれが本当に重要だとは思わない。
MySQLバージョンのペストのようなサブクエリを避ける<!> lt; 6.0。まだ開発のアルファ段階にあることを考えると、6.0を使用しているとは思えません。知る限り、MySQLオプティマイザーはサブクエリをうまく処理しません。いくつかの主要な作業が6.0のオプティマイザーの改良に費やされ、サブクエリの機能は改善されましたが、これらの変更は5.0または5.1シリーズには反映されていません。