web-dev-qa-db-ja.com

MySQLビューはどのように機能しますか?

ビューを作成するときは、基本的に、結合するテーブルの1つのデータが変更されたときに自動的に処理される新しいテーブルを作成します。あれは正しいですか?

また、ビューでサブクエリを使用できないのはなぜですか?

39
John Nall

ビューはテーブルのように機能しますが、テーブルではありません。それは決して存在しません。ビュー名を参照するときに実行されるのは、準備されたSQLステートメントだけです。 IE:

_CREATE VIEW foo AS
  SELECT * FROM bar

SELECT * FROM foo
_

...これは実行と同等です:

_SELECT x.* 
  FROM (SELECT * FROM bar) x
_

MySQLDumpには、ビューに挿入される行が含まれることはありません...

また、なぜ私のビューでサブクエリを使用できないのですか????

残念ながら、これは(疑わしい)設計によるものです。ドキュメント化されているMySQLビューには多くの制限があります。 http://dev.mysql.com/doc/refman/5.0/en/create-view.html

つまり、架空のテーブル/準備されたステートメントだけの場合、理論的には通常のテーブル/クエリと同じ(またはそれ以下)のパフォーマンスしか得られないということですか。


番号。
テーブルには、インデックスを関連付けることができます。これにより、データの取得がより高速になります(挿入/更新には多少のコストがかかります)。一部のデータベースは、「マテリアライズド」ビューをサポートしています。これは、インデックスを適用できるビューです。これは、MySQLがサポートしないであることは驚くべきことではありません制限されたビュー機能を考慮して(v5 IIRCでのみ開始され、非常に遅いゲーム)。

ビューは派生テーブルであるため、ビューのパフォーマンスは、それが構築されているクエリと同じくらい良好です。そのクエリがうまくいかない場合、パフォーマンスの問題はSnowballだけです...つまり、ビューをクエリするとき-WHERE句のビュー列参照が関数(IE:_WHERE v.column LIKE ..._、notWHERE LOWER(t.column) LIKE ...)の場合、オプティマイザは基準(述語と呼ばれる)を元のクエリにプッシュし、高速化します。

53
OMG Ponies

私も同じ問題に遭遇しました(驚いたことに、検索でOracleとMSがサポートしているようです)。

最終的なビューに2つの追加のビューを作成することで、この制限を回避します(少なくとも現時点では、使用できないことが証明されるまで)。

例:

CREATE VIEW Foo1 AS
    SELECT * FROM t ORDER BY ID, InsertDate DESC

CREATE VIEW Foo2 AS
    SELECT * FROM Foo1 GROUP BY ID

CREATE VIEW Foo AS
    SELECT * FROM Foo2 ORDER BY ID

上記の例には、基本的にすべてのリビジョンを含む一時テーブルであるテーブル「t」があります。私の 'Foo'(ビュー)は基本的に、各レコードの最新のリビジョンのみの単純なビューです。今のところ問題なく動作しているようです!

更新:

これがMySQL 5.1の別のバグかどうかはわかりませんが、上記の例は実際には機能しません。 「Foo1」は期待どおりに機能しますが、「Foo2」はグループ化する前の順序を無視するようです。そのため、私の最終結果は意図したものではありません。 (驚くべきことに)「DESC」を「ASC」に変更しても同じ結果が得られます。

また、 17.5.1。構文を表示 セクション、それは明確に述べています:

「ビューは、さまざまな種類のSELECTステートメントから作成できます。ビューは、ベーステーブルまたは他のビューを参照できます。結合、UNION、およびサブクエリを使用できます。」

データベースを5.6に更新して、再試行します。

2
Jeach

違いは次のとおりです。

ビューの場合、サブクエリはwhere-部分ではなく、from-部分でのみ使用できます。

CREATE VIEW v AS SELECT * FROM foo WHERE id IN (SELECT id FROM bar) 

動作しますが、同時に読み取り専用のビューが表示されます...単一のテーブルの単純なビューにより、ビューを基になっているテーブルに「スルー」で更新できます。

2
eagle275