Upgrade to Pro — share decks privately, control downloads, hide ads and more …

データベース研修

 データベース研修

パーソルキャリア株式会社 テクノロジー本部 エンジニアリング統括部 サービス開発部
※本資料は2023年3月時点の情報であり、当該部門における2023年新卒の研修教材です。

techtekt

August 25, 2023
Tweet

More Decks by techtekt

Other Decks in Programming

Transcript

  1. データベースの種類 種類 説明 階層型データベース データを階層構造(木構造)で表す リレーショナルデータ ベース(Relational Database:RDB) Excelのような2次元表の形式でデータを管理 最も広く利用されている

    オブジェクト指向データ ベース データとそれを操作する処理をまとめたオブジェクトを管理する データベース XMLデータベース XML形式のデータを扱う キー・バリュー型データ ストア 検索に使うキー(Key)と値(Value)の組み合わせで管理 プログラムでいう「連想配列」や「ハッシュ」的なイメージ 他にも色々...
  2. テーブルの構造 id 名前 年齢 性別 1 田中太郎 24 男 2

    花沢花子 26 女 3 鈴木次郎 31 男 行(レコード) フィールド 列(カラム) テーブルは列(カラム)と行(レコード)でできており、レコードの中の入力項目はフィールド と呼ばれる
  3. MySQLのサーバ起動とログイン ・サーバ起動 ・ログイン $ mysql.server start $ mysql -u root

    ・mysqlのプロンプト(mysql>)が表示される サーバーを終了させるときは、 $ mysql.server stop 実践
  4. ファイルを読み込んでsqlを実行 > SOURCE info.sql; SELECT 'hello world!' AS info; info.sql

    cf. https://dev.mysql.com/doc/refman/8.0/en/mysql-batch-commands.html
  5. SQL

  6. TCL(Transaction Control Language) データベース内におけるトランザクションを扱うコマンド START TRANSACTION または BEGIN 新しいトランザクションを開始 COMMIT

    現在のトランザクションをコミットして、その変更を永続的なものにしま す ROLLBACK 現在のトランザクションをロールバックして、その変更を取り消します
  7. データ型(文字) データ型 説明 CHAR(M) 格納時に必ず、Mで指定された長さになるように右側がスペースで埋められる固定長文字列。Mの範囲は0から255 。 VARCHAR(M) 可変長文字列。M はカラムの最大長文字数。Mの範囲は0から65535。 TEXT

    最大長が 65535文字のテキスト文字列。値にマルチバイト文字が含まれる場合、有効な最大長は少なくなります。 BLOB 最大長が 65535文字のバイナリ文字列。 https://dev.mysql.com/doc/refman/5.6/ja/string-type-overview.html
  8. データ型(数値) データ型 説明 TINYINT [UNSIGNED] 非常に小さい整数。 符号付きの範囲は-128から127。符号なしの範囲は0から255。 INTEGER [UNSIGNED] 普通サイズの整数。

    符号付きの範囲は-2147483648から2147483647。 符号なしの範囲は0から4294967295。 BIGINT [UNSIGNED] 大きい整数。 符号付きの範囲は-9223372036854775808から9223372036854775807。 符号なしの範囲は0から18446744073709551615。 BOOLEAN 0 or 1が格納されます。0は false, 1はtrueと見なされます。 FLOAT 浮動小数点数。 DOUBLE 倍精度の浮動小数点数。 https://dev.mysql.com/doc/refman/5.6/ja/numeric-type-overview.html
  9. データ型(日付/時間) データ型 説明 DATE 日付です。サポートしている範囲は '1000-01-01' から '9999-12-31' です。 DATETIME

    日付と時間の組み合わせです。 サポートしている範囲は '1000-01-01 00:00:00.000000' から '9999-12-31 23:59:59.999999' です。 TIMESTAMP タイムスタンプ。TIMESTAMP 値はエポック ('1970-01-01 00:00:00' UTC) から (‘2038-01-19 03:14:07’) の秒数として格 納されます。(2038年問題) TIME 時間。範囲は、'-838:59:59.000000' から '838:59:59.000000' です。 https://dev.mysql.com/doc/refman/5.6/ja/date-and-time-type-overview.html
  10. > ALTER TABLE users ADD COLUMN age INTEGER AFTER name;

    テーブル構造を変更する ・usersテーブルのnameの次にageというカラムを追加する ・追加(ADD)、変更(CHANGE)、削除(DROP)などがある https://www.dbonline.jp/mysql/table/index18.html 実践
  11. 下準備 > CREATE DATABASE mydb; > USE mydb; > CREATE

    TABLE users ( id INT AUTO_INCREMENT, name TEXT, age INTEGER, PRIMARY KEY (id) ); 実践
  12. データを追加する ・usersテーブルにname = ‘Suzuki’, age=20のデータとname = ‘Tanaka’, age=22の データを追加する ・テーブルのカラムを全て設定する場合、(name,

    age)の部分は省略できる ・カラムを指定しなかった場合は指定しなかったフィールドにはNULLが入る https://www.dbonline.jp/mysql/insert/index1.html > INSERT INTO users (name, age) VALUES ('Suzuki', 20), ('Tanaka', 22); 実践
  13. 比較演算子 演算子 使用例 意味 = a = b a と

    b は等しい != a != b a と b は等しくない < a < b a は b よりも小さい <= a <= b a は b よりも小さいか等しい > a > b a は b よりも大きい >= a >= b a は b よりも大きいか等しい IS NULL a IS NULL a はNULL IS NOT NULL a IS NOT NULL a はNULLではない BETWEEN AND a BETWEEN min AND max a は minより大きいか等しくmaxより小さいか等しい LIKE a LIKE pattern SQL の単純な正規表現比較を使用したパターンマッチング https://dev.mysql.com/doc/refman/8.0/en/sql-function-reference.html
  14. 論理演算子 演算子 使用例 意味 AND a AND b a と

    b が共にTRUEの時にTRUE OR a OR b a か b の少なくとも1つがTRUEの場合にTRUE XOR a XOR b a と b が共にTRUEまたはFALSEの時にFALSE a または b がNULLのときはNULL NOT NOT a a がTRUEならFALSE、a がFALSEならTRUE https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html > SELECT * FROM users WHERE (age > 20) AND (name = ‘Suzuki’);
  15. 集計関数 ・SQLでテーブルの値を集計するために使う機能 ・対象データがNULLの場合は無視される 名前
 説明
 AVG()
 引数の平均値を返します
 COUNT()
 返された行数のカウントを返します
 GROUP_CONCAT()


    連結された文字列を返します
 MAX()
 最大値を返します
 MIN()
 最小値を返します
 SUM()
 集計を返します
 https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html
  16. 内部結合(INNER JOIN) 指定したそれぞれのテーブルのカラムの値が一致するデータだけを取得 id name age 1 佐藤 25 2

    鈴木 18 3 田中 20 4 渡辺 18 5 斎藤 35 id user_id article 1 3 テストです 2 1 コメント 3 1 あああ 4 6 何か id name age id user_id article 1 佐藤 25 2 1 コメント 1 佐藤 25 3 1 あああ 3 田中 20 1 3 テストです users articles
  17. 外部結合(LEFT JOIN) 左側のテーブルにしかないデータも取得する id user_id article 1 3 テストです 2

    1 コメント 3 1 あああ 4 6 何か id name age id user_id article 1 佐藤 25 2 1 コメント 1 佐藤 25 3 1 あああ 2 鈴木 18 NULL NULL NULL 3 田中 20 1 3 テストです 4 渡辺 18 NULL NULL NULL 5 斎藤 35 NULL NULL NULL id name age 1 佐藤 25 2 鈴木 18 3 田中 20 4 渡辺 18 5 斎藤 35
  18. 外部結合(RIGHT JOIN) 右側のテーブルにしかないデータも取得する id user_id article 1 3 テストです 2

    1 コメント 3 1 あああ 4 6 何か id name age 1 佐藤 25 2 鈴木 18 3 田中 20 4 渡辺 18 5 斎藤 35 id name age id user_id article 3 田中 20 1 3 テストです 1 佐藤 25 2 1 コメント 1 佐藤 25 3 1 あああ NULL NULL NULL 4 6 何か
  19. 成功時 start 購入履歴テーブルに データを追加 在庫管理テーブルの データを変更 end 購入履歴テーブル 在庫管理テーブル 顧客

    商品 個数 Aさん 鍋 1 商品 在庫数 鍋 9 鍋一個買う Aさん鍋一つ購入 データ追加 鍋の在庫を1減ら す 鍋の合計個数に矛 盾はない 鍋の合計個数に 矛盾はない
  20. 失敗時 start 購入履歴テーブルに データを追加 在庫管理テーブルの データを変更 end 購入履歴テーブル 在庫管理テーブル 顧客

    商品 個数 Aさん 鍋 1 商品 在庫数 鍋 10 鍋一個買う Aさん鍋一つ購入 データ追加 鍋の在庫を1減ら す 予期しない処 理中断 鍋の合計個数に矛 盾はない 鍋の合計個数に 矛盾が発生
  21. トランザクション start 購入履歴テーブルに データを追加 在庫管理テーブルの データを変更 end 購入履歴テーブル 在庫管理テーブル 商品

    在庫数 鍋 9 鍋一個買う Aさん鍋一つ購入 データ追加 鍋の在庫を1減ら す 鍋の合計個数に矛 盾はない commitされると変 更が反映される commit rollback エラーなし エラーあり 一つの処理として 扱う 変更を反映する 顧客 商品 個数 Aさん 鍋 1
  22. トランザクション start 購入履歴テーブルに データを追加 在庫管理テーブルの データを変更 end 購入履歴テーブル 在庫管理テーブル 顧客

    商品 個数 商品 在庫数 鍋 10 鍋一個買う Aさん鍋一つ購入 データ追加 鍋の在庫を1減ら す 鍋の合計個数に矛 盾はない 処理全体がなかっ たことになる commit rollback エラーなし エラーあり 一つの処理として 扱う 反映を中止する
  23. 例えば start 残高を参照する 残高に20000プラスし て保存する end 残高 70000 20000円仕送 り送る

    start 残高を参照する 残高から5000マイナ スして保存する end 振込処理 引き落とし処理 5000円下ろす 残高テーブル 例) 銀行の振り込みと引き落としの同時処理
  24. 排他制御しない場合 start 残高を参照する 残高(70000)に20000 プラスして保存する end 残高 70000 20000円仕送 り送る

    start 残高を参照する 残高(70000)から 5000マイナスして保 存する end 振込処理 引き落とし処理 5000円下ろす 残高テーブル 残高 90000 残高 65000 残高結果が間違っ てしまう 70000 70000
  25. 排他制御した場合 start 更新のために残高を 参照する 残高(70000)に20000 プラスして保存する end 残高 70000 20000円仕送

    り送る start 更新のために残高を 参照する 残高(90000)から 5000マイナスして保 存する end 振り込み処理 引き落とし処理 5000円下ろす 残高テーブル 残高 90000 残高 85000 正しい残高になる 70000 90000 commit ロック状態 ロック解除 ロック開始 commit commitでロック解 除される
  26. ACID特性(トランザクションの特性) • 原子性(Atomicity) ◦ 全て実行されるか、または全て実行されないか。 • 一貫性(Consistency) ◦ 実行前後で矛盾が無い状態が保たれる。 •

    独立性(Isolation) ◦ 他のトランザクションに影響を与えない。 • 永続性(Durability) ◦ トランザクションの結果は失われない。
  27. トランザクション分離レベル 分離レベル ダーティーリード ファジーリード ファントムリード READ UNCOMMITTED 発生 発生 発生

    READ COMMITTED 発生しない 発生 発生 REPEATABLE READ 発生しない 発生しない 発生※ SERIALIZABLE 発生しない 発生しない 発生しない ※InnoDBではREPEATABLE READでもファントムリードが発生しない トランザクションが複数同時に発生した際に、どの程度一貫性を担保するかのレベル。4 段階存在する。
  28. トランザクション分離レベル • ダーティーリード(Dirty Read) ◦ 他のトランザクションのコミットされていない内容が見える • ファジーリード(Fuzzy Read) ◦

    他のトランザクションのコミットした追加・削除・更新が見える • ファントムリード(Phantom Read) ◦ 他のトランザクションのコミットした追加・削除が見える
  29. トランザクション分離レベルの確認 > SELECT @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ |

    REPEATABLE-READ | +-------------------------+ 1 row in set (0.02 sec) MySQLのデフォルトは「REPEATABLE READ」 ※研修用に用意したテーブルを使用しています
  30. REPEATABLE READ A> use training; // Aでトランザクション開始 A> BEGIN; B>

    use training; // Bでトランザクション開始 B> BEGIN; A> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 国語 | +----+--------+ 1 row in set (0.02 sec) A> UPDATE subjects SET name = '更新' WHERE id = 1; A> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 更新 | +----+--------+ 1 row in set (0.02 sec) // Bではコミット前の変更が見えない( ダーティーリードが起きない ) B> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 国語 | +----+--------+ 1 row in set (0.01 sec) A> commit; // Bではコミット後の変更が見えない( ファジーリードが起きない ) B> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 国語 | +----+--------+ 1 row in set (0.01 sec) A> INSERT INTO subjects (name) VALUES ('新しい科目 '); A> commit; // Bではコミット後の追加処理が見えない( ファントムリードが起きない ) B> SELECT * FROM subjects; ...
  31. READ COMMITTED A,B> set session transaction isolation level read committed;

    A,B> SELECT @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | READ-COMMITTED | +-------------------------+ // トランザクションの開始 A,B> BEGIN; A> UPDATE subjects SET name = '新しい更新 ' WHERE id = 1; // Bではコミット前の変更が見えない( ダーティーリードが起きない ) B> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 更新 | +----+--------+ A> commit; // トランザクション中の BでAがコミットした内容が見えてしまう( ファジーリードが発生 ) B> SELECT * FROM subjects WHERE id = 1; +----+-----------------+ | id | name | +----+-----------------+ | 1 | 新しい更新 | +----+-----------------+ A> INSERT INTO subjects (name) VALUES ('新しい科目 '); A> commit; // トランザクション中の BでAがコミットした追加が見えてしまう( ファントムリードが発 生) B> SELECT * FROM subjects; +----+-----------------+ | id | name | +----+-----------------+ | 1 | 新しい更新 | ... | 7 | 新しい科目 | +----+-----------------+
  32. READ UNCOMMITTED A,B> use training; A,B> set session transaction isolation

    level read uncommitted; A,B> SELECT @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | READ-UNCOMMITTED | +-------------------------+ A,B> BEGIN; A> UPDATE subjects SET name = '更新' WHERE id = 1; // トランザクション中の BでAがコミットしてない内容が見える //(ダーティーリードが発生 ) B> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 更新 | +----+--------+ A> commit; // トランザクション中の BでAがコミットした内容が見えてしまう( ファジーリードが発生 ) B> SELECT * FROM subjects WHERE id = 1; +----+--------+ | id | name | +----+--------+ | 1 | 更新 | +----+--------+ A> INSERT INTO subjects (name) VALUES ('新しい科目 '); A> commit; // トランザクション中の BでAがコミットした追加が見えてしまう( ファントムリードが発 生) B> SELECT * FROM subjects; +----+-----------------+ | id | name | +----+-----------------+ | 1 | 新しい更新 | ... | 8 | 新しい科目 | +----+-----------------+
  33. 非正規 例)料理の注文データ 注文番号 注文日 名前 電話番号 料理 値段 個数 料理

    値段 個数 合計 C0001 2021/04/01 佐藤太郎 090-0022-1 122 カレー 500 2 ラーメン 600 1 1600 C0002 2021/04/03 田中花子 090-0034-9 921 マグロ丼 800 1 ピザ 1000 1 1800 C0003 2021/04/04 斎藤次郎 090-0077-5 567 ピザ 1000 3 3000 C0004 2021/04/05 佐藤太郎 090-0022-1 122 マグロ丼 800 1 800 注文表
  34. 問題点 ・注文の種類が多くなるたびに列を増やす必要がある ・同じ情報が複数箇所にあり、更新が必要になった場合に複数箇所更新する必要があ る 注文番号 注文日 名前 電話番号 料理 値段

    個数 料理 値段 個数 合計 C0001 2021/04/01 佐藤太郎 090-0022-1 122 カレー 500 2 ラーメン 600 1 1600 C0002 2021/04/03 田中花子 090-0034-9 921 マグロ丼 800 1 ピザ 1000 1 1800 C0003 2021/04/04 斎藤次郎 090-0077-5 567 ピザ 1000 3 3000 C0004 2021/04/05 佐藤太郎 090-0022-1 122 マグロ丼 800 1 800 料理1つ目 料理2つ目
  35. 第一正規化 ・繰り返し項目を別レコードにする ・計算して算出できるものは無くす 注文番号 注文日 名前 電話番号 料理 値段 個数

    料理 値段 個数 合計 C0001 2021/04/01 佐藤太郎 090-0022-1 122 カレー 500 2 ラーメン 600 1 1600 C0002 2021/04/03 田中花子 090-0034-9 921 マグロ丼 800 1 ピザ 1000 1 1800 C0003 2021/04/04 斎藤次郎 090-0077-5 567 ピザ 1000 3 3000 C0004 2021/04/05 佐藤太郎 090-0022-1 122 マグロ丼 800 1 800 注文表
  36. 第一正規化後 注文番号 注文日 名前 電話番号 料理 値段 個数 C0001 2021/04/01

    佐藤太郎 090-0022-1122 カレー 500 2 C0001 2021/04/01 佐藤太郎 090-0022-1122 ラーメン 600 1 C0002 2021/04/03 田中花子 090-0034-9921 マグロ丼 800 1 C0002 2021/04/03 田中花子 090-0034-9921 ピザ 1000 1 C0003 2021/04/04 斎藤次郎 090-0077-5567 ピザ 1000 3 C0004 2021/04/05 佐藤太郎 090-0022-1122 マグロ丼 800 1 注文表
  37. 第二正規化 関数従属:主キーが決まると、列の値が一意に定まる関係 部分関数従属:複合キーの一部の項目だけで、列の値が一意に定まる関係 注文番号 注文日 名前 電話番号 料理 値段 個数

    C0001 2021/04/01 佐藤太郎 090-0022-1122 カレー 500 2 C0001 2021/04/01 佐藤太郎 090-0022-1122 ラーメン 600 1 C0002 2021/04/03 田中花子 090-0034-9921 マグロ丼 800 1 C0002 2021/04/03 田中花子 090-0034-9921 ピザ 1000 1 C0003 2021/04/04 斎藤次郎 090-0077-5567 ピザ 1000 3 C0004 2021/04/05 佐藤太郎 090-0022-1122 マグロ丼 800 1 複合キー 複合キー 注文番号の部分関数従属 料理の部分関数従属 部分関数従属を別テーブルに分ける
  38. 第二正規化後 注文番号 料理 個数 C0001 カレー 2 C0001 ラーメン 1

    C0002 マグロ丼 1 C0002 ピザ 1 C0003 ピザ 3 C0004 マグロ丼 1 注文表 注文番号 注文日 名前 電話番号 C0001 2021/04/01 佐藤太郎 090-0022-1122 C0002 2021/04/03 田中花子 090-0034-9921 C0003 2021/04/04 斎藤次郎 090-0077-5567 C0004 2021/04/05 佐藤太郎 090-0022-1122 注文顧客表 料理 値段 カレー 500 ラーメン 600 マグロ丼 800 ピザ 1000 料理表
  39. 第三正規化 注文番号 注文日 名前 電話番号 C0001 2021/04/01 佐藤太郎 090-0022-1122 C0002

    2021/04/03 田中花子 090-0034-9921 C0003 2021/04/04 斎藤次郎 090-0077-5567 C0004 2021/04/05 佐藤太郎 090-0022-1122 注文顧客表 推移的関数従属:第二正規化テーブルで、主キー以外の項目で列の値が一意に定まる 関係 名前の推移的関数従属 推移的関数従属を別テーブルに分ける
  40. 第三正規化後 注文番号 料理 個数 C0001 カレー 2 C0001 ラーメン 1

    C0002 マグロ丼 1 C0002 ピザ 1 C0003 ピザ 3 C0004 マグロ丼 1 注文表 注文顧客表 料理 値段 カレー 500 ラーメン 600 マグロ丼 800 ピザ 1000 料理表 注文番号 注文日 名前 C0001 2021/04/01 佐藤太郎 C0002 2021/04/03 田中花子 C0003 2021/04/04 斎藤次郎 C0004 2021/04/05 佐藤太郎 名前 電話番号 佐藤太郎 090-0022-1122 田中花子 090-0034-9921 斎藤次郎 090-0077-5567 顧客表