私はソフトウェア開発者です。私はコーディングが好きですが、データベースは嫌いです...現在、ユーザーがエンティティをliked(FBのように)としてマークできるWebサイトを作成しています、tagitおよびcomment。
この機能を処理するためのデータベーステーブルの設計にこだわっています。 1種類の物(写真など)に対してのみこれを行うことができる場合、解決策は簡単です。ただし、これを5つの異なるものに対して有効にする必要があります(現時点では、サービス全体が拡大するにつれて、この数も増えると想定しています)。
ここで似たような質問をいくつか見つけましたが、満足のいく答えがないので、もう一度この質問をしています。
問題は、適切に効率的におよび弾性的にデータベースを設計し、異なるtables、likes異なるtablesおよびtags 彼らのために。答えとしてのいくつかのデザインパターンが最適です;)
詳細な説明:tableUser
といくつかのユーザーデータ、さらに3つのtables:Photo
withphotographs、Articles
witharticles、Places
with場所。ログに記録されたユーザーに次のことを許可したい:
これら3つのテーブルのいずれかにコメントする
気に入ったものとしてマークする
それらのいずれかに何らかのタグを付けます
また、すべての要素のいいねの数と、特定のタグが使用された回数もカウントします。
1st アプローチ:
a)tagsの場合、tableTag [TagId, tagName, tagCounter]
を作成してから、多対多関係tables:Photo_has_tags
、Place_has_tag
、Article_has_tag
。
b)コメントについても同様です。
c)tableLikedPhotos [idUser, idPhoto]
、LikedArticles[idUser, idArticle]
、LikedPlace [idUser, idPlace]
を作成します。 likesの数はqueries(これは悪いと思います)によって計算されます。そして...
私は最後の部分でこのデザインが本当に好きではありません、それは私にとってひどく臭いです;)
2nd アプローチ:
管理者(私)にtablesの名前を入力するテーブルElementType [idType, TypeName == some table name]
を作成しますliked、コメント付きまたはタグ付き。次に、テーブルを作成します:
a)LikedElement [idLike, idUser, idElementType, idLikedElement]
およびコメントとタグについても同じで、それぞれに適切な列があります。今、私が好きな写真を作りたいとき、私は挿入します:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)
そして場所のために:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)
など... 2番目のアプローチの方が良いと思いますが、このデザインにも何かが欠けているように感じます...
最後に、その要素が何回好かれたのか、カウンターを保管するのに最適な場所はどれかと思います。次の2つの方法しか考えられません。
Photo/Article/Place
)テーブル内私はこの問題についての私の説明が今より完全であることを望んでいます。
最も拡張可能なソリューションは、1つの「ベース」テーブル(「いいね」、タグ、コメントに接続)のみを持ち、それから他のすべてのテーブルを「継承」することです。新しい種類のエンティティを追加するには、新しい「継承された」テーブルを追加するだけで済みます。これにより、like/tag/comment機構全体に自動的にプラグインされます。
このためのエンティティ関係の用語は「カテゴリ」です( ERwinメソッドガイド 、セクション:「サブタイプの関係」を参照)。カテゴリシンボルは次のとおりです。
ユーザーが複数のエンティティを好む場合、同じタグを複数のエンティティに使用できますが、コメントはエンティティ固有であるため、モデルは次のようになります。
ところで、「ERカテゴリ」を実装するには、おおよそ3つの方法があります。
非常に厳しいパフォーマンス要件がない限り、おそらく3番目のアプローチが最適です(つまり、物理テーブルは上の図のエンティティと1:1で一致します)。
データベースが「嫌い」なのに、なぜそれを実装しようとしているのですか?代わりに、このようなものを愛し、呼吸する人に助けを求めてください。
そうでなければ、データベースを愛することを学ぶ。適切に設計されたデータベースは、プログラミングを簡素化し、サイトのエンジニアリングを行い、継続的な運用を円滑にします。経験豊富なd/b設計者でさえ、完全で完全な先見の明はありません。使用パターンの出現や要件の変更に伴い、今後のスキーマの変更が必要になります。
これが1人のプロジェクトである場合は、add_user、update_user、add_comment、add_like、upload_photo、list_commentsなどのストアドプロシージャを使用して、データベースインターフェイスを単純な操作にプログラムします。1行のコードにもスキーマを埋め込まないでください。この方法で、コードに影響を与えずにデータベーススキーマを変更できます。スキーマについては、ストアドプロシージャのみが知っている必要があります。
スキーマを数回リファクタリングする必要がある場合があります。これは正常です。初めて完璧になることを心配しないでください。初期設計のプロトタイプを作成するのに十分なだけ機能的にします。時間に余裕がある場合は、ある程度使用してから、スキーマを削除してからもう一度実行してください。 2回目はalwaysより良いです。
これは一般的な考え方です。フィールド名のスタイル設定にはあまり注意を払わずに、関係と構造に注意してください。
この擬似コードは、ID 5の写真のすべてのコメントを取得します
SELECT * FROMアクション
Whereアクション.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"
この擬似コードは、ID 5の写真が好きなすべてのいいね!またはユーザーを取得します
(count()を使用して、いいね!の数を取得できます)
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff="photo"
AND actions.typeAction = "like"
私が理解する限りでは。いくつかのテーブルが必要です。それらの間には多対多の関係があります。
必要になるアクセスパターンを見てください。それらのいずれかが、設計の選択のどちらか一方を特に困難または非効率にしているように見えますか?
より少ないテーブルを必要とするものを好まない場合
この場合:
あなたの「差別的な」アプローチ、オプション2は、いくつかのケースではより単純なクエリを生成し、他のケースではそれほど悪くはないと思うので、私はそれで行くと思います。
1つのテーブルがあり、各行の要素タイプを格納する2番目のアプローチを使用することは間違いありません。これにより、柔軟性が大幅に向上します。基本的に、より少ないテーブルで何かを論理的に行うことができる場合、ほとんどの場合、より少ないテーブルで行く方が良いです。あなたの特定のケースについて今思い浮かぶ1つの利点は、特定のユーザーの好きな要素をすべて削除することを検討してください。最初のアプローチでは要素タイプごとに1つのクエリを発行する必要がありますが、2番目のアプローチではそれを行うことができますクエリを1つだけ使用するか、新しい要素タイプを追加するタイミングを検討します。最初のアプローチでは新しいタイプごとに新しいテーブルを作成しますが、2番目のアプローチでは何もしないでください...