0

同じプラットフォームを使用してデータを共有する複数のコミュニティがあるという点で、StackExchange に似たマルチサイト プラットフォームを構築しています。

ユーザーは、スタック交換の質問にタグを付けるのと同じ方法でコンテンツに「タグを付ける」ことができます。タグの概念を作成するのに最適なアーキテクチャは何ですか?

私が考えたいくつかの小さなメモは、エイリアス (同義語) の概念でした。また、サイト間でタグを共有したい (同じトピックの別のサイトのコンテンツを表示できるようにする) ことも考えましたが、コミュニティによってコンテキストが異なる可能性があります。たとえば、コンピューターの「グラフ」はデータ構造ですが、数学は別のものです (私の頭の上のランダムな例-それが重要かどうかはわかりません)。

また、英語のコミュニティとフランス語のコミュニティがある場合...

どう思いますか?

4

2 に答える 2

1

完全に正規化された方法でそれを行うには、次のようなものが必要です。

ここに画像の説明を入力

MEANING_ITEM には次のインデックスがあります。

  • {SITE_ID, MEANING_NO, ITEM_NO} - 主キー用に自動的に作成され、指定されたタグを持つアイテムを効率的に検索できます。
  • {ITEM_NO, SITE_ID, MEANING_NO} - 「指定されたアイテムのタグを取得する」という逆のクエリを効率的に実行できます。

注: DBMS でサポートされている場合は、このテーブルをクラスタ化することを検討してください。クラスター化されたテーブルのセカンダリ インデックスはコストがかかる可能性があります (PK 全体のコピーを含める必要があり、二重ルックアップが発生する可能性があるため)。ただし、この場合、両方のインデックスに同じフィールドが含まれます (したがって、すべての「余分な」フィールドは既にセカンダリにありますindex) であり、インデックスの外側にはフィールドがないため、二重ルックアップは必要ありません。クラスタリングによって、(役に立たない) テーブル ヒープを単純に排除し、2 つの B ツリーだけが残ります。

このモデルには次のプロパティがあります。

  • タグとアイテムの両方がサイト固有の方法で識別され、デフォルトでサイト固有のタグを照会します。サイトに関係なくタグ名でクエリを実行する場合はSITE_ID = ...、以下のクエリで WHERE 句を省略します。TAG_NAME は TAG PK の最先端にあるため、サイトレス クエリは追加のインデックスなしで効率的に満たすことができます。
  • 「間違った」サイトのタグでアイテムをタグ付けすることはできません。SITE_ID を「ひし形」の依存関係の両端に伝播する識別関係を使用して、「ひし形」の下部 (MEANING_ITEM 内) でマージします。これにより、この保証が得られます。
  • タグの類義語は効率的に表現されます (同じサイト内で同じ意味を持つタグは類義語と見なされます)。タグに M:N 自己関係を実装しようとした場合に発生する可能性のあるさまざまな異常の余地はありません。1
  • タグの意味はサイト固有であるため、シノニムもサイト固有です。
  • MEANING テーブルは、タグに関する追加情報 (説明など) を格納する自然な場所であり、すべての同義語で共有されます。

1同義語の推移性をどのように処理しますか? A、B、C が同義語の場合、AB と BC を保存するだけですか、それとも AC も保存しますか? どうやって強制するの?強制しない場合は、すべての依存関係を選択するために何らかの再帰クエリが必要になります。また、接続ごとに行が必要になり、スペースとパフォーマンスが無駄になります。

指定されたタグのいずれかを持つアイテムを取得するには、次のようなクエリを実行する必要があります...

SELECT *
FROM ITEM
WHERE EXISTS (
    SELECT *
    FROM TAG JOIN MEANING_ITEM ON
        TAG.SITE_ID = MEANING_ITEM.SITE_ID
        AND TAG.MEANING_NO = MEANING_ITEM.MEANING_NO
    WHERE
        TAG.SITE_ID = <site id>
        AND TAG.NAME IN ( <list of tags> )
        AND ITEM.SITE_ID = MEANING_ITEM.SITE_ID
        AND ITEM.ITEM_NO = MEANING_ITEM.ITEM_NO
)

注: 上記のクエリから MEANING への JOIN を完全に省略できます。JOIN に必要なすべてのフィールドは既に TAG に含まれています。

指定されたすべてのタグを持つアイテムの場合、次のような COUNTing が必要になります。

SELECT *
FROM ITEM
WHERE <number of tags> = (
    SELECT COUNT(DISTINCT TAG_NAME)
    FROM TAG JOIN MEANING_ITEM ON
        TAG.SITE_ID = MEANING_ITEM.SITE_ID
        AND TAG.MEANING_NO = MEANING_ITEM.MEANING_NO
    WHERE
        TAG.SITE_ID = <site id>
        AND TAG.NAME IN ( <list of tags> )
        AND ITEM.SITE_ID = MEANING_ITEM.SITE_ID
        AND ITEM.ITEM_NO = MEANING_ITEM.ITEM_NO
)

これは多くの JOIN 処理のように見えますが、このモデルはクラスター化された (インデックス構成された) テーブルや、クエリをインデックスでカバーするのに優れています。

おそらく、パフォーマンス上の理由からこの設計を非正規化することを検討する前に、実際の StackExchange のデータ量に近づく必要があります (たとえば、ジャンクション テーブルを削除し、アイテムごとのタグ数を制限するなど)。

いずれにせよ、特定の設計に取り組む前に、現実的な量のデータを測定してください。

于 2012-07-12T15:53:22.063 に答える
0

次のようなモデルを提案します。

ERD

使用可能なタグのリストを保持します。これらは、標準の多対多交差テーブルを使用してタグ付けするアイテムに適用されます。

タグのシノニムを管理するには、使用可能なタグ テーブルで複雑な関係を使用します。これは、同義語であるさまざまなタグのうちの 1 つが「メイン」タグと見なされることを前提としています。

使用可能なタグには、英語またはフランス語を示す言語フラグがあります。カナダ政府などのためにこれを行っていて、すべてが両方の言語で表示されるようにする必要がある場合は、複雑な 1 対 1 (表示されていません) を追加してAVAILABLE_TAG、同等の英語とフランス語のタグをリンクできます。

サイト間でタグを共有するには、別の多対多交差をSITEテーブルと使用して、どのタグがどのサイトに属しているかを示します。それらのタグが各サイトで異なることを意味する場合、サイト間でタグを共有することは避けます。

于 2012-07-12T11:49:39.870 に答える