6

MySQLのinnoDBテーブルには、マイクロブログの投稿とそれに関連する投票/顔文字があります。2種類のページの要件があります。

(A)1ページ(たとえば25)の投票数/顔文字数とともに多くのマイクロブログを含むリストページ。

例えば

素晴らしい面白い投稿

面白い投稿を意図した、それほど面白いコンテンツではありません。Lorem ipsum dolorは、amet、consecteturadipiscingelitに座ります。Phaselluseuismodはpellentesqueを意味します。.....続きを読む....

(3)いいね、(5)退屈、(7)笑顔

。+同じページにさらに24件の投稿。

(B)詳細な投票+投票数/絵文字を含む単一のマイクロブログを含むパーマリンクページ。

素晴らしい面白い投稿

面白い投稿を意図した、それほど面白いコンテンツではありません。Lorem ipsum dolorは、amet、consecteturadipiscingelitに座ります。Phaselluseuismodはpellentesqueを意味します。Quisque viverraadipiscingauctor。Mauris ut diam risus、fermentumelitで。Aliquam urna lectus、egestas sit amet cursus et、auctorutelit。Nulla tempus suscipit nisi、nec condimentum duifermentumnon。eget lacus miでは、utplaceratnisi。

(あなた、ダープともう1人はこのように)、(5)退屈(7)微笑んだ

最初のアプローチ:

表1:

post_id | post_content | post_title | creation_time 

投票、いいね、絵文字を保存するための表#2:

action_id | post_id | action_type | action_creator | creation_time

投稿のページ、または単一の投稿を表示します。最初のテーブルは投稿を取得するためにクエリされ、2番目のテーブルは投稿に関連するすべてのアクションを取得するためにクエリされます。投票などが行われるたびに、テーブルに挿入が行われpost_actionsます。

2番目のアプローチ:

表1:

post_id | post_content | post_title | creation_time | action_data 

どこaction_dataにあるのか{ "likes" : 3,"smiles":4 ...}

表#2:

action_id | post_id | action_type | action_creator | creation_time

投稿のページを表示するには、最初のテーブルのみをクエリして投稿とアクションデータを取得し、個々の投稿を詳細なアクションとともに表示するには、2番目のテーブルをクエリして投稿に関連するすべてのアクションを取得します。投票などが行われるたびに、テーブルに挿入が行われ、post_actionsテーブル#1のaction_dataフィールドが更新されて、更新されたカウントが格納されます。

10万件の投稿があり、10倍のアクション、つまり100万以上のアクションが作成されたと仮定します。アプローチ#2にはメリットがありますか?JSON情報を読み取り、変更し、更新する必要があること以外に、それの欠点はありますか?とにかく、アプローチ#2に従い、さらに改善できる方法はありますか?

フィードバックに基づいてさらに情報を追加する:

  1. Pythonスクリプトは、データの読み取りと書き込みを行います。
  2. MySQLDBサーバーはWebサーバーとは異なります。
  3. 投稿作成による書き込みは、1日あたり10000と低くなっています。ただし、アクションによるものはもっと高くなる可能性があります。投票、いいね、絵文字などのアクションにより、1秒あたり最大50回の書き込みを想定します。
  4. 私の懸念は、2番目のアプローチの両方と落とし穴の読み取り/書き込みパフォーマンスの比較と、将来的に不足する可能性がある場所についてです。
4

4 に答える 4

7

すべてのいいね/投票データ(集約およびアトミック)をテーブル1内に格納し、テーブル2を完全に破棄するか、構文、巧妙JOINなクエリ、および適切なインデックスに依存しながら、集約データなしで2つのテーブルを使用することをお勧めします。

なんで?それ以外の場合は、コメント/投票/いいねが行われるときに、常に両方のテーブルにクエリと書き込みを行うことになります。インタラクションを表示するためだけの投稿ごとに10個のアクションを想定すると、実際にはすべてを1つのテーブルに格納し、アクションの種類ごとに追加の列を作成します。JSONを使用することも、単にserialize()配列で使用することもできます。これは少し高速です。

最終的にどのソリューションを選択するかは、取得するアクションの数とそれらをどのように使用するかによって大きく異なります。ソリューション1を使用すると、1つの投稿のすべてのアクションを取得するのは簡単で、非常に高速ですが、内部を検索するのは面倒です。一方、ソリューション2は、より多くのスペース、慎重なクエリ書き込み、およびインデックスを必要とします。

于 2012-10-25T14:55:49.100 に答える
2

システムからの読み取りが書き込みよりもはるかに多いと仮定すると、これを行う方法はいくつか考えられます。ソーシャルネットワーキングサイトは実際には一貫性のあるデータを持っている必要はなく、すべてのユーザーが自分の行動を一貫して見ている限り、結果整合性があるという事実を利用できます。

オプション1。

表#1の各アクションタイプの列を追加し、新しいアクションが発生するたびに列を増やします。このように、メインページのリストは非常に高速です。

表1

post_id | post_content | post_title | creation_time | action1_count | action2_count | action3_count | ...

このアプローチの優れている点は、パーマリンクを表示するときに、テーブル#2からの投稿に対してすべてのアクションを照会する必要がないことです。最後の5つのアクションと、ビューアによって行われたすべてのアクションをクエリするだけです。ここでインスピレーションを確認してください:1つの選択でカテゴリごとに最新の2つのアイテムを取得する方法(mysqlを使用)

オプション#2。

これは最初のアプローチに似ていますが、アクションカウントをRedisハッシュセットに書き込むか、単にJSONオブジェクトとしてmemcacheに書き込みます。メインページの読み込み時にそれらを照会するのは非常に高速です。欠点は、redis(および常にmemcachedの場合)を再起動する場合、それらを再初期化する必要があるか、誰かがパーマリンクビューからページを表示するときにそれを行う必要があることです。

于 2012-10-27T02:20:56.413 に答える
2

何よりもまず、オプション2は最適化が早すぎることに起因していると言えます。ただし、リストページでクエリの結合がないことでパフォーマンスが向上することを示す統計がない限り、オプション1を使用します。

オプション2の主な問題はメンテナンスです。何かを変更する必要があるたびに、2か所で変更する必要があります。間違いを修正したり、古いレコードに新しいフィールドを入力したりするには、すべての投稿でデータベース側で文字列操作を実行する必要があります(通常)。

私の経験から、オプション2のパフォーマンス上の利点はごくわずかであり、データベースのクエリ(少なくともそのような短いクエリ)の遅延のほとんどは、リモートサーバーへの接続に起因します。

また、クエリを適切に抽象化すると、両方のアプローチ間を移動する(または、最も頻繁なエントリをキャッシュするなどの別のアプローチを使用する)のが簡単になります。最初に最も簡単なアプローチ(オプション1)を使用してから、変更してください。現在の実装の問題に関する情報がある場合(現在の実装とは異なります)。

わかりやすくするために、オプション1(オプション2の逆)の長所と短所のリストを次に示します。

オプション1

プロ

  • より高速な書き込み。
  • メンテナンスが簡単
  • より小さなストレージ要件
  • データの重複はありません

短所

  • リストの読み取りが遅くなります。
于 2012-10-28T06:52:33.490 に答える
-1

重要なことの1つは、挿入/削除/更新のパフォーマンスの違いです。挿入は削除/更新よりもはるかに高速です。そのため、削除/更新を最小限に抑えるソリューションを選択します。

表1は、最初のオプションのようになります。
post_id | post_content | post_title | creation_time

表#2はほとんど同じですが、。はありませんaction_id
post_id | action_type | action_creator | creation_time

表2には、post_id、action_type、およびaction_creator列にマップ複合インデックスがあります。

高速クエリでは、マップ複合インデックスの2つの順序が重要です。インデックスのすべての部分が使用されていなくても、インデックスは使用されるためです。つまり、次のクエリは機能し select ... from table_2 where post_id = 1 and action_type = 2
ますが、次のクエリは機能しません
select ... from table_2 where post_id = 1 and action_creator = 2

簡単に説明すると、ツリーのようなマップ複合インデックスを使用するには、ツリーの上のすべての部分を使用する必要があります。つまり、インデックスを使用するためにpost_idとaction_typeをクエリせずに、「action_creator」をクエリすることはできません。

-post_id  
    |--action_type  
          |--action_creator             

ただし、クエリを実行して常に複合インデックスをヒットできるようになりました。また、ほとんどの場合、テーブル#1とテーブル#2の両方に挿入を行っています。

大量の「アクション」が原因で巨大なテーブル#2になってしまった場合は、将来、post_idでパーティションを作成する場所でテーブルをパーティション化する可能性があります。ほとんどの場合、ユーザーは新しいエントリにアクセスするため、1つのパーティションに「優先順位を付けて」、より高速なディスクとDB内のより多くのメモリキャッシュを使用できます。または、後でデータベースの前にあるhttp://memcached.org/のようなもので最適化します。

于 2012-10-28T12:01:25.423 に答える