データベース設計徹底指南

93,105 views

Published on

DBエンジニアのための技術勉強会(第3回)で使用した資料です。主にリレーショナルモデルと正規化について解説しています。リレーショナルモデルの限界について正しく認識してこそ、リレーショナルモデルを理解したと言えると思います。

Published in: Technology
1 Comment
351 Likes
Statistics
Notes
  • The Atlas has made it easier for Gigging & Recording Artists, Managers, Labels, Agents & Publicists to tour, promote and sell music more successfully – with and without label support. Atlas subscribers have the music industry at their fingertips plus a full-time research staff working nite and day qualifying new opportunities & updating every single contact in our databases.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
93,105
On SlideShare
0
From Embeds
0
Number of Embeds
37,397
Actions
Shares
0
Downloads
715
Comments
1
Likes
351
Embeds 0
No embeds

No notes for slide

データベース設計徹底指南

  1. 1. データベース設計 徹底指南!! @ 第3回 DB エンジニアのための技術勉強会 奥野 幹也 Twitter: @nippondanji mikiya (dot) okuno (at) gmail (dot) com
  2. 2. 免責事項 ● 本プレゼンテーションにおいて示されている見 解は、私自身の見解であって、オラクル・コー ポレーションの見解を必ずしも反映したもので はありません。ご了承ください。
  3. 3. 自己紹介 ● MySQL サポートエンジニア – 日々のしごと ● ● ● ● ライフワーク – 自由なソフトウェアの普及 ● ● トラブルシューティング全般 Q&A 回答 パフォーマンスチューニング など オープンソースではない 今日は個人として 参加しています。 ブログ – – 漢のコンピュータ道 http://nippondanji.blogspot.com/
  4. 4. みなさん、 正しい DB 設計を していますか?
  5. 5. 正しいデータ型を使う 〜 カラムの場合 〜 ● 整数 – ● 実数 – ● NUMBER, DECIMAL 文字列 – ● FLOAT, DOUBLE 固定小数点 – ● INT, BIGINT VARCHAR, CHAR バイナリ – BLOB
  6. 6. 正しいデータ型を使う 〜 配列の操作の場合 〜 a = Array.new # 要素の挿入 a.push(' 要素 ') # N 番目の要素 a[N] a = '' # 要素の挿入 a = a << (a.size == 0 ? ' 要 素 ' : ', 要素 ' # N 番目の要素 n = 0 s = '' a.each_char do |c| if c == ',' return s if n == N n += 1 s = '' else s << c end end return s if n == N
  7. 7. 正しいデータ型を使う 〜 配列の操作の場合 〜 a = Array.new # 要素の挿入 a.push(' 要素 ') # N 番目の要素 a[N] a = '' # 要素の挿入 a = a << (a.size == 0 ? ' 要 素 ' : ', 要素 ' # N 番目の要素 n = 0 s = '' a.each_char do |c| if c == ',' return s if n == N n += 1 s = '' else s << c end end return s if n == N
  8. 8. 正しいデータ型を使う 〜 テーブルの場合 〜 ● 演算のためのデータ型 – テーブル ● ● カラムのデータ型だけではない!! 演算 – クエリ( SELECT, INSERT, UPDATE, DELETE... ) テーブルを正しく定義しないと まともなクエリは書けない!!
  9. 9. 正しくない DB 設計のまま クエリを書くと・・・ ● ● ● ● 遅い SQL 文が無駄に長い JOIN やサブクエリ、 UNION などが異常に多い 検索条件が複雑怪奇 – – ● ● OR が多数出現するなど LIKE 句による中間一致 難解である ロジックが間違っている
  10. 10. DB 設計の欠陥は 技術的負債になる ● データベースはリファクタリングが難しい – 変更による影響が大きい ● ● ● – – DDL に時間がかかる アプリケーションの修正箇所多数 工数がかかる 方法が分からない 負債が溜まりすぎて首が回らない 放置された負債が さらに足かせに!!
  11. 11. 技術的負債がたまる原因 ● データモデルに対する無理解 – リレーショナルモデルを知らない ● ● – 結果、セオリーを無視したデータベース設計に ● ● テーブルをただのデータの入れ物として使う文化 正規化をしない → クエリはスパゲティに リレーショナルモデルを知らなくても RDBMS は便利 – – インデックスを用いた高速なアクセス トランザクションによる処理の簡素化
  12. 12. 技術的負債が蓄積すると ● 技術的負債は開発を難しくする – – – 検索の要件が難解 テスト項目が増える 負債がたまるほどリファクタリングが困難に 負債は雪だるま式に 増える!!!
  13. 13. RDBMS を使いこなすには ● ● 負債をためない! データベース設計をしっかり! データモデルは 超重要!!
  14. 14. RDBMS における データモデル リレーショナル モデル!!
  15. 15. リレーショナルモデル とは。
  16. 16. クイズ 1 リレーショナルモデルにおけるリレーションとは、 テーブル間のリレーションシップのことである? ○ ×
  17. 17. リレーションとは ● ある物事に対する事実の集合 テーブル ≒ リレーション
  18. 18. 集合の性質 ● ● 重複がない NULL がない – ● 実際に存在する値のみ 要素間に順序がない – 例え数値でも。 米国 ベトナム 日本 オーストラリア スウェーデン カメルーン
  19. 19. リレーションの構成部品 ● ● リレーション=見出し(ヘッダ)+本体(ボディ) 見出し(ヘッダ、 headding ) – – ● 属性(アトリビュート) – ● – 属性で定義された型を持つ値 ≒ 列(カラム) 組(タプル) – – ● 名前と型(タイプ) 属性値 – ● 属性の集合 集合なので順序はない 見出しに対応した属性値の集合 ≒ 行(ロー) 本体(ボディ) – 組(タプル)の集合
  20. 20. リレーションのイメージ 見出し 国名 / 文字列 国番号 / 整数 地域 / 文字列 本体 国番号: 86, 国名:中華人民共和国 , 地域:アジア 国番号: 61, 国名:オーストラリア , 地域:オセアニア 国名:日本 , 国番号: 81, 地域:アジア 国名:米国 , 国番号: 1, 地域:北米 地域:アフリカ , 国名:カメルーン , 国番号: 237 地域:欧州 , 国名:スウェーデン , 国番号: 46
  21. 21. SQL との対応 リレーショナルモデル SQL 関係(リレーション) テーブル 属性値(アトリビュート) カラム 組(タプル) 行 対応する概念だが性質は異なる。
  22. 22. クイズ 2 リレーションは2次元的な構造を持つ? ○ ×
  23. 23. リレーションの実体 ● ● ● n 個のアトリビュートを持つリレーションは、 n 次元空間に プロットされた点(のようなもの)の集合 タプル = 点 2次元に見えるのは縦横の軸がある表として表現するから – – 紙に描かれた絵は2次元になる 絵が表すものが2次元だとは限らない ● 風景や人物などはすべて3次元
  24. 24. データ型=ドメイン ● 属性が取りうる値の有限集合 – – – ● 無限でないのはコンピュータで扱う値だから 32 ビット整数なら 232 通り データサイズが増えれば表現できる要素数は増えるけ ど、絶対に無限にはならない ドメインの要素の性質 – 要素はコンピュータで表現できるものなら何でも可 ● – ベクトル、行列、配列、リレーションそのものなど ただしポインタと NULL は NG
  25. 25. リレーションの演算
  26. 26. リレーションの演算 ● 演算の入力も結果もリレーション – – ● n 個のリレーションの演算の結果、 1 個のリレーションが 返る 整数と整数の足し算の結果が整数なのと同じ 集合操作に基づく演算 – 和、差、直積、射影、制限、結合 etc
  27. 27. リレーションのイメージ(再掲) 見出し 国名 / 文字列 国番号 / 整数 地域 / 文字列 本体 国番号: 86, 国名:中華人民共和国 , 地域:アジア 国番号: 61, 国名:オーストラリア , 地域:オセアニア 国名:日本 , 国番号: 81, 地域:アジア 国名:米国 , 国番号: 1, 地域:北米 地域:アフリカ , 国名:カメルーン , 国番号: 237 地域:欧州 , 国名:スウェーデン , 国番号: 46
  28. 28. 制限( RESTRICT )
  29. 29. 制限( RESTRICT )
  30. 30. 射影( PROJECT )
  31. 31. 射影( PROJECT )
  32. 32. 属性名変更( RENAME ) 国名 / 文字列 国番号 / 整数 大陸 / 文字列
  33. 33. 属性名変更( RENAME ) 国名 / 文字列 国番号 / 整数 地域 / 文字列
  34. 34. 拡張( EXTEND ) 国名 / 文字列 人口 / 整数 面積 / Decimal (km2)
  35. 35. 拡張( EXTEND ) 国名 / 文字列 人口 / 整数 人口密度 / Decimal ( 人 /km2) 面積 / Decimal (km2)
  36. 36. 和( UNION )
  37. 37. 和( UNION )
  38. 38. 積( INTERSECT )
  39. 39. 積( INTERSECT )
  40. 40. 差( DIFFERENCE )
  41. 41. 差( DIFFERENCE )
  42. 42. 直積( PRODUCT ) a b x y c d z
  43. 43. 直積( PRODUCT ) a b x a b y a b z c d x c d y c d z
  44. 44. 結合( JOIN ) a x w 1 b y x 2 c z y 3
  45. 45. 結合( JOIN ) b x 2 c y 3
  46. 46. 豆知識 ● 直積( Product )と積( Intersect )はいずれも結合 ( Join) の特殊なケース – – ● 直積・・・共通する属性がひとつも存在しないケース 積・・・すべての属性がまったく同じケース リレーショナルモデルに存在する Join は Inner Join だけ
  47. 47. Outer Join の意味 ● Outer Join (LEFT JOIN または RIGHT JOIN )はプリミ ティブな演算ではない。 – ● 他の演算で置き換え可能 Outer Join は UNION 相当 – (Inner Join) ∪ ( 駆動表にマッチしないものの集合 )
  48. 48. リレーションの演算は 分かったけど SQL とどう関係あるの?
  49. 49. SELECT の実態 SELECT FROM WHERE select_list table_reference where_condition
  50. 50. SELECT の実態 = 3 つの集合演算 SELECT 射影 FROM 直積 WHERE 制限
  51. 51. クイズ 3 次の SELECT は正しく実行されるか? SELECT weight / POWER(height, 2) AS bmi FROM body_shapes WHERE bmi > 25 ○ ×
  52. 52. SELECT の評価順序 SELECT 3 射影 FROM 1 直積 WHERE 2 制限
  53. 53. その他の操作 ● 和( UNION ) – ● SELECT … UNION DISTINCT SELECT … 差( DIFFERENCE ) – – SELECT … MINUS SELECT … SELECT … WHERE NOT EXISTS (SELECT …) …
  54. 54. リレーションの正規化
  55. 55. クイズ 4 テーブルに主キーがあれば 正規化は完了している。 ○ ×
  56. 56. なぜ正規化が必要なのか ● データベースの論理的整合性を保つ – – ● 「論理的」な正しさを保証する → 論理演算によって「正しい」結果が得られる = 矛盾を防ぐ – 集合(リレーション)に含まれる命題に矛盾がない
  57. 57. 論理的に矛盾しているデータは、 どちらが正しいか いくら考えても分からない!!
  58. 58. 論理的に矛盾しているデータは、 どちらが正しいか いくら考えても分からない!! 正しい答えが得られない データベースは 無価値!!
  59. 59. 論理的に矛盾しているデータは、 どちらが正しいか いくら考えても分からない!! 正しい答えが得られない データベースは 無価値!! 矛盾をなくすための定石 それが 正規化!!
  60. 60. データの”論理的”整合性 論理的な不整合とは? 名前 格闘スタイル 年齢 範馬刃牙 総合格闘技 19 範馬勇次郎 総合格闘技 38 愚地独歩 空手 57 ビスケットオリバ 怪力 40 ビスケットオリバ 柔道 42 花山薫 素手喧嘩 19 烈海王 中国拳法 30 烈海王 ボクシング 30 不整合 = 矛盾 どっちが 正しい?
  61. 61. 正規化理論 ● リレーションから重複を排除するためのデータベース設計 理論 – ● 重複は矛盾の原因になる 第一正規形( 1NF )〜第六正規形( 6NF ) – – – より高次の正規形のほうが重複が少ない(望ましい)状 態になる。 3NF と 4NF の間に BCNF というものがある。超重要。 ただし最終目標は 5NF
  62. 62. 用語 1 ● 命題 – – ● 述語 – – ● 命題の中の固有名詞をパラメータ化したもの 例) x は犬である 命題関数 – 述語から意味を取り除いて関数化したもの。値を代入した場 合の評価結果は述語と同じ。 – ● ある物事について記述した文章で、その意味が正しいかどうか、つ まり真なのか偽なのかを問えるもののこと 例)ポチは犬である 例) F(x) 閉世界仮説 – リレーションは事実の集合 ● – – 事実=真となる命題 リレーションに含まれる組の属性値を代入 → 真 それ以外の属性値を代入 → すべて偽
  63. 63. 1NF ● 要件:テーブルがリレーションであること。 1.行が上から下に順序付けされていない。 2.列が左から右に順序付けされていない。 3.重複する行は存在しない。 4.それぞれの行と列の交差点(つまり列の値)は、ドメイン (データ型)に属する要素の値をちょうどひとつだけ含ん でいる。 5.全ての列の値は定義されたものだけであり、かつそれぞ れの行において常に存在する。
  64. 64. 繰り返しグループ 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 花山薫 素手喧嘩 海王烈 中国拳法 同じ性質のもの が繰り返し出現 カラム追加 名前 格闘スタイル 1 格闘スタイル 2 範馬刃牙 総合格闘技 NULL 範馬勇次郎 総合格闘技 NULL 愚地独歩 空手 NULL ビスケットオリバ 怪力 柔道 花山薫 素手喧嘩 NULL 海王烈 中国拳法 ボクシング
  65. 65. アトミックな属性 それ以上分解できないような属性 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 柔道 花山薫 素手喧嘩 海王烈 中国拳法 ボクシング 2つ入ってるので 分解可能 ※ 属性の中に繰り返しグループがある。
  66. 66. データ型=ドメイン ● 属性の値は、ドメインという有限集合に含まれる要素の「ひ とつ」 – – 集合の要素は分解できない=アトミック 属性がアトミックかどうかを判断するにはドメインを意識 する。
  67. 67. NG !!こんな設計にはご用心 ● ● 主キーの”一部”に意味を持たせる 例:基礎年金番号 – 1234-567890 事務所の ID ● 個人の ID 問題点 – – アトミックでない 値の一部に依存した処理 ● SELECT … WHERE ID LIKE '1234-%' AND …
  68. 68. 1NF の例 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 ビスケットオリバ 柔道 花山薫 素手喧嘩 海王烈 中国拳法 海王烈 ボクシング 繰り返しグループなし ● 重複なし ●NULL なし ●
  69. 69. 用語 2 ● 候補キーとスーパーキー – – あるリレーションにおいて、タプルの値を一意に決めるこ とができる属性の集合で、規約のもの(それ以上要素を 減らすことができないもの)を候補キーという 候補キーのスーパーセット、つまり余分な属性を含んだも のをスーパーキーという ● ● すべての属性を含む集合は常にスーパーキー 関数従属性( Functional Dependency - FD ) – – あるリレーション R の見出しの 2 つの部分集合を A 、 B とする。 R の要素の全てのタプルにおいて、 A の値が同 じならば B の値も同じである場合かつその場合だけに限 り、 B は A に関数従属すると言い、 A → B と記述する。 スーパーキー → 任意の属性の集合 ● 自明な FD
  70. 70. 2NF 候補キーの真部分集合(それ自身は含まないもの) から非キー属性への FD を取り除いた状態。 候補キー 非キー属性 タプル ・・・ FD
  71. 71. 2NF でないリレーションの例 候補キー 図に描くときは アンダーラインをひく 名前 格闘スタイル 年齢 範馬刃牙 総合格闘技 19 範馬勇次郎 総合格闘技 38 愚地独歩 空手 57 ビスケットオリバ 怪力 40 ビスケットオリバ 柔道 40 花山薫 素手喧嘩 19 烈海王 中国拳法 30 烈海王 ボクシング 30 FD 名前が同じなら 年齢は常に同じ
  72. 72. FD を解消する ● 無損失分解する – 必要な操作は射影 ● – SELECT DISTINCT { 名前 , 格闘スタイル , 年齢 } ● ● ● FD: 名前 → 年齢 FD を含む属性の射影 +FD の非キー属性(この場合 は年齢)を取り除いた属性の射影 { 名前 , 年齢 },{ 名前 , 格闘スタイル }
  73. 73. 2NF の例 名前 格闘スタイル 名前 年齢 範馬刃牙 総合格闘技 範馬刃牙 19 範馬勇次郎 総合格闘技 範馬勇次郎 38 愚地独歩 空手 愚地独歩 57 ビスケットオリバ 怪力 ビスケットオリバ 40 ビスケットオリバ 柔道 花山薫 19 花山薫 素手喧嘩 烈海王 30 烈海王 中国拳法 烈海王 ボクシング
  74. 74. クイズ 5 あまりに正規化し過ぎると テーブルが増え過ぎるので問題である。 ○ ×
  75. 75. テーブルが増えても 問題ない !! テーブルを減らそうと 誤った DB 設計になるほうが問題
  76. 76. 3NF 非キー属性同士の FD を解消した状態。 候補キー 非キー属性 タプル ・・・ FD
  77. 77. 2NF であって 3NF でない例 名前 格闘スタイル 寝技 範馬刃牙 総合格闘技 Yes 範馬勇次郎 総合格闘技 Yes 愚地独歩 空手 No ビスケットオリバ 怪力 No 花山薫 素手喧嘩 Yes 烈海王 中国拳法 No
  78. 78. BCNF ボイス・コッド正規形の略。 すべての自明でない FD が取り除かれた状態。 残る FD は、非キー属性から 候補キーの真部分集合への FD 。 候補キー 非キー属性 タプル ・・・ FD
  79. 79. 3NF であって BCNF でない例 名前 格闘スタイル 流派 松尾象山 空手 北辰館 姫川勉 空手 北辰館 丹波文七 柔術 竹宮流 丹波文七 空手 丹波流 長田弘 プロレス FAW 長田弘 柔術 竹宮流 藤巻十三 柔術 竹宮流
  80. 80. FD のおさらい 候補キー 非キー属性 タプル ・・・ FD 候補キー 非キー属性 タプル ・・・ FD 候補キー 非キー属性 タプル ・・・ FD
  81. 81. 候補キー内部には FD がない ● もし仮に候補キーに FD があると・・・ – – – {A,B} が候補キー A→B B の値は A によって決まる ● 規約ではない!
  82. 82. 用語 3 ● 結合従属性( Join Dependencies - JD ) – – ● Join すると元に戻るような無損失分解 A,B,...,C をリレーション R の見出しの部分集合であると する。もし A,B,...,C に対応するリレーションを結合した結 果と R が同じ場合かつその場合に限り、 R は以下の JD を満たすという。 ☆{A,B,...,C} 自明な JD – 複数の非キー属性があるリレーションにおいて、それぞれ 候補キーを含んだ複数の異なるリレーションに無損失分 解できるような JD 。
  83. 83. 自明な JD 名前 年齢 国籍 範馬刃牙 19 Japan 範馬勇次郎 38 Japan 愚地独歩 57 Japan ビスケットオリバ 40 U.S.A. 花山薫 19 Japan 名前 年齢 名前 国籍 範馬刃牙 19 範馬刃牙 Japan 範馬勇次郎 38 範馬勇次郎 Japan 愚地独歩 57 愚地独歩 Japan ビスケットオリバ 40 ビスケットオリバ U.S.A. 花山薫 19 花山薫 Japan
  84. 84. 4NF/5NF のヒント ● 非キー属性がある BCNF に自明でない JD はない – 何故ならば、候補キーがバラバラになるような射影をとる と FD が消失してしまう。 ● ● – ● FD: 候補キー → 非キー属性 無損失ができない!! 非キー属性のある BCNF は自動的に 5NF になる。 4NF/5NF – – 非キー属性がないリレーションのみが対象 自明でない JD がある場合に無損失分解
  85. 85. 自明でない JD の本質 ● 自明でない JD のあるリレーションとは、複数の「非キー属 性がないリレーション」を JOIN したリレーション – – = 「見出し全体が候補キーであるようなリレーション」 JOIN する前のリレーション同士は対等な関係性 ● ● ● FD のような方向性はない 発見は難しい 非キー属性がない場合だけ考えれば良い
  86. 86. 一般的な 4NF の解説 一般的には多値従属性( MVD )を取り除いた ものという解説がなされているが、 MVD は JD の特殊なパターン。
  87. 87. 4NF 共通の属性を含む 2 つのリレーションに無損失分解 可能な JD を解消した状態 ☆{AB,AC}
  88. 88. BCNF であって 4NF でない例 名前 格闘スタイル 戦歴 松尾象山 空手 試合 松尾象山 空手 道場破り 松尾象山 空手 喧嘩 丹波文七 空手 試合 丹波文七 空手 喧嘩 丹波文七 空手 路上 丹波文七 柔術 試合 丹波文七 柔術 喧嘩 丹波文七 柔術 路上 長田弘 プロレス 試合 長田弘 プロレス 道場破り 長田弘 柔術 試合 長田弘 柔術 道場破り ☆{{ 名前 , 格闘スタイル },{ 名前 , 戦歴 }}
  89. 89. 5NF 全ての自明でない JD が取り除かれた状態。 3 つ以上のリレーションに無損失分解可能な JD を解消した状態。 最終目標地点。
  90. 90. 実は 5NF です。 名前 格闘スタイル 名前 年齢 範馬刃牙 総合格闘技 範馬刃牙 19 範馬勇次郎 総合格闘技 範馬勇次郎 38 愚地独歩 空手 愚地独歩 57 ビスケットオリバ 怪力 ビスケットオリバ 40 ビスケットオリバ 柔道 花山薫 19 花山薫 素手喧嘩 烈海王 30 烈海王 中国拳法 烈海王 ボクシング
  91. 91. 4NF であって 5NF でない例 name art match 丹波文七 虎王 FAW マッチ 丹波文七 ハイキック FAW マッチ 丹波文七 ストレート FAW マッチ 丹波文七 ストレート 道場破り 丹波文七 ハイキック 道場破り 長田弘 バックドロップ 北心館トーナメント 長田弘 虎王 北心館トーナメント 長田弘 ストレート 北心館トーナメント 長田弘 ボディスラム 道場破り 長田弘 脇がため 道場破り 長田弘 ストレート 道場破り
  92. 92. 6NF 自明なものを含めてすべての JD を取り除く。 非キー属性は最大でひとつ。 正規化をする上ではあまり意味はない。
  93. 93. 自明な JD (再掲) 名前 年齢 国籍 範馬刃牙 19 Japan 範馬勇次郎 38 Japan 愚地独歩 57 Japan ビスケットオリバ 40 U.S.A. 花山薫 19 Japan 名前 年齢 名前 国籍 範馬刃牙 19 範馬刃牙 Japan 範馬勇次郎 38 範馬勇次郎 Japan 愚地独歩 57 愚地独歩 Japan ビスケットオリバ 40 ビスケットオリバ U.S.A. 花山薫 19 花山薫 Japan
  94. 94. リレーションの直交性 ● ● 正規化は個々のリレーションの内部の重複をテーマにした もの リレーション同士の重複に焦点を当てたのが直交性
  95. 95. 用語 4 ● 直交したリレーションとは、互いに重複したタプルを含まな いものを指す。 – – 直交していないと片方だけを更新することで不整合が生 じる 見出しが同じ型のタプルは単に重複がなければ OK
  96. 96. 見出しが異なる場合には 単純に比較できない!!
  97. 97. 直交性を確認する ● ● 6NF まで分解して比較する 重複があればデータベース設計を見なおそう – リレーションの統合と再編
  98. 98. 直交していないリレーションの例 name age nationality 範馬刃牙 19 日本 範馬勇次郎 38 無国籍 愚地独歩 57 日本 ビスケットオリバ 40 アメリカ 花山薫 20 日本 烈海王 30 中国 name fighting_style age 範馬刃牙 総合格闘技 19 愚地克己 空手 21 ジャック・ハンマー 総合格闘技 21 渋川剛気 柔術 60 愚地独歩 空手 57 鎬昂昇 空手 25 本部以蔵 柔術 59
  99. 99. 6NF に分解 name age name nationality 範馬刃牙 19 範馬刃牙 日本 範馬勇次郎 38 範馬勇次郎 無国籍 愚地独歩 57 愚地独歩 日本 ビスケットオリバ 40 ビスケットオリバ アメリカ 花山薫 20 花山薫 日本 烈海王 30 烈海王 中国 name age name fighting_style 範馬刃牙 19 範馬刃牙 総合格闘技 愚地克己 21 愚地克己 空手 ジャック・ハンマー 21 ジャック・ハンマー 総合格闘技 渋川剛気 60 渋川剛気 柔術 愚地独歩 57 愚地独歩 空手 鎬昂昇 25 鎬昂昇 空手 本部以蔵 59 本部以蔵 柔術
  100. 100. 共通の属性をまとめる name age name nationality 範馬刃牙 19 範馬刃牙 日本 範馬勇次郎 38 範馬勇次郎 無国籍 愚地独歩 57 愚地独歩 日本 ビスケットオリバ 40 ビスケットオリバ アメリカ 花山薫 20 花山薫 日本 烈海王 30 烈海王 中国 愚地克己 21 ジャック・ハンマー 21 name fighting_style 渋川剛気 60 範馬刃牙 総合格闘技 鎬昂昇 25 愚地克己 空手 本部以蔵 59 ジャック・ハンマー 総合格闘技 渋川剛気 柔術 愚地独歩 空手 鎬昂昇 空手 本部以蔵 柔術
  101. 101. リレーショナルモデルの 限界
  102. 102. リレーショナルモデルの外側の世界 ● 現実世界 – – – – ● リレーショナルモデルの範疇とそれ以外が入り乱れてい る。 境界線を見極めることが重要。 リレーショナルモデルで解決できる部分はリレーショナル モデルを適用すべし!! リレーショナルモデル以外の領域は創意工夫が必要 リレーショナルモデル≒ SQL – – SQL はリレーショナルモデル以外の分野も扱える SQL なら何とかできるものがある ● ● 非常に容易なものもある 例) GROUP BY, ORDER BY
  103. 103. リレーショナルモデルでは 扱いが難しいテーマ ● ● ● ● ● ● ● ● ● グラフの探索 ツリーの探索 行列 履歴データ 全文検索 正規表現 ソート 集計 空間データ
  104. 104. リレーショナルモデルでは 扱いが難しいテーマ ● ● ● ● ● ● ● ● ● グラフの探索 ツリーの探索 行列 履歴データ 全文検索 正規表現 ソート 集計 空間データ
  105. 105. グラフ ● グラフとは – ノード(頂点)をエッジ(辺)でつないだ構造を持つモデル b d エッジ 多重辺 ノード a c e ループ
  106. 106. 様々なグラフ 単純グラフ 非連結グラフ 完全グラフ 重み付きグラフ e 7 8 5 8 b 3 3 c a 9 d 3 f 4 8
  107. 107. グラフを表現した例 ● グラフ = ノードの集合 + エッジの集合 Nodes Edges Node Node1 Node2 Weight a a b 3 b a e 8 c b c 3 d b d 8 b e 7 c d 4 c f 8 d e 5 d f 3 e f 9 e f
  108. 108. グラフに対するクエリの問題点 ● グラフ特有の問題を表現できない – – – ● 何度 JOIN すれば良いのか事前に分からない – – ● 連結グラフかどうか 閉路があるかどうか 最短距離はどれか グラフを辿ることで得た値によって決まる JOIN を何度するかで、 SQL の構文が異なる 解決策 – – ストアドプロシージャ グラフデータベース
  109. 109. ツリーとは ● 次の条件を満たすグラフのこと – – – – 閉路がなく連結している すべてのエッジはブリッジである 任意の 2 つのノードを結ぶパスはただひとつだけである 隣接していないどの 2 つのノードを結んでも閉路ができ る e b i c g a f h d
  110. 110. よく扱うツリーの特徴 ● ● ● ● 親子関係がある有向グラフである あるノードへ向かうエッジはひとつのみ 全てのノードの出発点になるノードがある(根あるいは root ) a 根からの距離が深さとして表される – 階層構造になっている b e c f d g h
  111. 111. ツリーの表現方法 ● ● ツリーは特殊なグラフ 多数の制約がある – ● 表現の自由度が下がる一方、扱いは簡単になる 代表的なモデル – – – – 隣接リストモデル パス列挙モデル 入れ子集合モデル クロージャテーブルモデル
  112. 112. 隣接リストモデル ● 一般グラフと同じように隣接リストを使って表現する – – ● 子ノードが親ノードの ID を持つ 根ノードの親は NULL 再帰クエリあるいはストアドプロシージャ node_id Q: f の深さはいくつか? WITH RECURSIVE r AS ( SELECT 1 AS level, node_id, parent_id FROM Tree WHERE parent_id IS NULL UNION ALL SELECT r.level + 1, t.node_id, t.parent_id FROM r JOIN Tree t ON r.node_id = t.parent_id) SELECT * FROM r WHERE node_id = 'f'; parent_id a NULL b a c a d a e b f b g c h g
  113. 113. パス列挙モデル ● 根ノードからのフルパスで経路を表現するモデル – – – LIKE 句で検索 深さを求めるのは超簡単 非正規化されたデータそのもの node_id path Q: b の子孫をすべて挙げよ a /a SELECT * FROM Tree WHERE path LIKE CONCAT((SELECT path FROM Tree WHERE node_id='b'), '%'); b /a/b c /a/c d /a/d e /a/b/e f /a/b/f g /a/c/g h /a/c/g/h
  114. 114. 入れ子集合モデル ● ● ノードごとに lft 、 rgt という 2 つの数値を使って、ノードの 包含関係を表現するモデル 親ノードは全ての子ノードを含んでいる a b e c g f h d
  115. 115. 入れ子集合モデル lft と rgt による表現 10 3 2 1 4 6 5 e f 9 7 h g 8 b 11 12 13 14 c 15 d 16 a Q: b の子孫をすべて挙げよ SELECT t1.node_id FROM Tree t1 JOIN Tree t2 WHERE t2.node_id = 'b' AND t1.lft BETWEEN t2.lft AND t2.rgt node_id lft rgt a 1 16 b 2 7 c 8 13 d 14 15 e 3 4 f 5 6 g 9 12 h 10 11
  116. 116. クロージャーテーブルモデル ● 祖先、子孫の関係にあるノードをすべてリストアップ – テーブルサイズは大 更新は容易 Q: c の子孫をすべて挙げよ SELECT descendant FROM Tree WHERE ancestor = 'c' ancestor descendant a b a – c a d a e a f a g a h b e b f c g c h g h
  117. 117. どのモデルを使えば良いのか ● 残念ながら決定版はない!! – – ● なぜなら根本的にツリーとリレーショナルモデルは相容 れないから どのモデルも妥協案に過ぎない 要件次第で使い分けるべき – データサイズを気にしなければクロージャテーブル ● ● – ツリーの形状から分かる「事実」を列挙したもの 「事実の集合←→ツリー」の変換はアプリケーションの 役割 コンパクトさを重視するなら隣接リストモデル ● 再帰クエリ( WITH RECURSIVE )が使えるならクエリ も表現しやすい
  118. 118. 履歴データ ● ● 履歴データ ≒ 時系列で並んだデータ 実はリレーショナルモデルで扱うのは難しい (例)ショッピングサイトの価格リスト item price start_date end_date 10000 2010-01-01 9999-12-31 グリッパー 4000 2012-04-01 2013-03-31 グリッパー 5000 2013-04-01 9999-12-31 懸垂マシン 18000 2010-01-01 2011-12-31 懸垂マシン 20000 2012-01-01 2013-12-31 懸垂マシン 22000 2014-01-01 9999-12-31 ダンベルセット ※2013/11/28 現在
  119. 119. 履歴データの問題点 1 時間軸との直交性 ● リレーションとはある時点での事実の集合 – – ● 変数の中身と同じように、刻々と関係変数( Relvar )の 内容は刻々と変化する ある時点において事実はひとつ 履歴データは時間軸と直交していない! – 時刻が変わればクエリの結果が変わる (例)懸垂マシンの価格を調べるクエリ SELECT price FROM price_list WHERE item = ' 懸垂マシン ' AND NOW() BETWEEN start_date AND end_date
  120. 120. 履歴データの問題点 2 行の意味が異なる ● リレーションとは事実(=真となる命題)の集合 – リレーションには命題関数がある ● ● ● 命題関数に各属性の値を代入した結果=真 命題関数の意味はすべて共通 特定の行だけ(隠れた)特別な意味がある!! – – 現在有効な価格 現在有効でない価格
  121. 121. 行によって特別な意味がある item price start_date end_date 10000 2010-01-01 9999-12-31 グリッパー 4000 2012-04-01 2013-03-31 グリッパー 5000 2013-04-01 9999-12-31 懸垂マシン 18000 2010-01-01 2011-12-31 懸垂マシン 20000 2012-01-01 2013-12-31 懸垂マシン 22000 2014-01-01 9999-12-31 ダンベルセット このテーブルは・・・ 過去の価格 ∪ 現在の価格 ∪ 未来の価格 → そのままでは扱いにくい 有効な 価格 無効な 価格
  122. 122. 履歴データ対策 1 テーブルを分割する ● 意味の異なるリレーションに分ける – – ● 意味の違いが解消 日付はあるものの、クエリの結果には影響を与えない 元のテーブルは UNION で。 過去の価格 現在の価格 item price start_date item price start_date 10000 2010-01-01 グリッパー 4000 2012-04-01 グリッパー 5000 2013-04-01 懸垂マシン 18000 2010-01-01 懸垂マシン 20000 2012-01-01 ダンベルセット
  123. 123. 対策 1 の問題点 ● ● 外部キー制約が使えない 同じレコードが含まれてはいけないという制約をつけるの が難しい – トリガーを使えば表現可能
  124. 124. 履歴データ対策 2 重複したデータを持つ ● ● 外部キーが利用可能 UNION が不要 過去から現在に至るまでの価格 現在の価格 item price start_date item start_date 10000 2010-01-01 グリッパー 4000 2012-04-01 グリッパー 5000 2013-04-01 懸垂マシン 18000 2010-01-01 懸垂マシン 20000 2012-01-01 10000 2010-01-01 ダンベルセット グリッパー 5000 2013-04-01 懸垂マシン 20000 2012-01-01 ダンベルセット price
  125. 125. 対策 2 の問題点 ● 重複したデータがある – – 直交していない 更新異常(矛盾)に注意 ● ● 2 つのテーブルで同じアイテム、同じ日付なのに価格が 異なる どちらか一方だけにしか該当する行がない
  126. 126. 履歴データ対策 3 擬似 (pseudo) キーの利用 ● 外部キーは利用したいけどデータの重複は避けたい キーマスター 現在の価格 price_id price_id item 1 1 ダンベルセット 2 3 price start_date 10000 2010-01-01 3 グリッパー 5000 2013-04-01 5 懸垂マシン 20000 2012-01-01 4 5 過去の価格 price_id item price start_date 2 グリッパー 4000 2012-04-01 4 懸垂マシン 18000 2010-01-01
  127. 127. 対策 3 の問題点 ● 擬似キーは本質的に不要 – – – ● 擬似キー以外にもユニークキーが存在することになる ディスクスペースの無駄 更新のオーバーヘッドが増える JOIN が増える
  128. 128. NG!! こんな設計にご用心 ● フラグを立てたら? – – – end_date → valid フラグは自動的に更新されない フラグだらけになってしまう item price start_date end_date valid 10000 2010-01-01 9999-12-31 y グリッパー 4000 2012-04-01 2013-03-31 n グリッパー 5000 2013-04-01 9999-12-31 y 懸垂マシン 18000 2010-01-01 2011-12-31 n 懸垂マシン 20000 2012-01-01 2013-12-31 y 懸垂マシン 22000 2014-01-01 9999-12-31 y ダンベルセット
  129. 129. クイズ 6 リレーショナルモデルで 表現することができないテーブルでも 正規化できる。 ○ ×
  130. 130. まとめ DB 設計鉄則三箇条 一、リレーショナルモデルを理解する 一、リレーションを正規化する 一、リレーショナルモデルの限界を知る
  131. 131. おすすめの書籍 ● SQL and Relational Theory – ● ● ● ● データベースの実践講義は内容が少ないし古いのでお すすめはしない。 The Art of SQL プログラマのための SQL SQL アンチパターン WEB+DB PRESS – Vol.68 〜
  132. 132. Q&A!! ご静聴ありがとうございました。

×