• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
SQLアンチパターン メンター用資料
 

SQLアンチパターン メンター用資料

on

  • 760 views

SQLアンチパターン 読書会用メンター資料

SQLアンチパターン 読書会用メンター資料

Statistics

Views

Total Views
760
Views on SlideShare
758
Embed Views
2

Actions

Likes
6
Downloads
1
Comments
0

1 Embed 2

http://s.deeeki.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    SQLアンチパターン メンター用資料 SQLアンチパターン メンター用資料 Presentation Transcript

    • SQLアンチパターン メンター用資料 VOYAGE GROUP システム本部 三浦@hironomiu 1
    • 0章 • 本資料 • O ReillyのSQLアンチパターンを用いた勉強会の際にメンター用として作成 • 書籍と合わせて利用するための資料です • 個人の主観が大きく入っています • サンプルデータベース • xxi xxiii • サンプルコード • http://www.oreilly.co.jp/books/9784873115894/ • bksqla-code.tgz 2
    • 1章ジェイウォーク • 閑話 FKをつける際に気をつける事 • 親、子のカラム定義 • 1.2 アンチパターンを実践するDDLの流れ? • データの洗い替え方法を考える • 1.2.1 regexpやfind_in_setの実行計画 • 1.2.2 account_id = 34 は? • 1.2.3 実装しているSQLはどういう意図のSQL? • 1.2.4 アカウントの更新、削除は? • 1.2.5 bananaの妥当性はどのようにする? • 1.4 業務でアンチパターンの利用例はある? • 1.5 交差テーブル 多対多の関連を表現するテーブル(連関エンティティ?) • ジェイウォークに到達するまでの手順、実行計画 3
    • 2章ナイーブツリー • 2.1 階層構造とは • 組織図 • 商品カテゴリ • 掲示板(この章は掲示板を前提に記されている) • ネットワーク図ではありません(循環しない等) • 隣接リスト(+再起クエリ) • 再起クエリ WITH句、CONNECT BY PRIOR構文 • http://www.oracle.com/technetwork/jp/articles/otnj-sql-image7-1525406-ja.html • 親キー = 子キー のデータを挿入した場合どのような問題が生じるか(循環=無限ループ) • 2.2 なぜ隣接リストはアンチパターンなのか? • コメント数のようなcountがしずらい • そもそも1回のSQLで任意の階層データ全てを取得する必要はある? 4
    • 2章ナイーブツリー • 2.5.1 経路列挙 • パンくずリスト • ジェイウォークの問題点を抱える • 存在しない親、不正な文字列が挿入された場合 • 挿入出来る文字数の限界 • 自分のIDを入れる理由? • 2.5.2 入れ子集合 • http://www.geocities.jp/mickindex/database/db_tree_ns.html • ショッピングで使っている • 発展系 入れ子区間集合 • http://gihyo.jp/dev/serial/01/sql_academy2/000601 5
    • 2章ナイーブツリー • 2.5.3 閉包テーブル • ジェイウォークの解決版? • TreePaths = 交差テーブル(連関エンティ ティ) • 10回ネストすると55行TreePathsに挿入? • 自分のIDを入れる理由? 6
    • 2章ナイーブツリー • 2.5.4 比較表で考える • 自分から親をたどる • 自分から子をたどる • どれが自分の親か?(複数の親(親、祖父、祖祖父)がいる場合) • メンテナンス • 挿入(末端に追加、途中に追加) • 削除(自身のみ削除、自身より子孫も削除) • 更新(キーの更新、属する親キーの更新、従属する内容の更新) • キーの整合性の保証(参照整合性) 7
    • 3章IDリクワイアド • 35P 主キーは必要か? • 3.2 なぜこれがアンチパターンなのか考える • 特定のプラットフォームでの仕様による考慮(innodb クラスタインデックス) • http://dev.mysql.com/doc/refman/5.1-olh/ja/innodb-index-types.html • RDBMSでの行の特定方法(rowid,PK) • 実演 userテーブルに100万レコード で UUIDのようなuser_id 主にインデックスのスプリットについて考える • サロゲートキーでのinsert • user_idをPKにしてinsert • 論理設計にてマスタ、トランザクション(+サマリー)の観点 • 3.2.1 マスタでのメリット、デメリット(弾力性、親子関係) • 3.2.3 キーの意味 テーブル名+カラム名、カラム名だけで意味をもたす?(3.5.1も同様) • P39 シーケンスについて(auto_increment、Oracle sequence、などなど) 8
    • 4章キーレスエントリ(外部 キー嫌い)• 4.1 データベースのアーキテクチャの単純化 • どちらかと言うと良い意味でリレーションの可視化、強制化の側面もある • 4.2.1 • 仮登録の場合(別テーブルで回避する?(設計レベル)) • データフロー(親から挿入、子から挿入) • 参照整合性が可能なケース • データフロー(親(マスタ)、子(トランザクション))社員マスタ ー 行動履歴トランザクション • マスタとトランザクションを非同期で削除したい場合(カスケードを除外するか) • 親データは消えるが、子データは将来も残る(商品マスタは都度変わるが購買履歴上の商品情報は残 したい)(※商品マスタを履歴化することにも絡む) • データフロー(親(トランザクション)、子(トランザクション))受注トランザクション ー 受注明細ト ランザクション • 同一ドメインレベルでの縛りと参照整合性 9
    • 4章キーレスエントリ(外部 キー嫌い) • 4.5 ポカヨケ • http://ja.wikipedia.org/wiki/%E3%83%9D%E3%82%AB %E3%83%A8%E3%82%B1 • 4.5.1 カスケード更新 • http://dev.mysql.com/doc/refman/5.1/ja/innodb-foreign-key-constraints.html • 4.5.2 オーバーヘッドになるか否か • 過去は少ないリソースの制限が大きかったが今はオーバーヘッドを考慮する必要は無い (と考える) • データの不整合で不具合に陥った経験あります? • 冒頭のような経験 10
    • 5章EAV(エンティティアトリ ビュート・バリュー) • そもそも正規化するとこうなる? • 初期からではなく拡張の際に現れやすい(もしくは予め将来を見越す場合) • 5.2 anti 汎用的な属性テーブルを使用する • 5.2.2 EAVの問題点 • 必須属性を指定できない • 様々なattributeとvalueがあるため強制出来ない • SQLのデータ型を使えない • 日付も全て文字列で表現 • 参照整合性を強制出来ない • attributeすら間違いに気付けない 11
    • 5章EAV(エンティティアトリ ビュート・バリュー) • 5.5 サブタイプモデリング • スーパータイプ、サブタイプ? • 排他的(片方に存在)、共存的(重複して存在) • 完全(スーパータイプのキーが全てサブタイプに存在する) • 不完全(完全では無い場合) • 5.5.1 シングルテーブル継承 = スーパータイプに統合して実装 • 5.5.2 具象テーブル継承 = サブタイプのみで実装 • 5.5.3 クラステーブル継承 = スーパータイプ、サブタイプをそのまま実装 12
    • 5章EAV(エンティティアトリ ビュート・バリュー) • 5.5.4 半構造化データ = ジェイウォーク • 短所「このような構造においてSQLが特定の属性に アクセスする手段をほとんど持っていない。」 • 5.5.5 後処理 • EAVを使わないといけない状況「プロジェクトを引 き継いだ場合」 • 経験あります? 13
    • 6章ポリモーフィック関連 • この件に限らず、大体のアンチパターンはちゃんとモデリングから正規化を進めたらありえない実装 • イントロ • Bugs - Comments, FeatureRequest - Comments • P68 そもそもコメントを1つのテーブルに格納したい? • 外部キー • Bugsのコメント集計、FeatureRequestのコメント集計 • 削除運用 • Bugsのコメント、FeatureRequestのコメントの各々のドメイン • 具象テーブルを利用するのはNG?(Bugs,FeatureRequestsの各々にコメント情報を持つ) • 6.2.1 ポリモーフィック関連 issue_type はEAV(メタデータ:テーブル名の挿入) • EAVと同じ問題点(メタデータの内容が不正だった場合は?) • 6.2.2 SQLを実行して確認 14
    • 6章ポリモーフィック関連 • 6.2.3 User,Orders,Addressesのような関係 • 業務的にどういう関係か考える • 解法としてUserにAddressesのKey,OrdersにUserのKeyでは? • 送付先がユーザ登録されていない場合はNG • 6.5.1 6.2.3の解法=逆さま(UserとAddressesの関係の逆転) • 6.5.2 交差テーブルを作る必要はある? • 6.5.3 交差点に交通信号 • XXXComenntsにユニークキーを貼る理由 • 仕様としてXXXCommentsとCommentsを1対1にしたい? • BugsComments、FeaturesCommentsの両方に同じComment_idがある場合は? • 6.5.6 issueのサブタイプ化 • ちょっと無理のある実装 15
    • 7章マルチカラムアトリビュー ト • イントロ 複数の電話番号を格納したい場合どうする?(複数のカラムを作る?) • 7.1 ジェイウォークと同じテーマの問題とは? • 複数の値を持つ属性を格納する(例 タグ付けの複数可) • 7.2 複数の列を定義 • 定義数(有限)のみ可能 • 7.2.4 増加する値の処理の限界 • Alter時の注意(オンライン処理の場合止めれない等) • レプリケーション遅延も考慮する(MySQLの場合) • 「まず新規テーブルを定義し既存テーブルからデータをコピー∼」 • MySQL、Oracle各々の場合は? • 後続の処理を行うSQLのメンテ(追加したカラム分だけ or XXX = hoge の追加) 16
    • 7章マルチカラムアトリビュー ト(複数列属性) • 7.2.1 検索が不便 • co1=a and col2=b and col3=c • co1=b and col2=c and col3=a • co1=c and col2=a and col3=b • リテラルな文字列 in (col1,col2) の動き • P83 performance in (tag1,tag2,tag3) ー>  Full Scan • 7.2.2 更新も不便 • 7.2.3 一意性(行内のカラム)が保証できない • 7.4 アンチパターンを用いてよい場合 • 例は可変なマルチカラムでは無い状況(ドメインは同じだが、カラムには各々意味がある) • 7.5 従属テーブルを作成する • 親子の関係で解決する メリットは? 17
    • 8章メタデータトリブル • P90 「データの移行、表領域の再構成、新しい列の追加」 • 昔は表領域をきめ細かく領域管理していたが最近はhot spotを無くす考えが主流 • Oracle S.A.M.E.(Stripe And Mirror Everything) • 余談 32bit、64bit(扱えるメモリ)、搭載出来るメモリ(10年前は2Gとか)、ストレージの性能& 役割分担 • 8.1 「この章の目的は、クエリの実行速度を劣化させず」 • 大規模データを扱う際についての章? • メタデータが増えることと大規模データの相関? • P91 メタデータへのデータの混入? • rename table hoge to hoge_bk ,hoge_new to hoge; • bk,newがデータ • データへのメタデータの混入の逆 18
    • 8章メタデータトリブル • 8.2 アンチパターン • 行数の多いテーブルを複数のテーブルに分割する • 表領域、表のサイズの上限(過去のRDBMSの制限)★アンチ • 8.2.1 テーブルの増殖 • アクションログ • 挿入時の主キーの衝突を防ぐ • 意図したsharding(この章のshardingとは違うが) 19
    • 8章メタデータトリブル • 8.5.1 水平パーティショニング(sharding?) • 8.5.1の例はRDBMSのパーティショニング機能 • パーティショニング機能を利用するメリットは? • パーティションプルーニング(バッチ処理向き) • パーティション単位でのセグメント管理(Partition Dropによる領域解放) • 挿入時のボトルネックの改善(主に主キーの衝突をRDBMSレベルで回避) • 主にハッシュパーティション • RDBMSレベルでのI/Oのコントロール(均等化、局所化) • 均等化 主にハッシュパーティション、局所化 レンジ(日付、最新のみ書き込み参照) • 一般的(?)なshardingとは • 物理的な分割(ただし各ノードのI/Oは均等になるよう設計) • 水平の1スライス毎(shard毎)に独立し全機能の提供 20
    • 8章メタデータトリブル • 8.5.2 垂直パーティショニング • 機能分割、カラム分割 • 余談 1台のサーバでサービス提供している場合 • WEB+AP,DBと2台のサーバに分けるのも垂直分割(パーティションでは 無いが) • Text,Blob以外の切り離しだと • user_master,user_attributeのようなモデリング • どちらも不要なI/Oを減らせる • 8.5.3 イントロの解決策は? 21
    • 9章ラウンディングエラー • 型毎のbyte数 • http://dev.mysql.com/doc/refman/5.1-olh/ja/numeric-types.html • (浮動小数点型では、MySQL は単精度値には 4 バイトを使用し、倍精度値には 8 バイト使用します。 ) • 9.2 アンチパターン • IEEE_754 • http://ja.wikipedia.org/wiki/IEEE_754 • DB視点での型の選択 • ドメイン • 可逆性(もしくは同一値) • エスケープしてからデータを格納する -> 基本NG • キャストしてからデータを格納する -> 基本NG • 導出項目、導出結果(計算結果)の扱い 22
    • 10章サーティワンフレーバー • マスターエンティティ(テーブル)とは • 組織や人、「もの」などの経営資源を管理するもの(DBS 過去問) • status等の状態をマスタ(10.5 解決策 参照テーブルとして持つ)で管理する? • 区分やフラグ -> アプリケーション側に値の妥当性についての責務 • なんでもマスタにして困る?(テーブルを沢山作って困る事ある?) • 一度に開けるテーブル数の制限(がある場合)、file descriptorの制限 • 10.1 列を特定の値に限定する • 特定の値に限定する = カラムデータの妥当性の責務をどこに持たせるか • アプリ or DB? • DBの場合 チェック制約?ユーザ定義型?エンティティ? • アプリの場合 区分値等による判断(テーブルにはコメント句で明示) 23
    • 10章サーティワンフレーバー • enum,check • 小ネタ mysql set sql_mode ='STRICT_ALL_TABLES'; • https://dev.mysql.com/doc/refman/5.1/ja/server-sql- mode.html • ドメイン、UDTについてRDBプラットフォームごとの実装具合 • 解決策も論理設計上のドメインは利用されている? • 10.2.1中身はなんだろう • 挿入して良い状態(区分値)をテーブル検索して把握したい時がある? 24
    • 10章サーティワンフレーバー • 10.2.2 新しいフレーバーの追加 • 整数値の区分にしアプリケーションに責務を持たせたら? • ETL(Extract、Transform、Load) DWHなどで良く利用される • 10.5.3 廃止された値のサポート • 新規挿入からは新しい値を反映するが過去分の値は変更したく無い場合 • 10.5.4 移植が用意 • テーブルによる実装なのでどのRDBMSでも実装は容易 • 10.5.3のように値の有効、無効を追記した場合参照整合性は保てるが意図し たものからはずれる? 25
    • 11章ファントムファイル • アーキテクチャ上の都合 バッファキャッシュ(格納効率)、ネットワーク(memory - disk)RDBはオンメモリでは ない、RDBと直接CDNとの連携とか出来る? • イントロ • 画像ファイルの実態はファイルシステムで管理しパスをDBに保存し紐付ける • ファイルシステム上の画像はバックアップしない? -> DBと整合性の合うバックアップ方法は? • 11.2.1 ファイル削除時の問題 • パスの削除だけではファイルは残る • バッチによる定期的なクリーンアップ • 11.2.2 トランザクション分離の問題 • トレードオフとしてREDO、UNDOに画像データが乗るためオーバーヘッドが大きい • 11.2.3 ロールバック時における問題 • 11.2.2の問題を抱える。11.2.1のようにパスだけ削除し非同期でクリーンアップで対応できる 26
    • 11章ファントムファイル • 11.2.4 バックアップ • 画像データも含め一貫性のあるバックアップが必要なケースの場合DBに格納するべき • 一般的にはDB、ファイルシステムのバックアップは非同期でも問題のないシステムが多い • 11.2.5 SQLアクセスとファイルシステムのアクセスコントロール(ACL) • 11.2.6 パスの妥当性の確認 • アプリケーション側で不当なパスの場合のハンドリングをしてる? • 11.3 アンチパターン • リストア試験 DB、ファイルシステムのバックアップ不一致によるリストア後のサービス稼働の 確認 • 削除運用、DB&ファイルのACL、ファイルシステム上のファイルの変更(更新)&巻き戻し手段 • 「そのプロジェクトできんちんと検討されないまま、外部ファイルの使用が採用されている」 27
    • 11章ファントムファイル • 11.5 BLOBの採用 • BLOB https://dev.mysql.com/doc/refman/ 5.1/ja/blob.html • LOAD_FILE http://dev.mysql.com/doc/ refman/5.1/ja/load-data.html • DUMPFILE http://dev.mysql.com/doc/ refman/5.1-olh/ja/select.html 28
    • 12章インデックスショットガ ン • 12.1 パフォーマンスを最適化するとは? • システム(チューニング) マクロ、トップダウン • SQL(チューニング) ミクロ、ボトムアップ • 最適化の対象や指標は? • CPU利用率(+LA)、メモリ使用量(+ヒット率)、レスポンスタイム、スルー プット • インデックスはそのための1つの手段 • インデックスが適切に利用されたかをどのように判断する? • システム 稼働情報の確認 • SQL アクセスパスの確認 29
    • 12章インデックスショットガ ン • 12.2 アンチパターン • 適切なインデックスの張り方 • P132の解説 • インデックスの多寡が問題になる場合もあるが実際に使われるSQL (SELECT、INSERT、UPDATE、DELETE)を踏まえて考えるべき • 12.2.3 インデックスが役立たないとき • (last_name,first_name) -> order by first_name,last_name • where MONTH(date_reported) = 4 • なぜ上記はインデックスが役立たないか?改善策は? 30
    • 12章インデックスショットガ ン • P134 選択性(selectivity) • カーディナリティ(が高い=種類が多い) • ヒストグラム(データの分布状況) • MySQLではSQL実行時に都度ヒストグラムを取りアクセスパスを決定 • インデックスを理解しているか?(適材適所な利用をする) • B+treeが効果的なシチュエーションは? • index skip scan , index full scanと言われてピンとくる? • ビットマップインデックスが効果的なシチュエーションは? • その他インデックス(ハッシュ、ファンクション、全文) 31
    • 12章インデックスショットガ ン • 12.5 MENTOR • 12.1のパフォーマンスを最適化するとは?からある指標により行う • Measure(測定) • 観察の方がしっくりくる?(もしくはこの前に観察がある) • ピックアップ対象の指標は? • Explain(解析) • QEP : クエリ実行計画 • Nominate(指定) • インデックスを使用させる理由は?(オンライン処理 • カバーリングインデックス パフォーマンス対策の1つの手段 32
    • 12章インデックスショットガ ン • Test(テスト) • 評価軸や改善目標は?(レスポンスタイム、物理読み込み、論理読み込み、CPU時 間) • Optimize(最適化) • システム(サーバ、RDBMS)の最適化としてここでは使われている • Rebuild(再構築) • フラグメンテーション、不均衡(B+treeでは基本的には無い)の解消 • MySQL Optimize • Oracle ALTER INDEX Rebuild [online] • テーブルの再構築(再編成)もパフォーマンス改善になる 33
    • 13章フィア・オブ・ジ・アン ノウン • null、 空文字の扱い(mysql) • NULL 値の問題(日本語マニュアル) • http://dev.mysql.com/doc/refman/4.1/ja/problems-with-null.html • Problems with NULL Values(英語マニュアル) • http://dev.mysql.com/doc/refman/5.1/ja/problems-with-null.html • nullの扱い(oracle) • NULL とは(空文字をnullと扱う) • http://www.shift-the-oracle.com/element/null/ • wiki • http://ja.wikipedia.org/wiki/Null 34
    • 13章フィア・オブ・ジ・アン ノウン • イントロ • パイプによる連結 • SELECT first_name ¦¦ ' ' ¦¦ last_name AS full_name FROM Accounts; • concatによる連結(mysqlは主にこちらを使う) • SELECT concat(concat(first_name , ' '),last_name) AS full_name FROM Accounts; • mysqlでパイプを連結で利用する場合(セッションにて設定時) • set @@session.sql_mode = PIPES_AS_CONCAT ; • COALESCE • http://dev.mysql.com/doc/refman/5.1/ja/comparison-operators.html • http://docs.oracle.com/cd/E16338_01/server.112/b56299/functions030.htm 35
    • 13章フィア・オブ・ジ・アン ノウン • 13.1 NULL • 無(null)、不明(unknown)、適用不能(inapplicable) • 作成時点では不明な値 • 更新(update)により値を設定 • 13.2.1 式でNULLを扱う • select null + 10 ; • select 0 / null ; (0除算) • 13.2.2 NULLを許容する列の検索 • select * from Accounts where middle_initial = J.'; • select * from Accounts where NOT(middle_initial = J.'); • 13.2.4 NULLの使用を避ける • どのような問題があるか? 36
    • 13章フィア・オブ・ジ・アン ノウン • 13.4 今回のアンチパターンとは • NULLを一般値として利用したり、一般値をNULLに相当するものとして扱うこと • 13.5 3値理論 2値理論にNULLが追加 • そもそも2値理論とは(and,or,xor,not) • 論理「和」or • 論理「積」 and • スカラー式でのNULL • NULL = 0 (nullは0値かどうか不明の方が妥当) • NULL = NULL (不明な値と不明な値の「値」の比較は成り立たない) • NULL IS NULL (「不明」な値と「不明」な値は「同じ不明」なのでTRUE) • 論理式でのNULL 37
    • 13章フィア・オブ・ジ・アン ノウン • 13.5.3 NULLの検索 • <=> ,is distinct from • select * from Accounts where middle_initial is NULL; • select * from Accounts where middle_initial <=> NULL; • 13.5.4 NOT NULL制約 • いつNOT NULLを使う?(文字列の場合、数値の場合、その他) • データフローを踏まえてみる(更新時に値の登録等) • sql_mode、NULL、空文字 • 補足 有識者のNULLに対する考え方 • http://www.geocities.jp/mickindex/database/db_getout_null.html 38
    • 14章アンビギュアスグループ • 14.1 曖昧なグループ化 • SQL標準に則ったグループ化 • SELECT product_id, MAX(date_reported) AS latest FROM Bugs JOIN BugsProducts USING (bug_id) GROUP BY product_id; • 曖昧なグループ化(SQL標準に則っていない) • SELECT product_id, MAX(date_reported) AS latest,bug_id FROM Bugs JOIN BugsProducts USING (bug_id) GROUP BY product_id; • 14.2 アンチパターン • そもそもSQL標準から外れたSQLは記載しない 39
    • 14章アンビギュアスグループ • 14.2.1 単一値の原則 • 一般論(DataBaseSpecialistとかの解答)では • group by句を指定したSELECT文では、SELECTの後に指定する列には次のものだ けが可能である。 • グループ化対象化の列(group byの後に指定した列名)、集合関数、定数 • 14.2.2,14.3,14.4 • SQLを実行して確認する • 14.3 単一値の原則に反する • ONLY_FULL_GROUP_BY • http://dev.mysql.com/doc/refman/5.1-olh/ja/group-by-hidden-columns.html 40
    • 14章アンビギュアスグループ • 14.5.1 関数従属性 • 項目Xの値が決定すると、項目Yの値が一つに決定される • 14.5.2 相関サブクエリ • パフォーマンスに注意 • http://gihyo.jp/dev/serial/01/sql_academy2/000901 • 14.5.3 導出テーブル • 「ただし、データベースは導出テーブルの中間結果をテンポラリテーブルで格 納しなければならいため」 • パフォーマンス上、ボトルネックになる可能性がある 41
    • 14章アンビギュアスグループ • 14.5.4 JOIN(外部結合) • where xxx is nullにより外部結合にて存在しない行のみ取り出すテクニック • 14.5.5 集約関数の利用 • 単一値の原則に則っている(本来はこうあるべき)取り出したい結果セットに依存する • 14.5.6 group_concat • ジェイウォーク的な結果セットを返す • 結果セットを受けた側で区切り文字から値を抜き出す • 対象レコードを全て取るより冗長な部分(product_id、latest)が省かれるぐ らいのメリットしかない • http://dev.mysql.com/doc/refman/5.1/ja/group-by-functions.html 42
    • 15章ランダムセレクション • 15.1 目的:サンプル行をフェッチする • 「プログラミングにおける再現性と決定性の原則」 • 「直接データベースからクエリでサンプルを抽出する方が良い方法」 • 15.2 アンチパターン • ランダムにソートを行い、最初の行を取得する • 少量のデータに対してクエリを実行するときは特に目立ちません。 • 本番稼働後にデータベースのデータ量が増えていくにつれ、問題が現れ始める • 「インデックスとは本質的にある列の値を事前にソートした集合」 B+*treeインデッ クスの特徴 • 「ランダムソートのもう1つの弱点∼」 ソート以外の方法は?ランダム抽出 43
    • 15章ランダムセレクション • mysql rand() • select *,rand() from sort_a order by rand(); • select句のrand()とorder byのrand()は同値の可能性が高い • where句での評価 • select *,rand() from sort_a where rand() > 0.5 order by rand() desc; • where句とはselect句、order byとは同値とならない • 15.5.1 select ceil(rand() * (select max(id) from sort_a)); • キー値が連続の場合に有効 • 15.5.4 オフセット select * from sort limit 1 offset 10; • 15.5.5 ベンダー依存の解決策 • Oracle sample句、統計情報の取得 44
    • 16章プアマンズ・サーチエン ジン • 16.1 「比較の際には値全体が比較されます。」 RDBのおさらい。 • エンティティ(キーからレコードを導出)、リレーションシップ(正規化により抜き出したエンティティ間の繋がり) • キーから文字列「群」の導出。文字列からキーの導出、キーから文字列群の導出 • 16.2 どういう検索をしたいのか?  • 全文検索?(grep、索引(辞書+転置索引)、その他) • 一般的な英文(スペース区切り) = ジェイウォーク? • P183 転置索引の自作 • 代表的な全文検索 • full text index(mysql)、mroonga(mysql)、solr、Elasticsearch • 検索結果の出力順 • 文字コードによるソート、意図した価値によるランク、出現頻度、その他 • 結論と言うか。。。 like < full text < mroonga .. は 屋 45
    • 17章スパゲッティクエリ • デカルト積(直積) • ただしデカルト積が問題の本質じゃなく「取り出すデータ アクセスするデータ」のSQLを記述 することが大事 • 17.1 SQLのクエリ数を減らす(SELECT以外も含め) • メリット ネットワーク間のやりとりが減る • デメリット 意図しないアクセスパスになりパフォーマンスの問題が出る場合がある • MySQLの場合は相関サブクエリと解釈されるSQLは問題になりやすい • レプリケーション環境はレプリケーション遅延について考慮も必要 • 17.4 アンチパターンを用いるケース • ALL ROWSに最適化された製品 • DBの得意領域(データのソート) 46
    • 17章スパゲッティクエリ • 17.5 分割統治 • オプティマイザの判断に委ねるか人間の判断に委ねるか? • BI、DWH 分割しない方が良い場合がある(主にネステッドループ以外を利用する場合)。ALL Rows • OLTP(Online Transaction Processing)チューニングで分割統治する場合がある。FirstRows • 17.5.2 union • union ,union all • 17.5.3 case,sum • caseのメリット • All Rows(スループット),First Rows(レスポンスタイム) • SQLが長くなることを避け分割統治する意味はある?(次章のタイプを減らしたいで改めて考察) • 意味のない冗長なSQLは問題だが意図のある長いSQLは有効 47
    • 18章インプリシットカラム (暗黙の列) • イントロ エイリアス(別名) • カラム 疑似カラムや関数結果などにも、テーブル名 サブクエリなど • エイリアスのメリット(重複を区別する以外。パフォーマンス(昔は言われてた)) • 18.2.1 カラムの追加時 • insert時に明示的にカラム指定する場合と暗黙指定(明示的にカラム指定しない場合) • select時に同様 • 18.2.2 「多くのデータがアプリケーションとデータベースサーバ」 = ネットワークコスト • DISK(セクタ、キャッシュ) -> メモリ(ページ) -> ネットワーク(プロトコル由来) アーキテクチャ上での伝搬理解 • 18.5.1 ポカヨケ(4章に掛かってる理由はすることがオーバーヘッドにならないから) • http://ja.wikipedia.org/wiki/%E3%83%9D%E3%82%AB%E3%83%A8%E3%82%B1 • ワイルドカードについて • 行を取る、行をカウント(count(*))する場合に使うケース 48
    • 18章インプリシットカラム (暗黙の列) • 閑話(昔は正しいと思われていたとか的な) • http://otn.oracle.co.jp/forum/thread.jspa? threadID=28001914 • http://otn.oracle.co.jp/forum/ message.jspa?messageID=8056606 49
    • 19章リーダブルパスワード (読み取り可能パスワード) • 19.1 パスワードを忘れた場合メールを通じたパスワードの再設定 • 19.2 「権限のない人に特権的アクセスを与える」とは? • アクセスコントロール? • 19.2.1 「ネットワークの上で平文パスワードをやりとりするのは、なおさら危険です。」とは? • この場合のネットワークとは?(LAN、WAN、VPN、イントラ、インターネット、プロトコル (TCP/IP、SQL*NET)などなど) • パスワード以外の重要な情報(個人情報等)は平文で流通しても良い? • 19.2.1 「データベースサーバ上のSQLクエリログ」 • MySQL スローログ、クエリログ、バイナリログ(mysqlbinlogで整形可能) • 19.2.1 「バックアップファイル、またはバックアップメディア」 • データベースそのものの暗号化、メディアの暗号化 50
    • 19章リーダブルパスワード (読み取り可能パスワード) • 19.2.2 「2つの条件をひとまとめにしない」 • WHERE句にaccount_idとpasswordの2つを指定するのがNGな理由について • 19.3 アンチパターン「平文、または複合可能な暗号化」が必要な場合とは? • パスワードの特徴をトレーニングデータとした不正ユーザ検出(あり?なし?) • 19.4 本人識別と認証、認証と認可 • 徳丸本 これまで「認訓という用語をとくに説明なしに使ってきました。認証(Authentication)とは、 利用者が確 かに本人であることを芯んらかの手段で確認することを指します。Webアプリケーションで 用いられる 認証手段には、Basに認証のほか、HTMLフォームでIDとパスワードを入力させるフォーム 認証、SSLク ライアント証明書を用いるクライアント認証芯どがあります。認証と対になる用語に「認 可(Authorization)」があります。認可は、認証済みの利用者に権限を与えるこ とです。具体的には、デー タの参照・更新・削除や、預金の振り込み、物品の購入などを「できるように する」ことです。認証と 認可は画面上とくに区別されないので、混同しやすいですね。IDとパスワードを入力して認証さ れると、 即座に権限が与えられる場合がほとんどです。しかし、アプリケーション開発やセキュリティを 考える 上では、認証と認可をきちんと区別して理解し、別物として扱う習慣をつけましょう。認証と認可につ いては5.1節と5.3節で詳しく説明します。 51
    • 19章リーダブルパスワード (読み取り可能パスワード) • 19.5 ストレッチの回数 • SQLでは無理?(19.5.2 「MySQLではSHA2関数が使えます」) • select sha2(sha2(sha2(sha2(sha2(sha2(sha2( abcd ,256),256),256),256),256),256),256); • ソルトもconcatで付与出来そう • 19.5.1 MD5はパスワードハッシュ化に用いるべきではない • 19.5.3 「辞書攻撃」 • 19.5.4 「しかしパスワードは、SQL文の中ではまだ平文として使用されています。」 • SQLでハッシュ化しない動機となる • 19.5.5 「一時パスワードを電子メールで送る方法」 • 19.5.5 「電子メールに新しいパスワードを記載する代わりに、リクエストをデータベーステーブルに記録 し、一意のトークンを識別子として割り当てる」 52
    • 20章SQLインジェクション • これでFA? • 安全なSQLの呼び出し方 • http://www.ipa.go.jp/files/000017320.pdf • 間違いだらけのSQL識別子エスケープ • http://blog.tokumaru.org/2013/12/sql.html • Webアプリケーションとかの入門本みたいのを書く人への心から のお願い • http://d.hatena.ne.jp/ajiyoshi/20100409/1270809525 53
    • 20章SQLインジェクション • 20.5.1 入力のフィルタリング(=validation) • RDB的にはドメイン • 現状はAPPでvalidation、DBで型、有効桁、NOT NULL等の制約での対応 • 注釈にある通りSQLインジェクションの主となる対策ではないので注意 • 20.5.3 IN述語のパラメータ化 • SELECTしたkeyを用いたIN句は良く見かけるので重要 • ?を文字列連結し?の数分のarrayをPDOに送り込む • 20.5.5 コードレビュー • してますか? • してる場合どのように脆弱性を防いでいるか 54
    • 21章シュードキー・ニートフ リーク(疑似キー潔癖性) • 疑似キーとは?(= サロゲートキー) • 主にRDBMSの機能(何かしらの仕組み シーケンスジェネレータ)で生成される値を格納しPKとして扱う • Oracle sequence 、MySQL auto_increment • 21.1 欠番に問題はある? • 疑似キーの場合、有意キーの場合 • 疑似キー シーケンスジェネレータの仕様(キャッシュ破棄、ロールバック等) • 有意キー 実業務上の仕様(伝票の破棄等) • そもそも欠番に気付く? • 気付くものは番号の振り方そのものを見直す。(金融関係の伝票系など) • ユニーク、連番の関係(ユニークで連番、ユニークで非連番、非ユニークで連番、非ユニークで非連番) • Oracle sequenceだと細かく設定することができる。但しスタンドアロン、RACとノードの形態や機能要件を照 らしあわせ性能とのトレードオフを考慮し設定をする必要がある。 • http://docs.oracle.com/cd/E16338_01/server.112/b56299/statements_6015.htm 55
    • 21章シュードキー・ニートフ リーク(疑似キー潔癖性) • 21.2.1 欠番を求めるSQLに不備は無い? • 存在するレコードより小さい番号の欠番 • P237 「並行処理の問題が生じる」-> P39 コラム • select max(bug_id) + 1 from Bugs; • 問題点は? • 21.2.2 「主キー値の欠番を、すぐにでも埋めたい場合」ある? • 疑似キージェネレーター = シーケンスジェネレーター 56
    • 21章シュードキー・ニートフ リーク(疑似キー潔癖性) • 21.4 アンチパターン • 主キーを変更する状況とは? • 余談 パーティションテーブルで主キーを変更する場合、内部でどのような動作がおきるか? • 疑似キーの値それ自体が重要な意味を持つべきではない • 主キー列の値が何らかの意味を持つ場合とは? • 物流システムのテーブルで疑似キーをお問い合わせ番号にした場合 この場合は? • wiki 人口キーと自然キー • http://ja.wikipedia.org/wiki/主キー #.E4.BA.BA.E5.B7.A5.E3.82.AD.E3.83.BC.E3.81.A8.E8.87.AA.E7.84.B6.E3.82. AD.E3.83.BC 57
    • 21章シュードキー・ニートフ リーク(疑似キー潔癖性) • 21.5.2 GUID(UUID)MySQLの場合 select uuid(); • http://dev.mysql.com/doc/refman/5.1/ja/miscellaneous- functions.html • メリット「複数のデータベースサーバ間で、重複した値を生成するこ となく」 • shardingの際、PK利用に有効 • ただしMySQL innodbでは整数値のシーケンスがPKとして最適 • 注意点レプリケーション時 http://dev.mysql.com/doc/ refman/5.1/ja/replication-features-functions.html 58
    • 22章シー・ノー・エビル(臭 いものに蓋) • 適切に例外処理を入れる • 適切に戻り値の判定をいれる • 22.2.1 See-No-Evil/anti/no-check.php • 問題点は?①例外②戻り値③戻り値④戻り値 • 22.3 動的なSQL生成 • 22.5.1 ソース参照 • 例外、戻り値の判定 • 22.5.2 デバック時に実際に構築されたSQLクエリを使用する • DBセッションを追跡 • Oracle TKPROF • クエリログの収集 • http://dev.mysql.com/doc/refman/5.1/ja/query-log.html 59
    • 23章ディプロマティック・イ ミュニティ(外交特権) • イントロ 「安易な方法を選んだことで」。。技術的負債 • 文書やテストがなく。。。どちらかと言うと俗人化? • 23.1 ベストプラクティス • バージョン管理 • 新規から変更はALTER文を差分で抽出とCREATE文を作り管理(ER管理ツールで行い作りバージョン管理 する) • テスト • ドキュメント • 23.2 SQL(DDL、DML)を特別扱い してます? • データベース上に定義するDDLと定義後に格納されるデータ、格納されたデータを参照するDMLの違い(開発 と運用) • データベース管理者は「お客さん」 • 善し悪しは別として特権部分はある。(ERの部分のような破壊的な機能やACL周りなどを考慮すると) 60
    • 23章ディプロマティック・イ ミュニティ(外交特権) • 23.5.1 文書化 • してますか?正直面倒。頻繁に変わるため管理が大変 • ER図 • ObjectBrowserER • MySQL workbench • DBオブジェクト管理(テーブル、列、ビュー、リレーションシッ プ、ストアド、トリガー、セキュリティ、インフラ) • どう管理していますか?中々大変 61
    • 23章ディプロマティック・イ ミュニティ(外交特権) • 23.5.2 バージョン管理 • 巻き戻し方 • 直進のみの性質 • 定義とデータは別 • 23.5.3 テスト • してます? • テスト対象となるコードは過去とリリース分のDDL? • データ件数に依存はある?(例 マスタ) • 死活監視では簡易テストのようなスクリプトは良く使います • 23.5.4 複数のブランチを扱う 62
    • 24章マジックビーンズ(魔法 の豆) • DDD?(ドメイン駆動設計?) • 24.2 • CRUD(Create,Read,Update,Delete) • 24.2.4 モデルのテスト • 24.3 • DRYの原則(Don t Repeat Yourself:同じ事を繰り返さ ない) 63
    • 25章砂の城 • 25.1 24時間365日、停止時間を極限まで抑える • 稼働率 例 AWS 99.9%(年間8時間46分) 高可用性により実現 • http://ja.wikipedia.org/wiki/可用性 • 25.2 想定する(サービスレベルの障害、局所(機能)レベルの障害)、対応する • キャパシティ • Disk容量、CPU、コネクション、etc • 情報を採取する • 日々観測し予測、施策を講じる • 但し情報採取がボトルネックになることもある • SPOF(単一障害点) 64
    • 25章砂の城 • 25.3 アンチパターン 想定外の発生 • データサイズが想定以上に増えるとどういう問題が発生するか? • 想定内ならどういう対処をしているか? • 25.4 アンチパターンを用いてもよい場合 • スタートアップ、スモールスタート • ステージ毎のアーキテクチャの見直し • 規模が大きくない時点で大規模サイトの真似をしても良いこと はありません 65
    • 25章砂の城 • 25.5 解決策 • 25.5.5 高可用性(High Availability) • システム継続 • 冗長化(HA 現用、待機 現用、現用)、HAサーバ、RAID(ミラーリング)、N/W冗長構成 • 25.5.1 ベンチマーク(予め行うもの) • どういう情報を取ってどう判断しています? • トラフィック、データ量 • シナリオ試験(ロードジェネレータ) • 25.5.2 テスト環境 • 本番と同等(スペックだけでなくデータ等も)だと良いが全てを同等にするのは難しい • 25.5.6 ディザスタリカバリ • 最近ではBCP(事業継続計画)の一部として検討される 66
    • 25章砂の城 • 25.5.7 運用ポリシー • 以下について予めどのような対応をするか策定(事前に検討?) する • 高可用の限界を超えた障害 • 「ぴんぽん」現用待機の切り替えの繰り返し • 問題の調査 • 再現は困難な場合が多い • 性能の劣化 67
    • 付録A 正規化 • A.1 リレーショナルとは何か • リレーションとリレーションシップの違い • A.2 正規化の神話 • 正規化はデータベースを遅くする • 適切なSQL、INDEX設計をしていれば遅くならない • 疑似キーを用いて参照すること • 空間効率を考慮した際に採用される 68
    • 付録A 正規化 • A.3 正規化とは • 正規化のルールを満たしたものを正規形と呼ぶ • 情報無損失分解 • 分解後に分解前の関係に復元出来る分解(可逆的) • A.3.1 第一正規形 • 繰り返しグループがないこと • A.3.2 第二正規形 • 関数従属性の抜き出し(キー) • A.3.3 第三正規形 • 推移従属性の抜き出し(非キー) 69