web-dev-qa-db-ja.com

ブックマークシステムのデータベース設計

ブックマークを保存できるブックマークシステムを作成しています。各ユーザーは、ブックマークを含む独自の個人ページを持っています。ブックマークには少なくとも1つのタグと最大5つのタグが必要です。各ユーザーは無制限のブックマーク/タグを作成できます。

次のテーブルを作成しました。

User
----
Id
Email


Bookmark
--------
Id
UserId
Title
Url


Tag
---
Id
UserId
Title
Description


TagBookmark
-----------
TagId
BookmarkId

これは正規化されていますか?それとも別の方法で行う必要がありますか?これは100万のブックマークでうまく機能しますか?

また、既存のブックマーク/タグを再利用する必要があるかどうかもわかりません。

例1:

User1とUser2の両方がブックマーク " http://google.com "を作成します。これを1つのブックマークとして保存する必要がありますか?または、ユーザーごとに個別に保存しますか?

例2:

User1とUser2はどちらもタグ「search-engine」を作成します。これを1つのタグとして保存する必要がありますか?または、ユーザーごとに個別に保存しますか?

ユーザー間でブックマークとタグを再利用しない場合、これらのテーブルは非常に大きくなる可能性があります。

4
wbosland

予想される大規模なユーザーベースに対して最大のパフォーマンスを実現するように設計する場合、ブックマークとタグが不必要に複製されないようにすることをお勧めします。以下の推奨スキーマを使用して、http://google.com/は単一のブックマーク行になります。 Googleへのブックマークが必要なユーザーは、ブックマーク行と関連するタグ行を参照するUserBookmarksTagsに行があります。

私は、ブックマークテーブルからUserIDを抽象化し、相互参照テーブルを使用して、ブックマークを持っているユーザーと、各ブックマークに付けたタグを判別する傾向があります。

SQL Serverを使用して、私は次のようにします。

USE tempdb;
GO
CREATE TABLE Users
(
    UserID INT NOT NULL 
        CONSTRAINT PK_Users
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , UserName varchar(255)
);
CREATE TABLE Bookmarks
(
    BookmarkID INT NOT NULL
        CONSTRAINT PK_Bookmarks
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , BookmarkName varchar(255)
    , BookmarkURL varchar(255)
);
CREATE TABLE Tags
(
    TagID INT NOT NULL
        CONSTRAINT PK_Tags
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , TagName varchar(255)
);

システムのすべてのエントリにブックマークとタグの両方が必要な場合は、次の表を使用して最大のパフォーマンスを得ることができます。

CREATE TABLE UsersBookmarksTags
(
    UserID INT NOT NULL
        CONSTRAINT FK_UsersBookmarksTags_UserID
        FOREIGN KEY REFERENCES Users(UserID)
    , TagID INT NOT NULL
        CONSTRAINT FK_UsersBookmarksTags_TagID
        FOREIGN KEY REFERENCES Tags(TagID)
    , BookmarkID INT NOT NULL
        CONSTRAINT FK_UsersBooksmarksTags_BookmarkID
        FOREIGN KEY REFERENCES Bookmarks(BookmarkID)
    , CONSTRAINT PK_UsersBookmarksTags
        PRIMARY KEY CLUSTERED 
        (UserID, TagID, BookmarkID)
);

上記のバージョンのテーブルUsersBookmarksTagsを使用すると、特定のタグに一致する特定のユーザーのブックマークのリスト、またはそのユーザーのすべてのブックマークをすばやく返すことができます。

または、次のように、タグとブックマークの両方にnullエントリを許可する相互参照テーブルを作成することもできます。

CREATE TABLE UsersBookmarksTags
(
    UsersTagsBookmarksID INT NOT NULL
        CONSTRAINT PK_UsersBookmarksTags
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , UserID INT NOT NULL
        CONSTRAINT FK_UserBookmarks_UserID
        FOREIGN KEY REFERENCES Users(UserID)
    , TagID INT NULL
        CONSTRAINT FK_UserBookmarks_TagID
        FOREIGN KEY REFERENCES Tags(TagID)
    , BookmarkID INT NULL
        CONSTRAINT FK_UserBooksmarks_BookmarkID
        FOREIGN KEY REFERENCES Bookmarks(BookmarkID)
);

これにより、タグのないブックマークを持つ行が許可され、ブックマークのないユーザーにタグを関連付けることができます。

ユーザーが追加したすべてのタグを知る必要があり、それらのタグに必ずしも関連付けられたブックマークがない場合は、その目的のために次のように別のテーブルを追加することを検討します。

CREATE TABLE UserTags
(
    UserID INT NOT NULL
        CONSTRAINT FK_UserTags_UserID
        FOREIGN KEY REFERENCES Users(UserID)
    , TagID INT NOT NULL
        CONSTRAINT FK_UserTags_TagID
        FOREIGN KEY REFERENCES Tags(TagID)
    , CONSTRAINT PK_UserTags
        PRIMARY KEY CLUSTERED 
        (UserID, TagID)
);
2
Max Vernon
User //Might be useful to have a seperate ID for the relationship between the user data
----
Id
UserId
Email


Bookmark
--------
Id
Title
Url


BookmarkUser //Lookup Table
------------
Id
UserId
Bookmark.Id


TagList //You don't need to associate users with tags
---
Id
Title


TagBookmark
-----------
Tags.TagId
Bookmarks.Id


BookmarkView //Suggestion. Aggregates data, will make queries easier
------------
User.UserId
Bookmark.Id
Tags.TagID
1
nobrandheroes

このデザインは私には完璧に見えます。あなたが持っているので、私はブックマークとタグをユーザーごとに区別しておきます。これにより、共有ブックマークにどのユーザーがどのタグを使用するか、共有タグにどのブックマークを使用するかという複雑さから解放されます。彼らが多くのスペースを占めるようになるわけではありません。

「Tag1」、「Tag2」、「Tag3」などのフィールドを作成しないでください。

0