ビュー(DB)について


ビューとはテーブルからSELECTしてきた取得結果や複数テーブルを結合した結果を仮想的なテーブルとして作成する手法である。

仮想的なテーブルとあるとおり、通常作成されるテーブルとは違い、実態はない。

めちゃくちゃ簡単に言うとSELECT文を名前をつけて保存したものである。

ビューを作成する構文は以下のとおり
```
CREATE VIEW ビュー名 AS SELECT文
```

下記のような家計簿テーブルで費目が食費だけのレコードのビューを作ってみる

DBはpostgresでテーブル名はhousehold_account_book

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/90d3610f-d125-c2c6-b523-ce1ff570c3d4.png)


``` SQL
CREATE VIEW test_view AS 
SELECT
    * 
FROM
    household_account_book 
WHERE
    expense_item = '食費'

```


これでビューができた。

DBを確認すると、ビューができているのがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/c769a18b-c43a-ddc2-fb26-412f31fced0f.png)

以降はこのビューを参照すれば簡単に食費だけのデータを確認できる。

ビューの参照結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/9272fd9d-b843-4b99-a2e5-8b03556b0fa6.png)

元のテーブルの更新されればビューも自動で更新される。
元テーブル(寿司代が追加)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/43d6bcfc-c0ff-e4da-a957-5dd4d4bdc530.png)


元テーブル更新後のビュー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/2f717dbf-ebe6-e695-cb0f-5bd50a8fe949.png)








もちろん、ビューに対してSQLを実行することも可能である。
``` SQL
SELECT
    * 
FROM
    test_view 
WHERE
    memo = '高級焼肉代';
```

出力結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/7c70f8fa-00f8-29af-ce0e-2b24b5350df8.png)


# ビューの削除方法

削除するときはDROP VIEW文を使う
```
DROP VIEW ビュー名
```
先程の食費データのビューを削除してみる。


``` SQL
DROP VIEW test_view
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/c21e4493-5cc4-538c-f5c5-ec2b35d0770d.png)



ビューを削除できた。簡単。




# ビューのメリット


### 容量を圧迫しない

ビュー自体がSELECT文なので、データを保存しないで、SELECT文そのものを保存するのでテーブルより容量を圧迫しない。


### SELECT文を何度も書く必要がなくなる

よく各SELECT文をビューとして保存しておけば何度も書かなくて済むので、効率よくデータの確認が行える。

特に複数テーブルを結合させるときなどに効果的だ。


# ビューのデメリット

### パフォーマンスの低下

ビューを利用したSQLの実行指示を受けると、DBはビューを展開してSQL文に変換して実行する。
実行する側はシンプルに記述されたSQLを実行しているつもりだが、実際に実行されるSQLは複雑なものになる。

そのため、ビューに対してWHERE句で条件をつけたり結合したりするとパフォーマンスが低下してしまう。


### DB更新処理に制限がある

insert,update,deleteの処理をビューに対して行うことは可能であるが、行う場合は以下の条件が満たされている場合に限られる。

・SELECTでdistinctが使用されていない
・GROUP BYを使用していない
・HAVINGを使用していない
・集約されたビューではない
・FROM句に含まれるテーブルが1つである

基本的には1つのテーブルに影響を与える場合にのみ更新処理は可能である。


# マテリアライズド・ビューについて

マテリアライズド・ビューとはSELECT文の結果をキャッシュとして保持しているテーブルのようなものである。


ビューとの違いはデータの実体を持っていることである。

マテリアライズド・ビューのメリットは主に以下の２つがある。

### 処理が高速

ビューは実態を持っていないので、呼び出されるたびにSQLを展開し、データの取得を行わなければならない。

比べて、マテリアライズド・ビューだと実態のデータを持っているので、SQLを都度実行する必要がなく処理が高速になる。


### 主キーやインデックスが作成できる

ビューでは主キーを作成することはできないが、マテリアライズド・ビューでは主キーを作成することができる。

そのため、主キーを用いての検索やデータ重複を防ぐことができる。

またインデックスもビューでは作成することができないが、マテリアライズド・ビューでは作成することができる。

ビューに比べて、高速検索が可能となる。


デメリットについては主に以下の２つが挙げられる。

### 最新データを取得するにはリフレッシュが必要

マテリアライズド・ビューはデータの実態があるので、ただ取得するだけでは常に最新のデータが取得できるわけではない。

最新データを取得する場合にはリフレッシュというのを行わなければならない。
リフレッシュを行わないと最新データとのズレが生じてしまう。


### ストレージ容量を消費する

マテリアライズド・ビューは通常のテーブルと同様にストレージ容量を消費する。
むやみやたらに作成すると、容量を圧迫するのでご利用は計画的に。


### マテリアライズド・ビューの作成方法

作成する際の構文は以下の通り

```
CREATE MATERIALIZED VIEW マテリアライズド・ビュー名 AS SELECT文
```

先ほど作成したビューと同じ内容のものをマテリアライズド・ビューで作成してみる。

``` SQL
CREATE MATERIALIZED VIEW test_m_view AS 
SELECT
    * 
FROM
    household_account_book 
WHERE
    expense_item = '食費'

```

実行すると作成されていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/c97694e1-a0a2-485c-c9a5-fb9dec776dc8.png)


中身を見てみると以下のようになっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/2e1f2227-03e8-8715-b3d9-a48c99a71d7a.png)

ビューのときのように寿司代を追加してもマテリアライズド・ビューでは自動で反映されない。(都度SELECTするのではなく、データの実態があるため)


最新の情報を反映させるにはリフレッシュを行う。

リフレッシュするには以下の文を実行する。

```
REFRESH MATERIALIZED VIEW マテリアライズドビュー名
```


先ほど作成したマテリアライズド・ビューで試してみる。

``` SQL
REFRESH MATERIALIZED VIEW test_m_view;
```

実行後に確認すると最新のデータになっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/4622e08f-ad23-dae5-40cb-c710382d874f.png)

自動リフレッシュというのも存在するようだが、今回は割愛。
詳しく調べたら追記するかも、、



マテリアライズド・ビューの削除については下記の構文を実行するだけなのでビューと同様非常に簡単。

```
DROP MATERIALIZED VIEW マテリアライズド・ビュー名
```
先ほど作成したマテリアライズド・ビューを削除するには以下の通り実行する。

``` SQL
DROP MATERIALIZED VIEW test_m_view;
```

見事削除することに成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/ce988f13-e4dd-7c08-13d8-2ebc50c1abc7.png)