5 schema erd normalization database-design
我正在创建一个书签系统,人们可以在其中保存他们的书签。每个用户都有自己的带有书签的个人页面。书签应至少有一个标签,最多五个。每个用户可以创建无限的书签/标签。
我创建了以下表格:
User
----
Id
Email
Bookmark
--------
Id
UserId
Title
Url
Tag
---
Id
UserId
Title
Description
TagBookmark
-----------
TagId
BookmarkId
Run Code Online (Sandbox Code Playgroud)
这是正常化了吗?或者我应该采取不同的做法?对于一百万个书签来说,这会表现良好吗?
我也不确定是否应该重用现有的书签/标签。
示例1:
User1 和 User2 都创建书签“ http://google.com ”。我应该将其保存为一个书签吗?或者为每个用户单独保存它们?
示例2:
User1 和 User2 都创建标签“search-engine”。我应该将其另存为一个标签吗?或者为每个用户单独保存它们?
如果我不在用户之间重复使用书签和标签,这些表可能会变得相当大。
为了实现预期的大型用户群的最佳性能,我建议确保书签和标签不会出现不必要的重复。使用下面我建议的架构,http://google.com/将成为单个书签行。想要 Google 书签的用户将有一行UserBookmarksTags引用书签行和关联的标签行。
我倾向于将 UserID 从 Bookmarks 表中抽象出来,并使用交叉引用表来确定哪些用户拥有书签,以及他们为每个书签标记的内容。
使用 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)
);
Run Code Online (Sandbox Code Playgroud)
如果系统中的每个条目都需要书签和标签,则可以使用下表以获得最佳性能:
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)
);
Run Code Online (Sandbox Code Playgroud)
上述版本的表UsersBookmarksTags允许您快速返回与任何给定标签匹配的特定用户的书签列表,或该用户的所有书签。
或者,您可以创建允许标签和书签为空条目的交叉引用表,如下所示:
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)
);
Run Code Online (Sandbox Code Playgroud)
这允许具有没有标签的书签的行,并且还允许将标签与没有书签的用户相关联。
如果需要知道用户添加的所有标签,而这些标签不一定有关联的书签,我会考虑为此目的添加另一个表,如下所示:
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)
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6024 次 |
| 最近记录: |