2009-03-19 14 views
6

EDIT:ビルタギングシステムの人に。これを読まないでください。あなたが探しているものではありません。私は、RDBMSがそれぞれ独自の最適化手法を持っていることに気付かずに単純な多対多スキームを使用するだけで、この質問をしました。スケーラブルデータベースのタグ付けスキーマ

私は数百万の投稿を持つ投稿システムを持っています。各投稿には、無限の数のタグが関連付けられています。

ユーザーは、メモ、作成日、所有者などを持つタグを作成できます。タグは、タグに関するメモを投稿できるため、ほとんどは投稿自体に似ています。

各タグの関連付けには所有者と日付があります。そのため、誰がタグを追加したのか、また誰がいつ表示されるのかがわかります。

私はこれをどのように実装できますか?これは、タグによる投稿の高速検索、または投稿によるタグの検索が高速でなければなりません。また、ユーザーは、Google検索バーのようなフィールドに名前を入力することで、タグ名の残りの部分を入力する必要があります。

私は現時点で3つの解決策を持っていますが、どちらが最善か、より良い方法があるかはわかりません。

タグの適切な解決策を取得すると、私はメモのレイアウトは表示されません。

方法1リンクリスト

はtagId tag_assocにリンクされたリストに後の点で、アプリケーションは、方法2非正規化

タグ= 0

post:   id, content, ownerId, date, tagId, notesId 
tag_assoc:  id, tagId, ownerId, flink 
tag:   id, name, notesId 

FLINKまでリストを横断しなければなりませんTagId:ownerIdのタブで区切られた配列を含むVARCHARまたはTEXTフィールドです。固定サイズにすることはできません。

post:   id, content, ownerId, date, tags, notesId 
tag:   id, name, notesId 

方法3 Toxi

(から:http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html、 ここにも同じ事:Recommended SQL database design for tags or tagging

post:   id, content, ownerId, date, notesId 
tag_assoc:  ownerId, tagId, postId 
tag:   id, name, notesId 

方法3は、問題を提起、どれだけ速くそれは、すべてを反復することになりますtag_assocの単一行ですか?

方法1と2は、タグでポストを返す場合は高速にする必要がありますが、タグでポストを行う場合は、別のルックアップテーブルを作成する必要があります。

最後に心配しなければならないのは、タグを名前で検索して最適化することですが、私はまだそれを解決していません。

私はここASCII図を作っ:http://pastebin.com/f1c4e0e53

答えて

0

Bill私はあなたを捨ててしまったと思います。ノートは別のテーブルにあり、別のテーブルには別の人が投稿したノートがあります。投稿にはメモとタグが付いていますが、タグにもメモがあります。そのため、タグはユニークです。

ジョナサンはリンクされたリストについては正しいですが、私はまったく使用しません。

DROP TABLE IF EXISTS `tags`; 
CREATE TABLE IF NOT EXISTS `tags` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `date` int(10) unsigned NOT NULL, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `name` (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

DROP TABLE IF EXISTS `posts`; 
CREATE TABLE IF NOT EXISTS `posts` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `date` int(10) unsigned NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `content` TEXT NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

DROP TABLE IF EXISTS `posts_notes`; 
CREATE TABLE IF NOT EXISTS `posts_notes` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `date` int(10) unsigned NOT NULL, 
    `postId` int(10) unsigned NOT NULL, 
    `note` TEXT NOT NULL, 
    PRIMARY KEY (`id`), 
    FOREIGN KEY (`postId`) REFERENCES posts(`id`) ON DELETE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

DROP TABLE IF EXISTS `posts_tags`; 
CREATE TABLE IF NOT EXISTS `posts_tags` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `tagId` int(10) unsigned NOT NULL, 
    `postId` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    FOREIGN KEY (`postId`) REFERENCES posts(`id`) ON DELETE CASCADE, 
    FOREIGN KEY (`tagId`) REFERENCES tags(`id`) ON DELETE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

私は、これは将来的になりますどのくらいの速わからないんだけど、それが唯一のカップルの人としてしばらくの間、罰金する必要があります:私は私のニーズを肉最も簡単な正規化された方法でタグを実装することを決定しましたデータベースを使用します。

0

「人々は、タグに関するメモを投稿することができますので、タグは、ほとんどのポスト自体のようなものです。」 - このフレーズは、POSTのための1つのテーブルと、POSTテーブルを参照する主キーと外部キーを必要とすると思うようになります。これで、ディスク容量が許す限り、各投稿ごとに多くのタグを持つことができます。

タグがポスト間で共有されていないので、私はこれに基づいて、POSTとタグの間に多くの多くのための必要はありませんと仮定しています:

「ユーザーが日付が作成した、ノートを持ってタグを作成することができ、オーナーなど。

作成日と所有者が共有されている場合は、2つの追加の外部キー関係IMOがあります。ここで

+0

タグは投稿間で共有されます。 私はかなり方法3を決めました。タグを持つことができるすべてのテーブルには_tagsという別のテーブルがあります。 EG:news_tags。 私はこの方法ではまだまだスケッチですが、誰もがそれを推薦しているようですので、MySQLが最適化すると仮定しています。 –

+0

"仮定" - 悪い考え。知っている方が良いです。 – duffymo

2

は、私はそれを行うだろうかです:

posts:   [postId], content, ownerId, date, noteId, noteType='post' 
tag_assoc:  [postId, tagName], ownerId, date, noteId, noteType='tagAssoc' 
tags:   [tagName], ownerId, date, noteId, noteType='tag' 
notes:   [noteId, noteType], ownerId, date, content 

角括弧内のフィールドは、それぞれのテーブルの主キーです。

各テーブル内のnoteTypeに制約を定義します。posts,tag_assocおよびtagsです。これにより、たとえば、特定のノートがposttagの両方に適用されなくなります。

タグ名を短い文字列として格納します。整数ではありません。id。そうすれば、tag_assocテーブルにカバーリングインデックス[postIdtagName]を使用することができます。

Doingタグ補完はAJAX呼び出しで行われます。ユーザーがタグに「datab」と入力すると、WebページはAJAX呼び出しを行い、サーバー側では、SELECT tagName FROM tags WHERE tagName LIKE ?||'%'というクエリを実行します。

0

リンクリストはほとんど間違ったアプローチです。リンクされたリストを使用する最も一般的な理由は、正しいソート順でデータを保持することなので、クエリが複雑または準最適であることを意味します。しかし、私は反復的に行を取得するのを避ける簡単な方法を見ていないし、取得されたflink値を使用して次の行の選択操作を条件付けすることはできません。

したがって、主キーの参照に対して通常の外部キーを使用するテーブルベースのアプローチを使用します。 Bill Karwinが概説したものは、私が概説するものに似ています。

関連する問題