これが私が昨日尋ねた質問です- https://stackoverflow.com/questions/22180727/left-joining-two-views-is-slow 。
私は助けになった良い答えを得ましたが、LEFT JOINが検索よりもはるかに遅い理由がわかりません。 LEFT JOINは16秒でした-私のテーブルは少なくとも90%最適化されていると確信しています-ルックアップを実行すると、それはわずか.14秒です。テーブルを左に結合した場合、これは遅くはないので、なぜビューなのでしょうか?
ビューの MySQLドキュメントによると
ビュー(更新可能なビューを含む)はMySQL Server 5.6で使用できます。ビューは、呼び出されたときに結果セットを生成するストアドクエリです。ビューは仮想テーブルとして機能します。
ビューについて最初に理解する必要があるのは、ビューが結果セットを生成することです。ビューから呼び出されたクエリから発生する結果セットは、オンデマンドで作成されるため、仮想テーブルです。結果セットをすぐにインデックス化するために後で呼び出すことができるDDLはありません。すべての意図と目的で、結果セットはインデックスのないテーブルです。実際には、実行していたLEFT JOINは基本的に、何らかのフィルタリングを施したデカルト積です。
2つのビューのJOINをより詳細に確認するために、MySQLがJOINとWHEREを評価するために使用する内部メカニズムを説明する昨年作成した投稿を参照します( JOIN条件とWHERE条件? )。 MySQL内部の理解 (ページ172)で公開されているメカニズムを紹介します。
ORDER BY
およびGROUP BY
にキーを使用できるかどうかを確認します。OK、インデックスを使用する必要があるようです。ただし、よく見てください。 WordのView
をTable
に置き換えた場合、メカニズムの実行がどうなるか見てください。
views
からレコードを取得するために使用できるキーを決定し、それぞれに最適なキーを選択しますview
。view
ごとに、キーの読み取りよりもview
スキャンの方が優れているかどうかを判断します。キー値に一致するレコードが多数ある場合、キーの利点が減り、view
スキャンが高速になります。views
が存在する場合にviews
を結合する順序を決定します。views
を結合から削除します。ORDER BY
およびGROUP BY
にキーを使用できるかどうかを確認します。すべてのテーブル(ビュー)にはインデックスがありません。したがって、JOINを実行すると、仮想テーブル、一時テーブル、またはインデックスのないテーブルでの作業は実際には不明確になります。使用されるキーはJOIN操作のためだけのものであり、物事をより速く検索するためのものではありません。
クエリ を、2014イエローページと2013イエローページの2つの電話帳を取得するものと考えてください。各イエローページの本には、住宅電話番号のホワイトページが含まれています。
明らかに、2つの電話帳には違いがあります。データベーステーブルのJOINを実行して2013年と2014年の違いを理解しても問題はありません。
2つの電話帳を手動でマージして違いを見つけることを想像してみてください。正気に聞こえませんか?それにもかかわらず、これは、2つのビューに参加するときにmysqldに要求することとまったく同じです。実際のテーブルを結合するのではなく、そこから便乗するインデックスがないことを覚えておいてください。
では、実際のクエリを振り返ってみましょう。
SELECT DISTINCT
viewA.TRID,
viewA.hits,
viewA.department,
viewA.admin,
viewA.publisher,
viewA.employee,
viewA.logincount,
viewA.registrationdate,
viewA.firstlogin,
viewA.lastlogin,
viewA.`month`,
viewA.`year`,
viewA.businesscategory,
viewA.mail,
viewA.givenname,
viewA.sn,
viewA.departmentnumber,
viewA.sa_title,
viewA.title,
viewA.supemail,
viewA.regionname
FROM
viewA
LEFT JOIN viewB ON viewA.TRID = viewB.TRID
WHERE viewB.TRID IS NULL
仮想テーブル(インデックスのないテーブル)viewAを使用しており、それを別の仮想テーブルviewBに結合しています。断続的に生成される一時テーブルは、viewAと同じ大きさになります。次に、大きな一時テーブルで内部ソートを実行して、それを区別します。
ビューの結果セットの一時的でインデックスなしの性質に沿って、JOINを評価する内部メカニズムを考えると、元のクエリ(2つのビューのLEFT JOIN)は桁違いの実行時間を取得しているはずです。同時に、 StackOverflowから取得した回答 は、今説明したのと同じJOINアルゴリズムを考えると、適切に機能するはずです。
私が投稿したばかりの悲惨な詳細が、理由についてのあなたの質問に答えることを願っています。
EXPLAIN EXTENDED [select query]
その後 SHOW WARNINGS
は、ビューの書き換えられた形式を表示します。ここから、パフォーマンス特性を分析する方が簡単です。
視力検査クエリは、一般的に最適化が容易ではありません。