From:ビューの功罪
ビュー(View)がとても便利な道具であることは、全ての DB エンジニアの方に同意してもらえるでしょう。もしビューなしで開発せねばならないとしたら、非常に手間が増えるに違いありません。特に正規化した結果、テーブルが増えすぎて結合が多く発生する場合など、あらかじめビューで厄介な部分を吸収させておくと、クエリがすっきりして効率的な開発が行なえます。クエリがすっきりするということは、バグも減るということです。しかも非正規化と違ってデータ独立性を保持できる「クリーン」な技術のうえ、ビューに必要な操作のみを許可することでセキュリティ強化にも役立つなど、その利点は多大です。デイトはビューを「クエリの缶詰」と、うまい表現をしました。保存がきく上に、開ければ常に新鮮なデータを取り出せる、というわけです。
しかし、一時的な使い捨てビューならばともかく、システムの中に組み込まれるビューの場合は、その使用に慎重を期す必要があります。なぜなら、ビューには一つの大きな欠点があるからです。それは、パフォーマンスの低下です。最近はビューの性能も向上して、可能な限り実表のインデックスを使用する工夫などが取り入れられ、昔ほど酷い速度低下とメモリ圧迫はなくなりました。恐らく皆さんも、ビューの使用にためらいを感じる人は少ないでしょう。しかしそれでもなお、注意を要するケースがあります。それは、ビュー定義で集約操作を行なっているときです。具体的には、次のような演算が含まれる場合です。
理由は直観的にも想像がつくでしょう。集約した結果を得るには、もとの実表に対して集約を行なわざるをえないからです(結局のところ、ビューが実データを保持していない、ただの「クエリ」だという点を忘れないでください)。ことに、物理メモリによるソートが発生すると格段に SQL が遅くなります。また似たような理由から、ビューからさらに別のビューを作った場合も、パフォーマンス低下を招く危険があります。多重ビューは大変危険です。
つまるところ、NULL やインデックスなど、データベースにおける他の便利な道具や概念と同様の厳しい格言がビューにも当てはまるのです。すなわち
適切な使用は薬だが濫用すると毒になる
どうやら DB エンジニアは、この格言を常に胸にしまっておく必要がありそうです。それがなかなかできないのですけれど。
もしビューの使用が実際にパフォーマンス低下を招いた場合、どう対処すればよいのでしょう。皆さんの隣には、「このビューに投げた SQL、1時間たっても返ってこないんですけど …… 」と困惑顔のプログラマがため息をついています。彼(女)の悩みをどう解決してあげればよいでしょう?
最近の DBMS はこの苦境に対する解決策をいくつか用意しています。一つが、ビューにインデックスを張るという技術。SQL Sever が実装しています。もう一つが、マテリアライズド・ビューの技術。Oracle、DB2、PostgreSQL が実装しています。
マテリアライズド・ビューというのは、直訳すれば「実体化されたビュー」、つまり文字通り、実データを保持するビューのことです。これはもう、ビューというよりほとんどテーブルに近い存在です。実際、Oracle の Enterprise Manager でオブジェクトの一覧を表示すると、ビューではなくテーブルの欄に出てきます。デイトも、マテリアライズド・ビューは本当の意味でのビューではない、と述べていてます[1]。マテリアライズド・ビューのアイデア自体は、けっこう昔から実現している DBMS もあったのですが、本格的に実装され始めたのは最近です。私も 100万行/テーブル を超える規模の業務では重宝しています。これがパフォーマンス面で劇的な改善をもたらす理由は、以下の三つです。
要するに、普通のテーブルと同じ扱いができる、というのが大きな利点です。大規模テーブルの場合、ビューとマテリアライズド・ビューの体感速度的な差は、鈍行電車と新幹線の「のぞみ」ぐらい違う、と言っても過言ではないでしょう。
ここまで読んで「素晴らしい、私も明日からマテリアライズド・ビューに乗り換えよう」と思った方 ―― それは早計です。さきの格言をもう一度思い出してください。
適切な使用は薬だが濫用すると毒になる
これは残念ながら、マテリアライズド・ビューにも当てはまります。実データを保持することで、次に挙げる欠点を抱え込むことになります。
どちらも、普通のビューを使っているときには起こらない問題でした。リフレッシュを怠れば、実表とデータが食い違ってしまいます。いわば「缶詰が腐る」のです。これはメーカーの信用に関わる大問題です。リフレッシュの方法には、大別して「 ON COMMIT 」と「 ON DEMAND 」がありますが、前者はリフレッシュに失敗したときのエラーを取得しづらいので、基本的には後者を使うべきです(クリティカルなシステムならなおさら)。それはつまり、手動リフレッシュが必要ということですから、定期的に管理者が行なうにせよ、アプリケーションから行なうにせよ、一手間増えます。不必要にマテリアライズド・ビューを増やすと、管理に苦労することになります。リフレッシュを忘れようものなら、データ不整合が起きて痛い目を見るのは必至です。(こういうのはシステム的なエラーではないので、その場では気づかない「爆弾」になることが多いのです。) おまけに、そのリフレッシュにもけっこう時間がかかるのも悩みどころです。 残念ながら、ここにおいてもやはり、狼男を倒す「銀の弾」は見つかりません。あるのはただただ、「諸刃の剣」だけです ―― きっと、どの分野でもそうなのでしょうが。
ほとんどの方が、NULL の危険性は承知しておられるでしょう(と期待します)。しかしビューの危険性というのは、意外に盲点で、汚いテーブル設計に対抗する善意のエンジニアの最後の拠りどころ、みたいな使われ方もします。その使い方をむげに否定する気は、私にもありません。要するにビューの使用は、NULL の使用と並んで、開発者の判断力を問われる場面だ、ということを理解してほしいのです。開発の効率性、クエリの可読性、セキュリティ、パフォーマンス、管理の手間、こうした様々な要素を総合的に考慮したうえで、ビューをいかに使うか、使わないか、あるいはマテリアライズド・ビューに乗り換えるか、あるいはインデックスを張ることで対処するか、判断を下さねばなりません。
「銀の弾」がない、という言葉は、悲観的に聞こえるかもしれませんが、それほど悪く受け取ることもありません。ある意味、これは取り組み甲斐のある問題の一つだからです。それにそもそも、銀の弾が見つかってしまったら、多くのエンジニアはきっと廃業の憂き目を見ることになるのですから。
少なくともリレーショナルモデルに関する限り、実体化されないことこそビューの真髄なのである。 ・・・・・・ したがって、「実体化されたビュー」とは、何とも矛盾した表現である。 C.J.デイト 『C.J.Dateのデータベース実践講義』 p.76デイトは上記の箇所で、マテリアライズド・ビューは、ビューよりはむしろスナップショット(ある時点での関係値を保存したもの)の概念を実装したものであり、正確にはビューと呼ぶべきではない、と注意を促しています。確かにその通りなのですが、マテリアライズド・「ビュー」という用語は既にかなり流通してしまっているので、いまさら用語を変更するのは難しいでしょうし、やるにしても時間がかかるでしょう。当面は、混乱しないよう注意するほかありません。
From:ビューの功罪