ブックマークを保存できるブックマークシステムを作成しています。各ユーザーは、ブックマークを含む独自の個人ページを持っています。ブックマークには少なくとも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つのタグとして保存する必要がありますか?または、ユーザーごとに個別に保存しますか?
ユーザー間でブックマークとタグを再利用しない場合、これらのテーブルは非常に大きくなる可能性があります。
予想される大規模なユーザーベースに対して最大のパフォーマンスを実現するように設計する場合、ブックマークとタグが不必要に複製されないようにすることをお勧めします。以下の推奨スキーマを使用して、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)
);
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
このデザインは私には完璧に見えます。あなたが持っているので、私はブックマークとタグをユーザーごとに区別しておきます。これにより、共有ブックマークにどのユーザーがどのタグを使用するか、共有タグにどのブックマークを使用するかという複雑さから解放されます。彼らが多くのスペースを占めるようになるわけではありません。
「Tag1」、「Tag2」、「Tag3」などのフィールドを作成しないでください。