はじめに
お家で学べるデータベースの基本を読んでみました。
Progateをやっているのでコードの書き方はわかりますが、データベースの考え方についてはまったくわからないので基礎から学ぶために読みました
本書は手を動かすことを強調している本です。なかなか読んでいるだけでは理解できないのでとても助かります
自分が見返すように書いたのですが、結構内容が濃くなってしまったのでAIで要約したものを載せています。
1章 データベースの基本性能
データベースには4つの基本性能が求められます。
-
データ操作(検索、登録、修正、削除)
データの管理は、電話帳のように情報を検索し、更新することから始まりました。 -
同時実行制御
複数のユーザーが同時にデータを扱う際の処理方法で、利便性とリスクのバランスが必要です。 -
耐障害性
データの消失を防ぐため、データの冗長化やバックアップが重要です。これらはコストがかかるため、企業は費用対効果を考慮する必要があります。 -
セキュリティ
データ漏洩を防ぐ対策が必須であり、クラウド利用が増える中、ユーザーがデータベースを意識する機会は少ないものの、企業にとってはデータ保護が重要です。
データベースは5つの種類があり、最も普及しているのはリレーショナルデータベースです。初心者はリレーショナルデータベースを学ぶことが推奨されます。
2章 リレーショナルデータベースとは
リレーショナルデータベースは、データを二次元表(テーブル)で管理するデータベースであり、データを操作するためにSQLという言語を使います。SQLはプログラミングに近いが直感的に使いやすい構造です。
リレーショナルデータベース管理システム(DBMS)はデータベースを管理するソフトウェアであり、本書ではMySQLを使用します。DBMSはミドルウェアで、アプリケーション(業務用ソフトウェア)とOSの間で機能します。
アプリケーションの作成方法には、0から開発する「スクラッチ」と、既存のソフトウェアを利用する「パッケージ」の2つのアプローチがあります。
3章 データベース運用におけるコスト
データベースシステムには、初期コスト(イニシャルコスト)と運用コスト(ランニングコスト)がかかります。ライセンス料金には、CPU性能やユーザー数に基づく料金形態があります。商用利用では、データベースのサポートサービスも必要で、年々サポートの質が低下し最終的には終了(EOSL)します。
ソフトウェアの課金方式には、永続ライセンス、サブスクリプション、従量課金の3つがあり、それぞれ特徴があります。たとえば、従量課金制は使った分だけ支払う形態で、AWSのようなクラウドサービスで多く採用されています。
4章 データベースとアーキテクチャ構成
データベースアーキテクチャの歴史は、スタンドアロンから始まり、クライアント/サーバモデル、そしてWeb3層構造へと進化してきました。
- スタンドアロンは単独で動作するシステムですが、拡張性や同時利用に制限があります。
- クライアント/サーバモデルでは、ネットワーク接続により複数ユーザーが利用可能になり、セキュリティリスクも増大します。
- Web3層構造では、プレゼンテーション層、ビジネスロジック層、データアクセス層の3つの層でアーキテクチャを分割することで、セキュリティと運用管理の両立が可能になりました。
特に、Webブラウザを用いた標準的なインターフェースが導入され、クライアント側の管理が簡素化されました。
5章 DBMSを操作する基本知識
MySQLのインストールとAWS設定
MySQLのインストールやAWS設定に約1時間かかるので時間に余裕をもって行いましょう。
###コネクション
MySQLでユーザーと接続することを「コネクション」と呼び、以下のコードでログインします。
mysql -uroot -pPassword
現在の接続数を確認するには以下のコマンドを使用してください
show status like 'Threads_connected';
ログオフ
MySQLからログオフするには quit コマンドを使用します。
管理コマンド
DBMSには様々な管理コマンドがあり、システムの状況を確認できます。
以下のコマンドでMySQLの稼働時間を確認できます。
show global status like 'uptime';
データベースの階層構造
リレーショナルデータベースは「インスタンス」「データベース」「スキーマ」「テーブル」の階層に分かれているが、MySQLではこの構造が異なり、スキーマとデータベースが同じ役割を果たします。
6章 SQLの基本を学ぶ
データベースの確認と操作
データベース内のテーブル一覧を確認するには show databases;
、特定のデータベースを使用するには use database_name;
を使用します。
ORDER BY の使用
ソートするには ORDER BY
を使用し、複数の列でソートする場合はカンマ区切りで列名を指定します。
集約関数
min
, max
, count
は文字列に対しても使用可能。重複を無視してカウントする機能もあります。
GROUP BY と HAVING
SQL文の実行順序の関係で、WHERE
では集約関数は使えず、代わりに HAVING
を使用します。
DEFAULT 値の確認
デフォルト値や自動インクリメントを確認するには show create table テーブル名 \G
を使用します。
テーブルの構造確認
テーブルの詳細情報は 'desc テーブル名; 'で確認でき、主キーや自動インクリメントの設定も確認できます。
ビュー
ビューは仮想テーブルであり、元のテーブルのSELECT
結果を保存せずに参照する。create view
で作成し、元テーブルに影響を与えません
サブクエリ
サブクエリは一時的な結果を返すもので、階層の制限がありません。
結合
内部結合(INNER JOIN
)は共通の行のみを表示し、外部結合(OUTER JOIN
)は片方のテーブルを基準に表示する。
第7章 トランザクションと同時実行制御
トランザクションのACID特性
トランザクションには、以下の4つの「ACID特性」があります。
-
Atomicity(原子性)
すべての操作が成功するか、失敗すればすべてが元に戻されることを意味します。たとえば、ECサイトで商品購入が途中で失敗した場合、在庫や決済情報は変更前の状態に戻ります。 -
Consistency(一貫性)
トランザクションが終了した後、データベースのデータは常に一貫した状態を保ちます。たとえば、銀行の送金操作では、送金元と送金先の口座の残高が正しく反映される必要があります。 -
Isolation(分離性)
複数のトランザクションが同時に実行されても、互いに干渉しないように処理されます。これにより、ホテルの予約システムなどで二重予約が防がれます。 -
Durability(持続性)
トランザクションが完了すると、その結果は永続的に保存され、システムが障害を起こしても失われません。
トランザクションの分離レベル
データベースは、トランザクションの分離性を高めるために4つの分離レベルを提供しています。これにより、データが他のトランザクションにどの程度の影響を与えるかを制御できます。
-
Read Uncommitted(リードアンコミッテッド)
他のトランザクションがコミットする前のデータも読み取ることができます。このため、読み取ったデータが最終的に反映されない可能性があり、データの不整合が発生するリスクが高いです。 -
Read Committed(リードコミッテッド)
クエリが実行された時点で、コミット済みのデータだけを読み取ります。他のトランザクションがコミットするまでの中間結果は見えません。このレベルでは、ノンリピータブルリードの問題が発生することがあります。 -
Repeatable Read(リピータブルリード)
最初にクエリを実行した時点のデータがトランザクション中ずっと保持され、同じクエリであれば同じ結果が返されます。これにより、ノンリピータブルリードを防ぐことができますが、ファントムリードの問題が発生する可能性があります。 -
Serializable(シリアライザブル)
最も厳密な分離レベルで、すべてのトランザクションが一列に並んで実行されるように扱います。これにより、ファントムリードやノンリピータブルリードも防ぐことができますが、パフォーマンスが低下することが多いです。
デッドロック
デッドロックとは、2つ以上のトランザクションが互いにロックを奪い合い、どちらも先に進めなくなる状況を指します。たとえば、トランザクションAがテーブルaをロックし、トランザクションBがテーブルbをロックしたまま、お互いに相手のロックを待っていると、デッドロックが発生します。デッドロックを防ぐための方法として、トランザクションの順序を決めたり、頻繁にコミットを行うなどが推奨されます。
第8章 テーブル設計の基礎
リレーショナルデータベースでは、すべてのデータはテーブルに格納されます。テーブル設計は、適切なデータ構造を作成するための重要なステップであり、データの整合性や効率性に大きく影響を与えます。テーブルには主キーを設定し、一意に識別できる列を持たせる必要があります。
正規化
正規化は、データの重複を最小限にし、データの一貫性を保つためにテーブルを適切に設計するプロセスです。正規化には以下の段階があります。
-
第一正規形(1NF)
各列の値がスカラ値(単一の値)であることを保証します。たとえば、1つのセルに複数の値が含まれている場合、それは第一正規形を満たしていないことになります。 -
第二正規形(2NF)
第一正規形を満たし、主キーに対して完全に依存する属性のみがテーブルに含まれている状態です。 -
第三正規性(3NF)
第二正規形を満たしていることに加え、すべての非キー属性が主キーに直接依存する必要があります。
9章 バックアップとリカバリ
DBMSが持つ持続性の3つの仕組み
データベース管理システム(DBMS)は、データの「持続性」(Durability)を保証するために、3つの重要な仕組みを提供しています。
- ログ先行書き込み (WAL: Write Ahead Log)
- データベースバッファ
- クラッシュリカバリ
WAL(ログ先行書き込み)
WALとは、データの更新を直接ディスクに書き込む代わりに、まずメモリ上のログバッファに書き込む手法です。MySQLではこのログを「InnoDBログ」と呼びます。
WALのメリット:
- ディスクへの連続書き込みにより、ランダム書き込みよりもパフォーマンスが高い。
- まとめてディスクにフラッシュするため、書き込み頻度が少なくなる。
- データベースバッファを活用して、効率的にデータを更新できる。
データベースバッファ
データベースバッファは共有メモリ上に存在し、以下のデータを保持します:
- データページ: テーブルやインデックスの一部を読み込んだデータ
- ダーティページ: メモリ内で変更されたが、まだディスクに反映されていないデータ
- インデックスページ: インデックス構造がキャッシュされ、クエリ処理が高速化される
データベースバッファの使用場面:
- データ読み取り時
クエリで要求されたデータがバッファにある場合、ディスクアクセスを避け、高速に処理。 - データ更新時
更新内容はまずバッファに記録され、変更内容はWALに記録される。 - 複数トランザクション同時実行時
トランザクションの一貫性を保ちながら、バッファを介してデータの効率的な読み書きを実現。
クラッシュリカバリ
システム障害が発生しても、WALファイルを使用してデータベースを復旧できます。これは「ロールフォワード」と呼ばれるプロセスで、WALログを使い、コミットされたトランザクションを適切に復元します。
PITR (Point-In-Time Recovery)
障害が発生した際、過去のバックアップに加えて、WALファイルに記録された更新ログを使って、特定の時点にデータベースを復元する方法です。
バックアップ
障害時にデータを復元するため、PITRとバックアップを併用します。ここではバックアップ手法を説明します。
ホットバックアップ vs コールドバックアップ
- ホットバックアップ
データベースが稼働中でもバックアップ可能。ダウンタイムを避けられるが、一貫性を確保する仕組みが必要。 - コールドバックアップ
データベース停止中にバックアップするため、一貫性は確保できるが、ダウンタイムが発生。
論理バックアップ vs 物理バックアップ
-
論理バックアップ
テーブルや行、列の単位でデータをバックアップ。異なるDBMS間での移行が容易。 -
物理バックアップ
データファイルをそのままバックアップ。高速だが、DBMS間の移行には向かない。
フルバックアップ vs 部分バックアップ(増分・差分バックアップ)
- フルバックアップ
全体をバックアップ。時間と容量を要するが、完全なリカバリが可能。 - 増分バックアップ
前回のバックアップ以降に変更されたデータのみをバックアップ。リカバリ時は増分バックアップを全て適用する必要がある。 - 差分バックアップ
最後のフルバックアップ以降に変更された全データをバックアップ。復元時にはフルバックアップと最後の差分バックアップを使う。
10章 パフォーマンスを考えよう
システムのパフォーマンス
SQLを1本書くごとに性能問題が発生するほど、データベースにおいてパフォーマンスを意識することは重要です。システム性能の指標にはレスポンスタイムとスループットがあります。
- レスポンスタイム
処理開始から終了までの時間。 - スループット
1秒あたりに処理できるトランザクション数。
スループットの向上は、CPUやメモリなどのハードウェア性能を高める必要があります。しかし、あるリソースが限界に達するとボトルネックが発生し、パフォーマンスが急激に低下します。
ボトルネック
高速道路で事故が発生し、片側2車線から1車線になると渋滞が発生するように、システムの一部リソースが限界に達すると処理が滞ります。
データベースとボトルネック
データベースにおけるボトルネックの原因には、次の要素が挙げられます:
- 扱うデータ量が大きすぎる
- リソースが不足する