2009-03-12 3 views
6

MySQL 5.1でビューを使用するクエリを最適化しようとしています。ビューから1列を選択しても、常にフルテーブルスキャンが行われるようです。それは期待された行動ですか?MySQLビューでは常にフルテーブルスキャンを実行しますか?

ビューは、下の最初のクエリで指定したテーブルのSELECT「すべての列のこれらのテーブル - NOT *」にすぎません。

これは、ビューを構成するクエリからインデックス付き列PromotionIDを選択したときの私の説明出力です。ご覧のとおり、ビューの出力とは大きく異なります。

EXPLAIN SELECT pb.PromotionID FROM PromotionBase pb INNER JOIN PromotionCart pct ON pb.PromotionID = pct.PromotionID INNER JOIN PromotionCode pc ON pb.PromotionID = pc.PromotionID WHERE pc.PromotionCode = '5TAFF312C0NT'\G; 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: pc 
     type: const 
possible_keys: PRIMARY,fk_pc_pb 
      key: PRIMARY 
     key_len: 302 
      ref: const 
     rows: 1 
     Extra: 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: pb 
     type: const 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: const 
     rows: 1 
     Extra: Using index 
*************************** 3. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: pct 
     type: const 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: const 
     rows: 1 
     Extra: Using index 
3 rows in set (0.00 sec) 

出力、私は同じことを選択したが、ビューからのMySQLで

EXPLAIN SELECT vpc.PromotionID FROM vw_PromotionCode vpc WHERE vpc.PromotionCode = '5TAFF312C0NT'\G; 
*************************** 1. row *************************** 
      id: 1 
    select_type: PRIMARY 
     table: <derived2> 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 5830 
     Extra: Using where 
*************************** 2. row *************************** 
      id: 2 
    select_type: DERIVED 
     table: pcart 
     type: index 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: NULL 
     rows: 33 
     Extra: Using index 
*************************** 3. row *************************** 
      id: 2 
    select_type: DERIVED 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.pcart.PromotionID 
     rows: 1 
     Extra: 
*************************** 4. row *************************** 
      id: 2 
    select_type: DERIVED 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 5. row *************************** 
      id: 3 
    select_type: UNION 
     table: pp 
     type: index 
possible_keys: PRIMARY 
      key: pp_p 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 6. row *************************** 
      id: 3 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.pp.PromotionID 
     rows: 1 
     Extra: 
*************************** 7. row *************************** 
      id: 3 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 8. row *************************** 
      id: 4 
    select_type: UNION 
     table: pcp 
     type: index 
possible_keys: PRIMARY 
      key: pcp_cp 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 9. row *************************** 
      id: 4 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.pcp.PromotionID 
     rows: 1 
     Extra: 
*************************** 10. row *************************** 
      id: 4 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 11. row *************************** 
      id: 5 
    select_type: UNION 
     table: ppc 
     type: index 
possible_keys: PRIMARY 
      key: ppc_pc 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 12. row *************************** 
      id: 5 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.ppc.PromotionID 
     rows: 1 
     Extra: 
*************************** 13. row *************************** 
      id: 5 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 14. row *************************** 
      id: 6 
    select_type: UNION 
     table: ppt 
     type: index 
possible_keys: PRIMARY 
      key: ppt_pt 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 15. row *************************** 
      id: 6 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.ppt.PromotionID 
     rows: 1 
     Extra: 
*************************** 16. row *************************** 
      id: 6 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 17. row *************************** 
      id: NULL 
    select_type: UNION RESULT 
     table: <union2,3,4,5,6> 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: NULL 
     Extra: 
17 rows in set (0.18 sec) 

答えて

9

ビューはその性質上それほどインデックス化されていない彼らがアクセスされるたびにフルスキャンが必要です。一般的に言えば、ビューは実際には、小さな結果セットを返す非常に複雑な静的クエリがあり、毎回結果セット全体を取得する予定がある場合にのみ便利です。

編集:もちろん、ビューは基礎となるテーブルのインデックスを使用して、ビュー自体が最適化されます(そうでなければ、全く意味がありません)。ビューにはインデックスがないためビューのWHEREクエリを最適化することはできません。

ビューのインデックスを作成しようとしていないうちに、一時テーブルがシーンの背後に構築され、結果セットが返されていることがかなり確かです。一時テーブルを構築するにはすでに多くの時間がかかりますが、インデックスが必要なのかどうかを推測しようとする考えはありません。これは、MySQLが現在、どのインデックスをViewに使用するかを指定する方法を提供していないという第2のポイントをもたらします。どのフィールドをインデックス化する必要があるかをどのように知っていますか?あなたの質問に基づいて推測しますか?

テンポラリテーブルのフィールドにインデックスを指定できるので、Temporary Tableを使用することをお勧めします。しかし、経験から、これは本当に、本当に遅くなる傾向があります。

このビューに含まれるすべてがSELECT ALL FROM table1、table2、table3の場合、なぜ私はこのクエリがなぜViewにある必要があるのか​​尋ねなければならないでしょうか?何らかの理由で絶対必要な場合は、ストアドプロシージャを使用してクエリをカプセル化し、最適化されたパフォーマンスを得ながら、結果セットのデータベースへのより簡単な呼び出しの利点を維持することができます。

+0

http://dev.mysql.com/doc/refman/5.0/ja/view-restrictions.htmlここでは、ビューは基になるテーブルのインデックスを使用すると言います。 – Alex

+0

私はあなたが正しいと確信しています。MySQLビューのクエリはソーステーブルのインデックスを使用できます。ビュー自体に索引を付けることはできません。したがって、複数の表の列を含む単一の索引を持つことはできません。 – thomasrutter

+0

残念ながら、それは2番目のクエリがMySQLによってあまり最適化されていない理由を説明していません。私が考えることができるのは、おそらく、その見方が、それが意図された通りに正確に合わないということです。しかし、知らない。 – thomasrutter

3

私は情報の重要なポイントを見逃してしまった:(私のビューのクエリは実際に別のテーブルとの結合を持っているため、ビューはMERGEアルゴリズムの代わりにTEMPORARY TABLEアルゴリズムを使用している。

TEMPORARY TABLEアルゴリズムは、基礎となる表での索引の使用を許可していません。

これは、MySQLのバグのようですし、帰り2006年に報告されたが、それはされているようには見えません。 2009年に解決されました!http://forums.mysql.com/read.php?100,56681,56681

私はちょうどouteとしてクエリを書き直す必要があるように見えますrジョイン。

関連する問題