質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

2回答

1563閲覧

イイねの対象が複数存在する場合のテーブル設計について

退会済みユーザー

退会済みユーザー

総合スコア0

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

1クリップ

投稿2018/12/19 18:10

編集2018/12/20 07:25

イイねの対象が複数存在する場合のテーブル設計について相談できる人がまわりにいないので困っています。

例えばmediumdev.toでは「投稿」と「投稿についたコメント」に対してイイねができます。
ユーザーは投稿/コメントについたイイね数が確認できるのはもちろんのこと、自分がイイねした投稿やコメントはマイページで確認できます。
今回の要件(やりたいこと)はこちらと同じようなことになります。

その要件を実現するために、自分なりにテーブル設計をしてみましたが、以下の懸念点が出てきました。

  • likesテーブルで外部キーがusersにしかはれない
  • データ量が膨大に膨れ上がりそうな予感

こういったケースの場合どういった設計にするべき(するのが良い)でしょうか?
何か少しでもアドバイスいただけると幸いです。

関連テーブルの構造イメージ
CREATE TABLE `users` ( `id` varchar(255), `name` varchar(255), PRIMARY KEY (`id`) ) CREATE TABLE `posts` ( `id` varchar(255), `title` varchar(255), `content` varchar(255), `author_id` varchar(255), PRIMARY KEY (`id`), FOREIGN KEY (`author_id`) REFERENCES `users` (`id`) ) CREATE TABLE `comments` ( `id` varchar(255), `post_id` varchar(255), `author_id` varchar(255), `content` varchar(255), PRIMARY KEY (`id`), FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`), FOREIGN KEY (`author_id`) REFERENCES `users` (`id`) ) CREATE TABLE `likes` ( `id` varchar(255), `object_type` varchar(255), `object_id` varchar(255), `user_id` varchar(255), PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) )
likesテーブルの中身イメージ
IDユーザーIDオブジェクトタイプ(テーブル名)オブジェクトID(レコードID)※説明用
1user1postspost1user1がpost1に対してイイね
2user2postspost9user2がpost9に対してイイね
3user1commentscomment1user1がcomment1に対してイイね
4user1commentscomment5user1がcomment5に対してイイね
5user1commentscomment13user1がcomment13に対してイイね
補足追記
  • 将来的に、投稿人物(users)に対してイイね機能を追加したり、投稿写真(photos)に対してイイね機能を追加したりと、イイねの対象が増える可能性があります。
  • RDBMS(MySQL5.7を利用想定)を前提に考えております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

likesテーブルで外部キーがusersにしかはれない

異なるテーブルを一元で管理する以上必ずそうなります。
仮に管理テーブルを用意して一意なIDを払い出すようにすると、likesテーブルからその管理テーブルに対しては、外部キーが設定できますが、管理テーブルには外部キーは設定できないのですから。

根本にあるのはテーブルが別ということです。
postcommentは主にテキストを扱うのですからこれをpostcommentの識別を持たせ一つのテーブルに纏めると、likesテーブルに外部キーが設定できることになります。

データ量が膨大に膨れ上がりそうな予感

正規化に照らすとそうなってしまうものは当然あります。
そのような場合に正規化を緩める方法として、配列などに折りたたむ方法があります。
配列の扱いとしてはjson形式であったりカンマ区切りの文字列だったり、純粋な配列だったり、DBMSのサポートする機能に依存します。
配列とする事のメリットとしては、別テーブルとした場合の結合コストやキー部分の容量を削減できる事がありますが、デメリットとしては、検索や更新が簡潔なSQLとはならない点です。

特に検索について、全行から検索するような要件がある場合は、最低限、(配列を含めて)その型に対する検索機能を有したRDBMSである事が選定条件になるでしょう。

尤も、RDBMSではなくNoSQLという選択なら上記のようなことは無い訳ですが。

投稿2018/12/20 02:53

編集2018/12/20 07:56
sazi

総合スコア25184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/20 07:30 編集

ご回答有り難うございます。 > 根本にあるのはテーブルが別ということです。 なるほどです。 ただ、投稿人物(users)に対してイイね機能を追加したり、投稿写真(photos)に対してイイね機能を追加したりと、イイねの対象が増える可能性が現実的にあります。 そういった将来的な拡張性を考慮すると別テーブルにしておいたほうが良いかと思いました。 そうなると以下の二択だと考えました。 1. 私が考えた設計をベースとして、saziさんの仰る「配列などに折りたたむ方法」を検討する 2. イイねの対象(users, photos)が増えるたびに中間テーブルを増やす(例:user_likes, photo_likes...) saziさん(ベテランの方)なら、こういった問題にどういった判断基準で1 or 2を選定されるのですか? または3や4...といった他の選択(上記以外の設計)をされるのでしょうか? > 尤も、RDBMSではなくNoSQLという選択なら上記のようなことは無い訳ですが。 こちらはすみませんがRDBMS前提でお願いいたしますm__m
sazi

2018/12/20 07:54 編集

1と2は判断基準が別物です。 1は第2正規化を緩める事ですし、2はエンティティの分割の話です。 1にについては既に経験があり、配列にする事で性能と容量を改善する事ができました。 但し、配列の扱いが得意なpostgresで、SQLのチューニング(配列を展開して検索するなど)を行った上で実現したものですけど。 2についても保守を不要とする汎用的な扱いを行うために実装したことはあります。 予めオブジェクトの種類ごとのパーティションにしておけば、性能的には物理テーブルを分けるのと変わりません。※postgresは実質物理的には別テーブルで構成される。 但し、共通化するために、逆にイレギュラーな部分を分割するというのは考慮ておいた方が良いですけど。
guest

0

ちょっと状況がわからないですが、イイねをするのが文章に対してですから
その文書のdocumentidと自分のuseridを紐付ける中間テーブルがあればいいのでは?
子文書をイイねすると親文書もマイページで閲覧したいなら、子文書に
親文書のdocumentidを属性として持たせることです

投稿2018/12/20 00:30

yambejp

総合スコア114814

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/20 07:27

ご回答有り難うございます。 > イイねをするのが文章に対してですからその文書のdocumentidと自分のuseridを紐付ける中間テーブルがあればいいのでは? 理解不足で申し訳ないですが、postsテーブルとcommentsテーブルを1つにして(わけずに)documentsテーブルみたいなものを1つ用意して、そのテーブルとusersテーブルの中間テーブルを作成するという設計でしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問