Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

リレーショナルな正しいデータベース設計

15.070 visualizaciones

Publicado el

北海道データベースDAYで使用した資料です。db tech showcaseの内容に、いくつかの説明を加えています。(講義時間90分)

Publicado en: Software
  • Sé el primero en comentar

リレーショナルな正しいデータベース設計

  1. 1. リレーショナルなリレーショナルな 正しいデータベース設計正しいデータベース設計  奥野 幹也 Twitter: @nippondanji mikiya (dot) okuno (at) gmail (dot) com @ 北海道データベース DAY 2014
  2. 2. 免責事項 本プレゼンテーションにおいて示されている見解は、私 自身の見解であって、オラクル・コーポレーションの見 解を必ずしも反映したものではありません。ご了承くだ さい。
  3. 3. 自己紹介 ● MySQL サポートエンジニア – 日々のしごと ● トラブルシューティング全般 ● Q&A 回答 ● パフォーマンスチューニング など ● ライフワーク – 自由なソフトウェアの普及 ● オープンソースではない ● ブログ – 漢のコンピュータ道 – http://nippondanji.blogspot.com/ 今日は個人として 参加しています。
  4. 4. リレーショナルモデル と聞いて 何を思い浮かべますか?
  5. 5. リレーショナルモデルとは? ● テーブル同士の関係を表現する方法? ● 2 次元のテーブルにデータを格納する? ● ER 図を使ってモデリングすること? ● ストアドプロシージャを使ってナンボ? すべて誤解です!!
  6. 6. リレーショナルモデルは 誤解されている!! ● リレーショナルデータベースは覚えることが多すぎる – データモデル – SQL – アプリケーションプログラムとの融合 – トランザクション – 実装、応用 – 製品もいっぱいある etc etc ● 言ってることがみんな違う – サロゲートキー vs ナチュラルキー – 正規化するべき派 vs 正規化しなくても良い派 – NULL 許容派 vsNULL 否定派 – ロジックは全部ストアドプロシージャで書け派 vs ストアドプロシージャ使ったら負け派 etc etc
  7. 7. 目の前のタスクを優先した結果 ● SQL の構文とトランザクションだけとても詳しくなる – データモデル不在 ● データベースはタダの入れ物です。 – 正規化などどこ吹く風 ● せっかくのリレーショナルデータベースのパワーが・・ リレーショナルモデルが蔑ろに !!
  8. 8. リレーショナルモデルとは! ● リレーションという名前のデータ構造を用いてデータを表現 するデータモデル – データモデル ≠ モデリング – データモデル = データの表現方法 ● リレーションを単位として様々な演算を行う – リレーションはデータそのもの – テーブル同士の関係性(リレーションシップ)ではない
  9. 9. リレーションとは ● 現実世界のある物事に対する事実の集合 テーブル ≒ リレーション
  10. 10. 集合の性質 ● 重複がない ● NULL がない – 実際に存在する値のみ ● 要素間に順序がない – 例え数値でも 米国 ベトナム 日本 オーストラリア スウェーデン カメルーン 要素が含まれるか どうかだけが重要
  11. 11. リレーションの構成部品 ● リレーション=見出し(ヘッダ)+本体(ボディ) ● 見出し(ヘッダ、 headding ) – 属性の集合 ● 属性(アトリビュート) – 名前と型(タイプ) ● 属性値 – 属性で定義された型を持つ値 – ≒ 列(カラム) ● 組(タプル) – 見出しに対応した属性値の集合 – ≒ 行(ロー) ● 本体(ボディ) – 組(タプル)の集合
  12. 12. リレーションのイメージ 見出し 国名 / 文字列 国番号 / 整数 本体 地域 / 文字列 国名:日本 , 国番号: 81, 地域:アジア 国番号: 84, 国名:ベトナム 地域:アジア 国番号: 61, 国名:オーストラリア , 地域:オセアニア 国名:米国 , 国番号: 1, 地域:北米 地域:アフリカ , 国名:カメルーン , 国番号: 237 地域:欧州 , 国名:スウェーデン , 国番号: 46
  13. 13. リレーションは 2 次元ではない ● n 個の属性を持つリレーションは、 n 次元空間にプロットさ れた点(のようなもの)の集合 – タプル = 点 ● 2次元に見えるのは縦横の軸がある表として表現するから – 紙に描かれた絵は2次元になる – 絵が表すものが2次元だとは限らない ● 風景や人物などはすべて3次元
  14. 14. 用語の対応 リレーショナルモデル SQL 関係(リレーション) 表(テーブル) 属性 [ 値 ] (アトリビュート) 列(カラム) 組(タプル) 行(ロー) 対応する概念だが性質は異なる。
  15. 15. 演算の単位はリレーション リレーション R1 リレーション R2 ・ ・ ・ リレーション RX 演算 入力 出力
  16. 16. リレーションの演算 ● 演算の入力も結果もリレーション – n 個のリレーションの演算の結果、 1 個のリレーションが 返る ● クロージャ(閉包) ● 整数と整数の足し算の結果が整数なのと同じ – 演算結果に対して新たに別の演算を適用できる ● 集合操作に基づく演算 – 和、差、直積、射影、制限、結合 etc
  17. 17. リレーションのイメージ(再掲) 見出し 国名 / 文字列 国番号 / 整数 本体 地域 / 文字列 国名:日本 , 国番号: 81, 地域:アジア 国番号: 86, 国名:中華人民共和国 , 地域:アジア 国番号: 61, 国名:オーストラリア , 地域:オセアニア 国名:米国 , 国番号: 1, 地域:北米 地域:アフリカ , 国名:カメルーン , 国番号: 237 地域:欧州 , 国名:スウェーデン , 国番号: 46
  18. 18. 制限( RESTRICT )
  19. 19. 制限( RESTRICT )
  20. 20. 射影( PROJECT )
  21. 21. 射影( PROJECT )
  22. 22. 属性名変更( RENAME ) 国名 / 文字列 国番号 / 整数 大陸 / 文字列
  23. 23. 属性名変更( RENAME ) 国名 / 文字列 国番号 / 整数 地域 / 文字列
  24. 24. 拡張( EXTEND ) 国名 / 文字列 人口 / 整数 面積 / 実数 (km2 )
  25. 25. 拡張( EXTEND ) 国名 / 文字列 人口 / 整数 面積 / 実数 (km2 ) 人口密度 / 実数 ( 人 /km2 )
  26. 26. 和( UNION )
  27. 27. 和( UNION )
  28. 28. 積( INTERSECT )
  29. 29. 積( INTERSECT )
  30. 30. 差( DIFFERENCE )
  31. 31. 差( DIFFERENCE )
  32. 32. 直積( PRODUCT ) a b c d x y z
  33. 33. 直積( PRODUCT ) xa b za bya b yc dxc d zc d
  34. 34. 結合( JOIN ) b y c z a x x 2 y 3 w 1
  35. 35. 結合( JOIN ) 2a x 3b y
  36. 36. 豆知識 ● 直積( Product )と積( Intersect )はいずれも結合( Join) の特殊なケース – 直積・・・共通する属性がひとつも存在しないケース – 積・・・すべての属性がまったく同じケース ● リレーショナルモデルに存在する Join は Inner Join だけ
  37. 37. リレーションの演算は 分かったけど SQL とどう関係あるの?
  38. 38. SELECT の基本形 SELECT select_list FROM table_reference WHERE where_condition
  39. 39. SELECT の実態 = 3 つのリレーション演算 SELECT FROM WHERE 射影 直積 制限
  40. 40. SELECT の評価の順序 SELECT FROM WHERE 3. 射影 1. 直積 2. 制限
  41. 41. 正しく評価されない SELECT の例 SELECT weight / POWER(height, 2) AS bmi FROM body_shapes WHERE bmi > 25 bmi は select_list で登場しているが 評価は一番最後。 WHERE 句で参照するのは不正。 これが通る製品もあるので注意。
  42. 42. リレーショナルモデルを 無視するとどうなるか ● データベース設計がぐだぐだになる。 – セオリー無視 – データとそれに対する操作はセット ● 結果、クエリもぐだぐだになる。 ● データベース設計が良くないと・・・ – クエリがすっきりと表現できない – クエリを書くのに様々なスーパーテクニックが必要に ● 他の人が見たら「なんじゃこりゃ!!?」 ● 自分が後から見ても「なんじゃこりゃ!!?」 ● 結果、メンテナンスが地獄 – ストアドプロシージャが颯爽と登場!! ● スーパーテクニックを駆使したクエリを手続き型で書き なおしただけ。 ● 状況はさらに悪化
  43. 43. Ruby で配列を操作する a = Array.new # 要素の挿入 a.push(' 要素 ') # N 番目の要素 a[N] スッキリ!!
  44. 44. Ruby で配列を操作する 誤ったやり方 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 ● 無駄に長い ● 何をしている処理なのかが一目で 分からない ● 読みづらい ● 間違い(バグ)を犯しやすい ● メンテナンスが大変
  45. 45. 誤った設計は 技術的負債を生む
  46. 46. クエリをすっきり表現するには ● 正しいデータ構造を用いる – リレーショナルデータベース上では正しいデータ構造は たったひとつ – リレーション!! ● テーブルがリレーションになっていること ● 矛盾がないこと ● 集合演算=論理演算に基づく表現 – SELECT  射影 FROM  直積 WHERE  制限
  47. 47. 述語論理 ● 命題 – ある物事について記述した文章で、その意味が正しいかどうか、つま り真なのか偽なのかを問えるもののこと – 例)ポチは犬である ● 述語 – 命題の中の固有名詞をパラメータ化したもの – 例) x は犬である ● 命題関数 – 述語から意味を取り除いて関数化したもの。値を代入した場 合の評価結果は述語と同じ。 – 例) F(x) ● 閉世界仮説 – リレーションは事実の集合 ● 事実=真となる命題 – リレーションには述語がある ● リレーションに含まれる組の属性値を代入 → 真 ● それ以外の属性値を代入 → すべて偽
  48. 48. 宣言型 vs 手続き型 ● SQL は宣言型で使うべき。 ● 宣言型= WHAT – 欲しいデータは SELECT 一発でゲット!! – 論理演算で表現されたもの ● クエリによって欲しい解(集合)に対する述語は何か? ● 手続き型= HOW – 難解なテクニックを駆使した SELECT – ストアドプロシージャ – 論理演算で欲しい解を導出することができない ● 条件分岐 ● ループ
  49. 49. 何故手続き型になってしまうか ● データベース設計が間違っている!! – 欲しい解が論理演算で得られるのは、データベースがそ のように設計されているから – 集合として表現する ● 集合と述語は 1:1 で対応 ● 集合として表現されていないと・・・ – 欲しい解は論理演算では得られない – カーソルをスクロールさせて探す羽目に ● 宣言型で書けない場合にはデータベース設計を見直す兆 候かも
  50. 50. 正しいデータベース設計 ● 集合=リレーションとして表現されたテーブル – NULL がない – 重複がない – 要素(タプル、属性)間に順序がない – 属性の値はドメインの要素のひとつ – 第 1 正規形 ● リレーションになっているからリレーションの演算が適用可能 – リレーションの演算=集合演算=論理演算 – リレーションでないものに対してリレーションの演算は適 用できない!
  51. 51. 正規化理論 ● リレーションから重複を排除するためのデータベース設計 理論 – 重複は矛盾の原因になる。 ● 重複=同じ事実を複数回述べている ● 部分的に変更すると異なる事実を述べることになる – 矛盾が含まれていると、論理演算によって正しい答えが 導き出せない ● 矛盾は論理学の天敵 ● クエリの結果が正しくない可能性がある
  52. 52. 矛盾の例 名前 格闘スタイル 年齢 範馬刃牙 総合格闘技 19 範馬勇次郎 総合格闘技 38 愚地独歩 空手 57 ビスケットオリバ 怪力 40 ビスケットオリバ 柔道 42 花山薫 素手喧嘩 19 烈海王 中国拳法 30 烈海王 ボクシング 30 どっちが 正しい? データそのものを見ただけでは どちらが正しいのかが分からない
  53. 53. 正規形( Normal Forms ) ● 第一正規形 (1NF)~ 第六正規形 (6NF) – より高次の正規形のほうが重複が少ない(望ましい)状態 になる。 – 3NF と 4NF の間に BCNF というものがある。超重要。 – ただし最終目標は 5NF ● 1NF ・・・テーブルがリレーションになっていること – スタート地点 ● 2NF~BCNF ・・・自明でない関数従属性( FD )を排除する ● 4NF~6NF ・・・自明でない結合従属性( JD )を排除する ● 自明でない FD と JD が重複の元
  54. 54. 1NF ● 要件:テーブルがリレーションであること。 1. 行が上から下に順序付けされていない。 2. 列が左から右に順序付けされていない。 3. 重複する行は存在しない。 4. それぞれの行と列の交差点(つまり列の値)は、ドメイン (データ型)に属する要素の値をちょうどひとつだけ含んで いる。 5. 全ての列の値は定義されたものだけであり、かつそれぞ れの行において常に存在する。
  55. 55. 繰り返しグループ 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 花山薫 素手喧嘩 海王烈 中国拳法 名前 格闘スタイル 1 格闘スタイル 2 範馬刃牙 総合格闘技 NULL 範馬勇次郎 総合格闘技 NULL 愚地独歩 空手 NULL ビスケットオリバ 怪力 柔道 花山薫 素手喧嘩 NULL 海王烈 中国拳法 ボクシング カラム追加 同じ性質のもの が繰り返し出現
  56. 56. アトミックな属性 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 柔道 花山薫 素手喧嘩 海王烈 中国拳法 ボクシング 2つ入ってるので 分解可能 それ以上分解できないような属性 ※ 属性の中に繰り返しグループがある。
  57. 57. データ型=ドメイン ● 属性が取りうる値の有限集合 – 集合の要素は分解できない=アトミック – 見出し(ヘッダ)、組(タプル)、本体(ボディ)、そしてドメイ ン。すべて集合。 – 無限でないのはコンピュータで扱う値だから ● 32 ビット整数なら 232 通り ● データサイズが増えれば表現できる要素数は増えるけ ど、絶対に無限にはならない ● ドメインの要素の性質 – 要素はコンピュータで表現できるものなら何でも可 ● ベクトル、行列、配列、リレーションそのものなど – ただしポインタと NULL は NG
  58. 58. 1NF の例 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 ビスケットオリバ 柔道 花山薫 素手喧嘩 海王烈 中国拳法 海王烈 ボクシング ● 繰り返しグループなし ●重複なし ●NULL なし
  59. 59. NG !!こんな設計にはご用心 ● 主キーの”一部”に意味を持たせる ● 例:基礎年金番号 – 1234­567890 ● 問題点 – アトミックでない – 値の一部に依存した処理 ● SELECT … WHERE ID LIKE '1234-%' AND … 事務所の ID 個人の ID
  60. 60. キーと関数従属性 ● 候補キーとスーパーキー – あるリレーションにおいて、タプルの値を一意に決めること ができる属性の集合で、規約のもの(それ以上要素を減 らすことができないもの)を候補キーという – 候補キーのスーパーセット、つまり余分な属性を含んだも のをスーパーキーという ● すべての属性を含む集合は常にスーパーキー ● 関数従属性( Functional Dependency ­ FD ) – あるリレーション R の見出しの 2 つの部分集合を A 、 B と する。 R の要素の全てのタプルにおいて、 A の値が同じ ならば B の値も同じである場合かつその場合だけに限 り、 B は A に関数従属すると言い、 A   B→ と記述する。 – スーパーキー → 任意の属性の集合 ● 自明な FD
  61. 61. 2NF 候補キーの真部分集合(それ自身は含まないもの) から非キー属性への FD を取り除いた状態。 タプル 候補キー 非キー属性 ・・・ FD
  62. 62. 2NF でないリレーションの例 名前 格闘スタイル 年齢 範馬刃牙 総合格闘技 19 範馬勇次郎 総合格闘技 38 愚地独歩 空手 57 ビスケットオリバ 怪力 40 ビスケットオリバ 柔道 40 花山薫 素手喧嘩 19 烈海王 中国拳法 30 烈海王 ボクシング 30 FD 名前が同じなら 年齢は常に同じ 候補キー 図に描くときは アンダーラインをひく
  63. 63. FD を解消する ● 無損失分解する – 必要な操作は射影 ● SELECT DISTINCT – { 名前 , 格闘スタイル , 年齢 } ● FD:  名前 → 年齢 ● FD を含む属性の射影 +FD の非キー属性(この場合は 年齢)を取り除いた属性の射影 ● { 名前 , 年齢 },{ 名前 , 格闘スタイル }
  64. 64. 2NF の例 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 ビスケットオリバ 柔道 花山薫 素手喧嘩 烈海王 中国拳法 烈海王 ボクシング 名前 年齢 範馬刃牙 19 範馬勇次郎 38 愚地独歩 57 ビスケットオリバ 40 花山薫 19 烈海王 30
  65. 65. 分解するとテーブルが 増えてしまうのでは? テーブルを減らそうと 誤った DB 設計になるほうが問題 ● テーブルが増えると開発工数が増える? ● テーブル数に応じてメンテナンスの手間も増える? ● テーブル数は増やさないほうが良い? テーブル数が増えても問題ない!
  66. 66. 3NF 非キー属性同士の FD を解消した状態。 タプル 候補キー 非キー属性 ・・・ FD
  67. 67. 2NF であって 3NF でない例 名前 格闘スタイル 寝技 範馬刃牙 総合格闘技 Yes 範馬勇次郎 総合格闘技 Yes 愚地独歩 空手 No ビスケットオリバ 怪力 No 花山薫 素手喧嘩 Yes 烈海王 中国拳法 No
  68. 68. BCNF ボイス・コッド正規形の略。 すべての自明でない FD が取り除かれた状態。 残る FD は、非キー属性から 候補キーの真部分集合への FD 。 タプル 候補キー 非キー属性 ・・・ FD
  69. 69. 3NF であって BCNF でない例 名前 格闘スタイル 流派 松尾象山 空手 北辰館 姫川勉 空手 北辰館 丹波文七 柔術 竹宮流 丹波文七 空手 丹波流 長田弘 プロレス FAW 長田弘 柔術 竹宮流 藤巻十三 柔術 竹宮流
  70. 70. FD のおさらい タプル 候補キー 非キー属性 ・・・ FD タプル 候補キー 非キー属性 ・・・ FD タプル 候補キー 非キー属性 ・・・ FD
  71. 71. 候補キー内部には FD がない ● もし仮に候補キーに FD があると・・・ – {A,B} が候補キー – A → B – B の値は A によって決まる ● 規約ではない!
  72. 72. 結合従属性 ● 結合従属性( Join Dependencies ­ JD ) – Join すると元に戻るような無損失分解 – A,B,...,C をリレーション R の見出しの部分集合であるとする。 もし A,B,...,C に対応するリレーションを結合した結果と R が同 じ場合かつその場合に限り、 R は以下の JD を満たすという。   ☆{A,B,...,C} ● 暗黙的な JD – 複数の非キー属性があるリレーションにおいて、それぞれ候補 キーを含んだ複数の異なるリレーションに無損失分解できるよ うな JD 。( Implied by super keys ) ● 自明な JD – 無損失分解後のリレーションのひとつが、元のリレーションその ものである場合
  73. 73. 暗黙的な JD 名前 年齢 国籍 範馬刃牙 19 Japan 範馬勇次郎 38 Japan 愚地独歩 57 Japan ビスケットオリバ 40 U.S.A. 花山薫 19 Japan 名前 年齢 範馬刃牙 19 範馬勇次郎 38 愚地独歩 57 ビスケットオリバ 40 花山薫 19 名前 国籍 範馬刃牙 Japan 範馬勇次郎 Japan 愚地独歩 Japan ビスケットオリバ U.S.A. 花山薫 Japan
  74. 74. 4NF/5NF のヒント ● 非キー属性がある BCNF に暗黙的でない JD はない – 何故ならば、候補キーがバラバラになるような射影をとる と FD が消失してしまう。 ● FD:  候補キー → 非キー属性 ● 無損失分解ができない!! – 非キー属性のある BCNF は自動的に 5NF になる。 ● 4NF/5NF – 非キー属性がないリレーションのみが対象 – 暗黙的でない JD がある場合に無損失分解
  75. 75. 暗黙的でない JD の本質 ● 暗黙的でない JD のあるリレーションとは、複数の「非キー 属性がないリレーション」を JOIN したリレーション – =  「見出し全体が候補キーであるようなリレーション」 – JOIN する前のリレーション同士は対等な関係性 ● FD のような方向性はない ● 発見は難しい ● 非キー属性がない場合だけ考えれば良い
  76. 76. 一般的な 4NF の解説 一般的には多値従属性( MVD )を取り除いた ものという解説がなされているが、 MVD は JD の特殊なパターン。
  77. 77. 4NF 共通の属性を含む 2 つのリレーションに無損失分解可 能な JD を解消した状態 ☆{AB,AC}
  78. 78. BCNF であって 4NF でない例 名前 格闘スタイル 戦歴 松尾象山 空手 試合 松尾象山 空手 道場破り 松尾象山 空手 喧嘩 丹波文七 空手 試合 丹波文七 空手 喧嘩 丹波文七 空手 路上 丹波文七 柔術 試合 丹波文七 柔術 喧嘩 丹波文七 柔術 路上 長田弘 プロレス 試合 長田弘 プロレス 道場破り 長田弘 柔術 試合 長田弘 柔術 道場破り ☆{{ 名前 , 格闘スタイル },{ 名前 , 戦歴 }}
  79. 79. 5NF 全ての暗黙的でない JD が取り除かれた状態。 3 つ以上のリレーションに無損失分解可能な JD を解消した状態。 最終目標地点。
  80. 80. 実は 5NF です。 名前 格闘スタイル 範馬刃牙 総合格闘技 範馬勇次郎 総合格闘技 愚地独歩 空手 ビスケットオリバ 怪力 ビスケットオリバ 柔道 花山薫 素手喧嘩 烈海王 中国拳法 烈海王 ボクシング 名前 年齢 範馬刃牙 19 範馬勇次郎 38 愚地独歩 57 ビスケットオリバ 40 花山薫 19 烈海王 30
  81. 81. 4NF であって 5NF でない例 name art match 丹波文七 虎王 FAW マッチ 丹波文七 ハイキック FAW マッチ 丹波文七 ストレート FAW マッチ 丹波文七 ストレート 道場破り 丹波文七 ハイキック 道場破り 長田弘 バックドロップ 北心館トーナメント 長田弘 虎王 北心館トーナメント 長田弘 ストレート 北心館トーナメント 長田弘 ボディスラム 道場破り 長田弘 脇がため 道場破り 長田弘 ストレート 道場破り
  82. 82. 6NF 暗黙的なものを含めて すべての自明でない JD を取り除く。 非キー属性は最大でひとつ。 正規化をする上ではあまり意味はない。
  83. 83. 暗黙的な JD (再掲) 名前 年齢 国籍 範馬刃牙 19 Japan 範馬勇次郎 38 Japan 愚地独歩 57 Japan ビスケットオリバ 40 U.S.A. 花山薫 19 Japan 名前 年齢 範馬刃牙 19 範馬勇次郎 38 愚地独歩 57 ビスケットオリバ 40 花山薫 19 名前 国籍 範馬刃牙 Japan 範馬勇次郎 Japan 愚地独歩 Japan ビスケットオリバ U.S.A. 花山薫 Japan
  84. 84. 直交性 ● 正規化は個々のリレーションの内部の重複をテーマにしたも の ● リレーション同士の重複に焦点を当てたのが直交性 ● 直交したリレーションとは、互いに重複したタプルを含まな いものを指す。 – 直交していない(同じ事実を重複して述べている)と片方 だけを更新することで不整合が生じる
  85. 85. 直交性を確認する ● 見出しが同じ型のタプルは単に重複がなければ OK ● 見出しが部分的に同じだが完全に一致しない場合 – 6NF まで分解して比較する ● 重複を解消するには – リレーションの統合と再編
  86. 86. 直交していないリレーションの例 name fighting_style age 範馬刃牙 総合格闘技 19 愚地克己 空手 21 ジャック・ハンマー 総合格闘技 21 渋川剛気 柔術 60 愚地独歩 空手 57 鎬昂昇 空手 25 本部以蔵 柔術 59 name age nationality 範馬刃牙 19 日本 範馬勇次郎 38 無国籍 愚地独歩 57 日本 ビスケットオリバ 40 アメリカ 花山薫 20 日本 烈海王 30 中国
  87. 87. 6NF に分解 name age 範馬刃牙 19 愚地克己 21 ジャック・ハンマー 21 渋川剛気 60 愚地独歩 57 鎬昂昇 25 本部以蔵 59 name nationality 範馬刃牙 日本 範馬勇次郎 無国籍 愚地独歩 日本 ビスケットオリバ アメリカ 花山薫 日本 烈海王 中国 name fighting_style 範馬刃牙 総合格闘技 愚地克己 空手 ジャック・ハンマー 総合格闘技 渋川剛気 柔術 愚地独歩 空手 鎬昂昇 空手 本部以蔵 柔術 name age 範馬刃牙 19 範馬勇次郎 38 愚地独歩 57 ビスケットオリバ 40 花山薫 20 烈海王 30
  88. 88. 共通の属性をまとめる name age 範馬刃牙 19 範馬勇次郎 38 愚地独歩 57 ビスケットオリバ 40 花山薫 20 烈海王 30 愚地克己 21 ジャック・ハンマー 21 渋川剛気 60 鎬昂昇 25 本部以蔵 59 name nationality 範馬刃牙 日本 範馬勇次郎 無国籍 愚地独歩 日本 ビスケットオリバ アメリカ 花山薫 日本 烈海王 中国 name fighting_style 範馬刃牙 総合格闘技 愚地克己 空手 ジャック・ハンマー 総合格闘技 渋川剛気 柔術 愚地独歩 空手 鎬昂昇 空手 本部以蔵 柔術
  89. 89. リレーショナルモデルは 万能薬ではない
  90. 90. リレーショナルモデルでは 表現できないものがある ● グラフ ● ツリー ● 行列 ● 履歴 ● 全文検索 ● 正規表現 ● ソート ● 集計 ● 空間データ etc etc
  91. 91. グラフ ● グラフとは – ノード(頂点)をエッジ(辺)でつないだ構造を持つモデル b d c e aノード エッジ ループ 多重辺
  92. 92. 様々なグラフ 単純グラフ 非連結グラフ 完全グラフ 重み付きグラフ b d c f a e 8 3 7 9 3 5 3 4 8 8
  93. 93. データを格納するだけなら できなくはない ● グラフ = ノードの集合 + エッジの集合 Nod e a b c d e f Node1 Node2 Weight a b 3 a e 8 b c 3 b d 8 b e 7 c d 4 c f 8 d e 5 d f 3 e f 9 Nodes Edges
  94. 94. 問題はクエリ・・・ ● グラフ特有の問題を SELECT で表現できない – グラフが連結かどうか – 閉路はあるか – 2 つのノード間の最短距離はどれか – 全てのノードを通り、距離が最短になる経路はどれか ● グラフ特有の問題を解くためには・・・ – 論理演算でないアルゴリズムが必要 – ループと条件分岐 ● 解決策 – リレーショナルモデル上では解決策はない!! ● ストアドプロシージャ ● グラフデータベース
  95. 95. リレーショナルモデルの 外側の世界 ● 現実世界のアプリケーション – リレーショナルモデルに適合するデータと、そうでない データが入り乱れている。 – リレーショナルモデルには定石がある – リレーショナルモデル以外の領域に決定的なやりかた ( DB 設計、クエリの書き方等)はない ● 創意工夫が必要 ● 外側の世界ではリレーショナルモデルを無理に実践すべき ではない!! – そもそも無理 – うまく行ったように見えても技術的負債に ● 両者の境界線を見極めることが重要。 – リレーショナルモデルで解決できる部分はリレーショナル モデルを適用すべし!! – そうでない部分はリレーショナルモデルを適用してはなら ない!!
  96. 96. リレーショナルモデルの 外側の世界 (つづき) ● SQL はリレーショナルモデル以外の分野も扱える – リレーショナルモデル≒ SQL ● 完全に同じではないから外側の世界も扱うことが可能 – 重複 OK – NULL OK – 手続き型の処理すら可能 – SQL なら非常に容易なものもある ● 例) GROUP BY, ORDER BY – ストアドプロシージャは頼りになる ● NoSQL との連携もアリ – 餅は餅屋
  97. 97. NoSQL について ● リレーショナルデータベースが苦手とするようなデータを容 易に扱えるケースがある – リレーショナルモデルの外側の世界は、 NoSQL のテリト リーかも知れない ● グラフデータベース ● ドキュメント型データベース etc ● リレーショナルモデルは NoSQL にとっては外側の世界 – 論理的なデータの整合性を担保するのは苦労する – 壮大な車輪の再発明が必要 ● 正規化 ● トランザクション etc
  98. 98. 履歴データ ● 履歴データ ≒ 時系列で並んだデータ ● 実はリレーショナルモデルで扱うのは難しい 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 2014-12-31 懸垂マシン 22000 2015-01-01 9999-12-31 (例)ショッピングサイトの価格リスト ※2014/11/16 現在
  99. 99. 履歴データの問題点 1 時間軸との直交性 ● リレーションとはある時点での事実の集合 – 変数の中身と同じように、刻々と関係変数( Relvar )の 内容は刻々と変化する – ある時点において事実はひとつ ● 履歴データは時間軸と直交していない! – 時刻が変わればクエリの結果が変わる (例)懸垂マシンの価格を調べるクエリ SELECT price FROM price_list WHERE item = ' 懸垂マシン ' AND NOW() BETWEEN start_date AND end_date
  100. 100. 履歴データの問題点 2 行の意味が異なる ● リレーションとは事実(=真となる命題)の集合 – リレーションには命題関数がある ● 命題関数に各属性の値を代入した結果=真 ● 命題関数の意味はすべて共通 ● 特定の行だけ(隠れた)特別な意味がある!! – 現在有効な価格 – 現在有効でない価格
  101. 101. 行によって特別な意味がある 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 2014-12-31 懸垂マシン 22000 2015-01-01 9999-12-31 有効な 価格 無効な 価格 このテーブルは・・・ 過去の価格 ∪ 現在の価格 ∪ 未来の価格 → そのままでは扱いにくい
  102. 102. 履歴データ対策 1 テーブルを分割する ● 意味の異なるリレーションに分ける – 意味の違いが解消 – 日付はあるものの、クエリの結果には影響を与えない ● 元のテーブルは UNION で。 item price start_date ダンベルセット 10000 2010-01-01 グリッパー 5000 2013-04-01 懸垂マシン 20000 2012-01-01 item price start_date グリッパー 4000 2012-04-01 懸垂マシン 18000 2010-01-01 現在の価格 過去の価格
  103. 103. 対策 1 の問題点 ● 外部キー制約が使えない ● 同じレコードが含まれてはいけないという制約をつけるのが 難しい – トリガーを使えば表現可能
  104. 104. 履歴データ対策 2 重複したデータを持つ ● 外部キーが利用可能 ● UNION が不要 item price start_date ダンベルセット 10000 2010-01-01 グリッパー 5000 2013-04-01 懸垂マシン 20000 2012-01-01 item price start_date ダンベルセット 10000 2010-01-01 グリッパー 4000 2012-04-01 グリッパー 5000 2013-04-01 懸垂マシン 18000 2010-01-01 懸垂マシン 20000 2012-01-01 現在の価格 過去から現在に至るまでの価格
  105. 105. 対策 2 の問題点 ● 重複したデータがある – 直交していない – 更新異常(矛盾)に注意 ● 2 つのテーブルで同じアイテム、同じ日付なのに価格が 異なる ● どちらか一方だけにしか該当する行がない
  106. 106. 履歴データ対策 3 擬似 (pseudo) キーの利用 ● 外部キーは利用したいけどデータの重複は避けたい price_ id 1 2 3 4 5 price_i d item price start_date 1 ダンベルセット 10000 2010-01-01 3 グリッパー 5000 2013-04-01 5 懸垂マシン 20000 2012-01-01 キーマスター 現在の価格 price_i d item price start_date 2 グリッパー 4000 2012-04-01 4 懸垂マシン 18000 2010-01-01 過去の価格
  107. 107. 対策 3 の問題点 ● 擬似キーは本質的に不要 – 擬似キー以外にもユニークキーが存在することになる – ディスクスペースの無駄 – 更新のオーバーヘッドが増える ● JOIN が増える
  108. 108. インデックスとは何か ● インデックスはリレーショナルモデルの一部ではない – リレーショナルモデル=データの論理的な表現 – インデックス=データの物理的なアクセス手段 ● =実装 ● 論理>物理 ● クエリ(何のデータが欲しいか)が決まってから、それを実現 するためのアクセス手段を考える – 良くある失敗:既にあるインデックスを使ってどういう風に クエリを書くかを考える – どのカラムの組み合わせに対してどんなインデックスが 必要なのかはクエリ次第
  109. 109. トランザクション ● データの整合性を保つために必須の機能 – リレーショナルモデルとは全く異なる理論 – 補完関係にある ● トランザクションが実現するものは 2 つ – 同時実行制御(排他処理) – クラッシュリカバリ ● ACID 特性 – 原子性( Atomicity ) – 一貫性( Consistency ) – 独立性( Isolation ) – 永続性( Durability ) 一貫性を考える上で データモデルが 重要になる
  110. 110. 複雑さに立ち向かう ● アプリケーションの規模が大きくなるとデータが複雑に – スキーマの複雑化は避けられない ● アプリケーションのコードとの整合性 – スキーマばかりにとらわれがち ● データの整合性について見落としがち – トランザクションが重要だということはよく把握されている – 正規化は? ● 正規化が必要な理由はデータの整合性を保つ ● アプリケーションのコードではなく DB 設計で整合性を担 保するのが正規化 ● スキーマレスにしてもデータの複雑さから解放されるわけで はない – むしろ問題点のほうが大きい ● スキーマの整合性を担保できない ● データの整合性を担保できない
  111. 111. まとめ:上手に RDB を使うために ● リレーショナルモデルを実践する – クエリがすっきりと表現できる – メンテナンス性向上 ● テーブルはきっちり正規化する – データの保全を考える – 複雑さへの対処 ● リレーショナルモデルの限界を知る – リレーショナルモデルのセオリーが通用しない世界がある – リレーショナルモデル以外の重要な機能について知る ● インデックス ● トランザクション
  112. 112. おすすめの書籍 ● SQL and Relational Theory – データベースの実践講義は内容が少ないし古いのでおす すめはしない。 ● The Art of SQL ● プログラマのための SQL ● SQL アンチパターン ● Transactional Information Systems ● WEB+DB PRESS – Vol.68 ~
  113. 113. 宣伝:新書籍の紹介 ● リレーショナルデータベース実践入門 – リレーショナルモデル、 SQL 、そして DB 設計が主なテーマの書籍です。 – どうやってリレーショナルデータベースを使いこなすか! ● リレーショナルモデル基礎編 – SQL とリレーショナルモデル – 述語論理とリレーショナルモデル – 正規化 1:  関数従属性 – 正規化 2:  結合従属性 – 直交性 – ドメインの設計 etc ● アプリケーション開発実践編 – 履歴 – グラフ – インデックスの設計 – ウェブアプリケーションのためのデータ構造 etc 基礎の基礎から よくある間違いを 指摘しつつ 応用まで
  114. 114. Q&Aご静聴ありがとうございました。

×