ユーザーが投稿したりブログを書いたりする小さなプログラムを作っています。これらの投稿では、他のユーザーがFacebookのように投稿を高く評価したり、低く評価したり、Stackoverflowのように投稿に賛成または反対票を投じたりできます。一般的に使用されている適切なデータベース構造を知りたいのですが、プログラムはその構造で効率的に機能します。 2つのオプションがあります
最初
役職:
id head message datepost likes dislikes
1 ab anchdg DATE 1,2,3 7,55,44,3
上記のように、id
はpostidです。 「いいね」列の1,2,3
は、投稿またはブログを高く評価または賛成したユーザーのIDです。 7,55,44,3
は、投稿またはブログを低評価または反対票を投じたユーザーのIDです。
2番目
役職:
id head message datepost
1 ab anchdg DATE
いいね:
id postid userid
1 1 1
2 2 2
嫌い:
id postid userid
1 1 7
2 1 55
このように、いいねと嫌いの2つの別々のテーブルを作成して、投稿のいいねを取得する必要があります。このようにして、テーブル、つまりLikes
&Dislikes
は非常にいっぱいになります。これにより、テーブルが重くなり、処理が遅くなる場合があります。
それで、私はこのタスクを達成するためのより良い標準的な方法がどれであるか知りたいですか?
直面する問題は、データベースの「通常の形式」、特に最初の通常の形式として知られています。 https://en.wikipedia.org/wiki/First_normal_form 。
連結されたユーザーID(最初のバージョン)を持つデータベースは、最初の通常の形式ではありません。
正規化が一般的に良いと見なされる理由と方法については、 https://en.wikipedia.org/wiki/Database_normalization を参照してください。
最初の例では、「ユーザー4は投稿を好きではなくなった」というクエリが複雑になります。副作用とコーナーケースを考慮する必要がある文字列操作を実行する必要があります(ユーザーは唯一の「好きな」ユーザー、ユーザーは最後の好きなユーザー、ユーザーは好きなユーザー文字列の真ん中にいます)。これは悪いと思います。しないでください。正規化されたデザインを使用します。
re:データベースが重くなる
400万件のいいねを含む投稿がある場合、データベース設計1では、「いいね」列が少なくとも400万文字幅の行が1つあります(区切り文字としてカンマが必要になるため)。次に、400万桁の幅の文字列に対して文字列操作を実行する必要があります。これは非常にパフォーマンスが低く、遅いです。
一方、データベースは数百万行を処理するように設計されています。数億行のデータベースがあり、count()操作は高速です。非常に速い。したがって、これはパフォーマンスのボトルネックにはなりません。
次の問題は、可読性と保守性です。
たとえば、次の2つのステートメントの機能を教えてください。
select count(*)
from posts
inner join likes on posts.postid = likes.postid
where postid = 7
select len(likes) - len(replace(likes, ',', ''))
from posts
where postid = 7
2番目の方法は、高評価/低評価を簡単に追加または削除できるため、はるかに優れています。
ただし、好きか嫌いかを表す1つのテーブルを使用して、2番目のソリューションを変更する必要があります。
高評価/低評価テーブルの列は、id、postid、userid、および高評価または低評価の値の別の列である必要があります。嫌いの場合は1、嫌いの場合は-1。
Post_idとuser_idを複合主キーとして設定すると、正常に機能します。
テーブルのサイズは時間とともに大きくなります。しかし、実際の列は2つしかありません。いいね/嫌いのIDと値。 postidとuseridはそれにのみリンクされ、ユーザーおよび投稿テーブルに保存されます。