投稿への高評価または投票


10

ユーザーが投稿したりブログを書いたりする小さなプログラムを作っています。これらの投稿では、他のユーザーが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です。

二番目

役職:

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つの個別のテーブルを作成する必要があります。このようにして、テーブル、つまりLikesDislikesは非常にいっぱいになります。これにより、テーブルが重くなり、処理が遅くなる場合があります。

それで、私はこのタスクを達成するためのより良い標準的な方法がどれであるか知りたいですか?


4
ユーザーが投稿高く評価したり低くしたりできない思いますか?もしそうなら、私は好きなものと嫌いなもののための1つのテーブルを持ち、BIT列があります(好きなものは1、嫌いなものは0)。
dwjv 2016

1
または、1と-1でより簡単な合計
jkavalik '19

1
@dwjv最初の例では、ユーザ3は、実際には、両方が気に入ったポストを嫌い。
Dan Henderson

回答:


20

直面する問題は、データベースの「通常の形式」、特に最初の通常の形式として知られています。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

先に述べたように、テーブルに数百万ものいいねが存在する場合、テーブルは重くなりませんか?テーブルが非常に速くいっぱいになるので、レコードの数十万のテーブルを検索するのに時間がかかりませんか?
Harshit Shrivastava 2016

6
@HarshitShrivastava mysqlは10億行の単純なテーブルを処理できますが、これらの10億(dis)のいいね!をユーザーのテーブル内の文字列として想像してみてください。
jkavalik 2016

3
@til_bが直接言及しないことの1つ(ただし、通常は通常のフォームの使用を通じて暗示される)は、適切に実装された2番目の設計により、基礎となるデータベースエンジンが最初の設計パターンでは実行できない参照整合性を維持できるようになることです。つまり、ユーザー4が削除された場合、データベースはリンクされたデータを消去します。これは、ユーザー4のレコードに依存するレコードがわかっているためです。データベースは文字列内の関係を管理する方法を直感的に知らないため、最初の設計ではこれを行うことができません。
David Antaramian 2016

9

2番目の方法は、高評価/低評価を簡単に追加または削除できるため、はるかに優れています。

ただし、好きか嫌いかを表す1つのテーブルを使用して、2番目のソリューションを変更する必要があります。
いいね/嫌いのテーブルの列は、id、postid、userid、およびlikeまたはdislikeの値の別の列(たとえば、1は嫌い、-1は好き)である必要があります。

post_idとuser_idを複合主キーとして設定すると、正常に機能します。

テーブルのサイズは時間とともに大きくなります。しかし、実際の列は2つしかありません。いいね/嫌いのIDと値。postidとuseridはそれにのみリンクされ、ユーザーと投稿のテーブルに保存されます。


3
あなたは持っているべきuser_idpost_idありvalue、テーブルにあります。別のidカラムは必要ありません。
jkavalik 2016

3
質問に対する@jkavalikのコメントが示唆しているように、1と-1は、1と2よりも、likeとdislikeの方がおそらくより良い値になるでしょう。 「1」の行数から「2」の行。
Dan Henderson、

@DanHenderson:いいねのようなもの-嫌いは合計よりもかなり速い可能性があります。(ただし、1と-1でも機能します。)
cHao

賛成ですが、愛と怒りのようなさらに2つのアクションを言ったとしたら、どうしますか。2つのアクションが
追加された「いいね」の

あなたがしたくない場合はsum何も、あなたは愛= 2と怒り= 3に設定することができます
ジュリアンS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.