# 2021/05/09 メンター相談 ###### tags: `メンター相談`,`5月` ## 従属テーブルの使い道について - 1対多の関係を扱う時に使う (かつ、個数の上限がないような場合) - 交差テーブルと従属テーブルどちらを採用するか? - 子を共有したい場合は、交差テーブルを使用する - 例: GitHubのTagの場合は、他にも利用されるので交差テーブルを採用する - 子を共有したくない場合は、従属テーブルを使用する - このタグはこのポストのものです!としたい場合 - 例: twitterのハッシュタグなど - (あるツイートのハッシュタグの変更を、他のツイートの同名ハッシュタグに反映させたくない) - 書籍としては、一つに複数リソースが紐づく関係の場合は1対多テーブルを使おうね、ということを言いたいのではないか - コンセプトは2つ - 1. カラムを増やして対応するのではなく、行を増やすことで対応しよう!ということ (これが1番大事) - 2. content, post_id を複合主キーとしよう ## 小説/漫画の交差テーブルの命名について テーブル名: Add_Comment_To_Manga - 長いとは思わなかった - 交差テーブルはイベントテーブルになることが多い - テーブルは主にresource, event の2種類に分けられる - 今回は、eventに該当すると思う - event の場合動詞で命名するので、`Add_Comment...` は良い命名だと思いました - `event` か `resource` かは日時をカラムに入れた時、自然かどうかで判断できる - 自然 -> イベントテーブル - 例) コメントした日 (自然) - 不自然 -> リソース - 例) 漫画した日 (不自然) - MangaComment とする人もおり、議論が分かれるところではある - テーブル名にアンスコは良く使う? - 良くみる - ORMによって変わるので、それに合わせる場合が多い - Prismaは、パスカルケース - TypeORMは、小文字+アンダースコア (大文字小文字のバグを防ぎたいという思想か?) ## ポリモーフィック関連の解決策について 詳しくは、表を参照 (松原さん作) ![polymorphic1](https://i.imgur.com/u2tYuQ4.png) ![polymorphic2](https://i.imgur.com/KDYy01T.png) - ユースケースにより異なる - 1. 別テーブル - 対象をまとめて扱うことがない場合 - あまり使ったことは無い - コメントとしてまとめて扱いたい時に不便なので - 特定の文字列をもつコメントを検索したい時、不便 (件数の制限がある場合、UNION+全件取得が必要) - コメントをまとめて取得した時に、漫画/小説どちらのコメントか判断できない - SQLアンチパターンのメタデータトリブル に該当する??? - 2. テーブル継承 - bookがmangaなのかnovelなのか判断が必要 - left outer join で結合してNull判断する必要がある - bookを必ずつくらなければいけない - なので、基底テーブルにはなるべく属性を持たせないようにしたい - そもそも、NovelとMangaは同じ継承関係だろうか?ということをユースケースで考えなければいけない - 「複数の交差テーブル」でも同様 - DBで一度作った継承関係を直すのは複雑(重要!!!!!) - 3. 複数の交差テーブル - 考えたユースケースでは、困る点はなかった - 強いてあげるなら、交差テーブルに時系列データがあり、ソートしたい場合に不便 (全件取得が必要になる) - → Commentにも重複して時系列情報を持たせることで解決できる - 結論 - まとめて扱わない・別のもの の場合 -> 単一テーブル継承 - まとめて扱う - 継承元が Book -> クラステーブル継承 - 継承元が Comment -> 複数の交差テーブル - 今回の場合、Commentを継承元とする方が良いと感じた - 今はmangaとnovelは同じだけど、将来別物になりそう、という気持ちから Commentを継承元にしたい - 複数のコメントテーブルは、コメント同士が交わるユースケースがない場合に良い ## クラステーブル継承を使うメリット、使う場面とはどのような場面でしょうか? - 継承関係をどうRDBで表現するかには3種類ある - [Catalog of Patterns of Enterprise Application Architecture](https://www.martinfowler.com/eaaCatalog/index.html)から生まれた概念 - 具象テーブル継承 - 継承元が存在しない、継承先で重複して持つ - 単一テーブル継承 - 一番シンプル - 全て一つのテーブルにまとめる (null許容) - クラステーブル継承 - 継承元テーブルに持つ - 参考: https://qiita.com/yebihara/items/9ecb838893ad99be0561#3%E3%81%A4%E3%81%AE%E7%B6%99%E6%89%BFor%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3 - どのような場面で使用するか - 基本は単一から考え始める - Nullが発生してしまう - nullを許容したくない場合、残りの2つ - クラステーブル継承にすると、必ずJOINが発生する - 属性の重複を排除したい時 - データ数が少ない、パフォーマンスが重要ではない場合に使う - あまりJOINしたくない場合は、具象テーブル継承を選択する - 共通項目が複数テーブルをまたいでしまう - 属性の重複を排除できない - 実際には、具象とクラスを混ぜて使うことが多い - codeは重複させたくないので、継承元に持たせたい - nameは重複してもよいので、継承先に持たせたい - Q. 基底テーブルに共通化する項目は、重複させたいかさせたくないかで判断する? - A. Yes - Q. まとめて検索したい時、基底テーブルにまとまっていると便利なのでは? - A. 両方に持っても良い - nameでたくさん検索するユースケースがある -> nameを両方に持たせる ## DBへの同時実行数が多いシステムで性能を向上させるために、デッドロック検知機能を無効化することはありますか? - 無効にしたことがなかった - そこまで大きなサービスに携わったことがない。 - そもそもデッドロック自体がほとんど起きない - そもそも、検知がONになっていると、なぜ遅くなるのか? - (shimokawa-san) deadlock detectionの章に書いてあった - (matsubara-san)一番小さいトランザクションをロールバックする らしい - ->判断するので遅くなる? - ロック待ちが無限に積み重なってしまう? ## CHECK制約とアプリケーション側の制約をどのように使い分けていますか? - 基本はアプリケーションで制約をもたせるのがよい - DBに持たせる制約は、基本的に以下の3つのみ - UNIQUE - NOT NULL - テーブル定義の際に必要な型と長さ: varchar(20)等 - 理由 - 制約がどこに書かれているかを見つけづらい - アプリケーションで制約を変更した時、DBへの反映し忘れが起こる - 責務を分けるため (DBは保存にのみ集中する) - 制約に対するテストを書きづらい - RDBMSごとに仕様が異なるため ## 交差テーブルの導入時に複合主キーとサロゲートキーを主キーに設定する場合の2パターンのテーブル定義がある場合、どのように使い分ければいいでしょうか - 複合主キーにすることが多い、あえて代理キーを作ることはない - 代理キー、ナチュラルキー どちらを使うか? - 制約条件が今後も続くかどうかで決める - 複合キーが複雑になると、JOINするとき書きづらい -> 代理キー - 実務で観測した範囲は、複合キー2つまで - 無理にサロゲートキーを貼る必要はない - 外部キーは意味をもたないものにすべき - 意味を持たないもの:product_id - 意味を持つもの:product_code - 松原さんは、とりあえず代理キー貼る派 - ミスを防ぐため ## 「データベースにおけるNULLの扱い」で出題したクイズに関して、想定回答がペアの間で異なりましたが、どちらにどのような利点があるのか - 交差テーブルを複数作る - こちらのほうが良さそう - like数の集計が少し面倒だが、likesテーブルを作ることで解決できる - ![](https://i.imgur.com/DFQfVz9.png) - like_targetで分ける - アンチパターン: マルチカラムアトリビュートに近い - target_id は、 `post.id` , `comment.id` の2つに紐づくため外部キーが貼れなくなる。参照整合性もなくなる。 - アプリケーションが考慮しなければいけないところが増える - 例: post or commentをJOINしてからアプリケーション側で判断しなければいけない - likes と likes_target まとめて一つのテーブルにしても良さそう ## Instagramで、いいねを押した際のAPIの解釈について - web/likes/1/like - web/comments/like/ - わからない - 昔は、投稿に対するいいねしかなかった? - APIのパスは自由に決められるので、想像がつかない