15.1. Lesson: データベースの概要
PostgreSQLのを使用する前に、一般的なデータベース理論をさらうことによって私たちの根拠を確認してみましょう。サンプルコードはどれも入力する必要はありません。それは説明目的のためだけにあります。
このレッスンの目標: 基本的なデータベースの概念を理解します。
15.1.1. データベースとは何ですか?
データベースは、典型的にはデジタル形式の、1つ以上の用途のための組織化されたデータの集合からなる。 -ウィキペディア
データベース管理システム(DBMS)は、データベースを操作し、ストレージ、アクセス、セキュリティ、バックアップなどの機能を提供するソフトウェアで構成されています。 -ウィキペディア
15.1.2. テーブル
リレーショナルデータベースとフラットファイルデータベースでは、テーブルは、縦の列(名前で識別される)と横の行のモデルを使用して構成されたデータ要素(値)のセットです。テーブルには指定された数の列がありますが、任意の数の行を持つことができます。各行は、候補キーとして識別された特定の列部分に現れる値によって識別されます。 -ウィキペディア
id | name | age
----+-------+-----
1 | Tim | 20
2 | Horst | 88
(2 rows)
SQLデータベースではテーブルは 関係 としても知られている。
15.1.3. 列/フィールド
列は、特定の単純型のデータ値の集合であり、表の各行に対して1つです。列は、行を構成する構造を提供します。フィールドという用語は、多くの場合、フィールド(またはフィールド値)を使用して、1つの行と1つの列の交差点に存在する単一項目を具体的に参照する方が正しいと考えられますが、列と互換的に使用されます。 -ウィキペディア
列:
| name |
+-------+
| Tim |
| Horst |
フィールド:
| Horst |
15.1.4. レコード
レコードは、テーブル行に格納されている情報です。各レコードには、テーブル内の各列のフィールドがあります。
2 | Horst | 88 <-- one record
15.1.5. データ型
データ型は、列に格納できる情報の種類を制限します。* - ティムとホルスト*
データ型には多くの種類があります。最も一般的なものに焦点を当ててみましょう:
String
- 自由形式のテキストデータを格納しますInteger
- 整数を格納しますReal
- 小数を保存しますDate
- 誰も忘れないよう、ホルストの誕生日を格納しますBoolean
- シンプルな真/偽の値を格納します
フィールドに何も保存しないようにデータベースに指示することができます。フィールドに何もない場合、フィールドコンテンツは 'null'値 と呼ばれます:
insert into person (age) values (40);
select * from person;
結果:
id | name | age
---+-------+-----
1 | Tim | 20
2 | Horst | 88
4 | | 40 <-- null for name
(3 rows)
There are many more datatypes you can use - check the PostgreSQL manual!
15.1.6. 住所データベースをモデル化
データベースが構築されるかを確認するために、単純なケーススタディを使用してみましょう。住所のデータベースを作成したいとします。
Try Yourself
簡単な住所を構成し、データベースに格納したいプロパティを書き留めます。
住所の構造
住所を記述するプロパティは列です。各列に格納される情報のタイプは、そのデータ型です。次のセクションでは、概念的な住所テーブルを分析して、それをより良くする方法を見てみましょう。
15.1.7. データベース理論
データベースを作成するプロセスには、現実世界のモデルを作成することが含まれます。実世界の概念を取り入れ、エンティティとしてデータベースに表現します。
15.1.8. 正規化
データベースの主なアイデアの1つは、データの重複/冗長性を避けることです。データベースから冗長性を除去するプロセスを正規化といいます。
正規化は、データベース構造が汎用照会に適しており、挿入、更新、および削除の異常(データの整合性が失われる可能性がある)などの望ましくない特性がないことを確実にする体系的な方法です。 -ウィキペディア
正規「形」には様々な種類があります。
簡単な例を見てみましょう:
Table "public.people"
Column | Type | Modifiers
----------+------------------------+------------------------------------
id | integer | not null default
| | nextval('people_id_seq'::regclass)
| |
name | character varying(50) |
address | character varying(200) | not null
phone_no | character varying |
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
select * from people;
id | name | address | phone_no
---+---------------+-----------------------------+-------------
1 | Tim Sutton | 3 Buirski Plein, Swellendam | 071 123 123
2 | Horst Duester | 4 Avenue du Roix, Geneva | 072 121 122
(2 rows)
同じ名前の通りや都市の友達が多いとしましょう。このデータが複製されるたびに、領域が消費されます。さらに悪いことに、都市名が変更された場合は、データベースを更新するために多くの作業を行う必要があります。
15.1.9. Try Yourself
重複を低減し、データ構造を正規化するために、上記の理論 people テーブルを再設計します。
You can read more about database normalisation here
15.1.10. 索引
データベース索引は、データベース表のデータ検索操作の速度を向上させるデータ構造です。 -ウィキペディア
たとえば教科書を読んでいて概念の説明を探してるが、その教科書には索引がなかったとします。必要な情報が見つかるまで、1つの表紙から読み始め、書籍全体を通して作業を進めなければなりません。教科書の裏にある索引は、関連情報を持つページに素早くジャンプするのに役立ちます:
create index person_name_idx on people (name);
名前の検索が高速になります:
Table "public.people"
Column | Type | Modifiers
----------+------------------------+-------------------------------------
id | integer | not null default
| | nextval('people_id_seq'::regclass)
| |
name | character varying(50) |
address | character varying(200) | not null
phone_no | character varying |
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
"person_name_idx" btree (name)
15.1.11. 連番
連番は、一意の番号ジェネレータです。通常、テーブル内の列の一意の識別子を作成するために使用されます。
この例では、IDは連番です - 数は、レコードがテーブルに追加されるたびに1つ増えます:
id | name | address | phone_no
---+--------------+-----------------------------+-------------
1 | Tim Sutton | 3 Buirski Plein, Swellendam | 071 123 123
2 | Horst Duster | 4 Avenue du Roix, Geneva | 072 121 122
15.1.12. エンティティ関係図の作成
正規化されたデータベースでは、通常、多くの関係(テーブル)があります。エンティティ関係図(ER図)は、関係間の論理依存関係を設計するために使用されます。レッスンの前半から正規化されていない people テーブルを考えてみましょう:
select * from people;
id | name | address | phone_no
----+--------------+-----------------------------+-------------
1 | Tim Sutton | 3 Buirski Plein, Swellendam | 071 123 123
2 | Horst Duster | 4 Avenue du Roix, Geneva | 072 121 122
(2 rows)
ちょっとした作業で2つのテーブルに分割でき、同じ通りに住む人のために通りの名前を繰り返す必要がなくなります:
select * from streets;
id | name
----+--------------
1 | Plein Street
(1 row)
および:
select * from people;
id | name | house_no | street_id | phone_no
----+--------------+----------+-----------+-------------
1 | Horst Duster | 4 | 1 | 072 121 122
(1 row)
その後、「キー」 streets.id と people.streets_id を使用して2つのテーブルをリンクできます。
この2つのテーブルのためのER図を描く場合は、次のようになります。
ERダイアグラムは、関係「一対多」を表現する助けになります。この場合、矢印記号は、1つの通りに対して住んでいる人々は何人もいることがあると示しています。
Try Yourself
この people モデルにはまだいくつかの正規化の問題があります - さらに正規化して、ER図を用いて自分の考えを示すことができるかどうか確認してみてください。
15.1.13. 制約、主キーと外部キー
リレーション内のデータがモデラーのデータの格納方法と一致するように、データベースの制約が使用されます。たとえば、郵便番号の制約により、数字が 1000 と 9999 の間に入ることが保証されます。
主キーは、レコードを一意にする1つ以上のフィールドの値です。通常、主キーはidという連番です。
外部キーは、(他のテーブルの主キーを使用して)別のテーブルに一意のレコードを参照するために使用されます。
ERダイアグラムでは、テーブル間の結合は、通常、主キーにリンクする外部キーに基づいています。
ここでの人々の例を見てみると、テーブルの定義によれば、street列は街路テーブルの主キーを参照する外部キーです:
Table "public.people"
Column | Type | Modifiers
-----------+-----------------------+--------------------------------------
id | integer | not null default
| | nextval('people_id_seq'::regclass)
name | character varying(50) |
house_no | integer | not null
street_id | integer | not null
phone_no | character varying |
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"people_street_id_fkey" FOREIGN KEY (street_id) REFERENCES streets(id)
15.1.14. トランザクション
データベース内のデータを追加、変更、または削除するときは、何か問題が生じた場合にデータベースを良好な状態に保つことが常に重要です。ほとんどのデータベースは、トランザクションサポートと呼ばれる機能を提供します。トランザクションを使用すると、データベースへの変更が計画通りに実行されなかった場合に戻ることができるロールバック位置を作成できます。
会計システムを持っているというシナリオを取ります。1つの口座から資金を転送し、他にそれらを追加する必要があります。一連のステップは次のように進むでしょう。
JoeからR20を削除
AnneをR20に追加
処理の間に何か問題(例えば停電)が発生した場合、トランザクションはロールバックされます。
15.1.15. In Conclusion
データベースを使用すると、簡単なコードの構造を使用して構造化された方法でデータを管理できます。
15.1.16. What's Next?
これでデータベースが理論的にどのように動作するか見てしまいましたので、カバーしてきた理論を実装する新しいデータベースを作成してみましょう。