我正在构建一个Web应用程序(项目管理系统),并且在性能方面一直想知道这一点。
我有一个Issues表,里面有12个外键链接到其他各种表。在其中的8个中,我需要加入才能从其他表中获取title字段,以便使记录在Web应用程序中有意义,但是,这意味着进行8个加入似乎非常繁琐,尤其是因为我只是在拉入这些联接中的每个联接都有1个字段。
现在,出于永久性的原因,我还被告知要使用自动递增的主键(除非考虑到分片,在这种情况下我应该使用GUID),但是在性能上使用varchar(最大长度为32)有多糟糕?我的意思是,这些表中的大多数可能不会有很多记录(其中大多数应该在20以下)。另外,如果我使用标题作为主键,则不必在95%的时间内进行联接,因此对于95%的sql,我什至会发生任何性能下降(我认为)。我唯一能想到的缺点是我将拥有更高的磁盘空间使用率(但是一天下来确实是一件大事)。
我将查找表用于很多此类而不是枚举的原因是因为我需要最终用户可以通过应用程序本身配置所有这些值。
将varchar用作不包含很多记录的表的主键有什么弊端?
更新-一些测试
因此,我决定对此做一些基本测试。我有100000条记录,这些是基本查询:
基本VARCHAR FK查询
SELECT i.id, i.key, i.title, i.reporterUserUsername, i.assignedUserUsername, i.projectTitle,
i.ProjectComponentTitle, i.affectedProjectVersionTitle, i.originalFixedProjectVersionTitle,
i.fixedProjectVersionTitle, i.durationEstimate, i.storyPoints, i.dueDate,
i.issueSecurityLevelId, i.creatorUserUsername, i.createdTimestamp,
i.updatedTimestamp, i.issueTypeId, i.issueStatusId
FROM ProjectManagement.Issues i
基本INT FK查询
SELECT i.id, i.key, i.title, ru.username as reporterUserUsername,
au.username as assignedUserUsername, p.title as projectTitle,
pc.title as ProjectComponentTitle, pva.title as affectedProjectVersionTitle,
pvo.title as originalFixedProjectVersionTitle, pvf.title as fixedProjectVersionTitle,
i.durationEstimate, i.storyPoints, i.dueDate, isl.title as issueSecurityLevelId,
cu.username as creatorUserUsername, i.createdTimestamp, i.updatedTimestamp,
it.title as issueTypeId, is.title as issueStatusId
FROM ProjectManagement2.Issues i
INNER JOIN ProjectManagement2.IssueTypes `it` ON it.id = i.issueTypeId
INNER JOIN ProjectManagement2.IssueStatuses `is` ON is.id = i.issueStatusId
INNER JOIN ProjectManagement2.Users `ru` ON ru.id = i.reporterUserId
INNER JOIN ProjectManagement2.Users `au` ON au.id = i.assignedUserId
INNER JOIN ProjectManagement2.Users `cu` ON cu.id = i.creatorUserId
INNER JOIN ProjectManagement2.Projects `p` ON p.id = i.projectId
INNER JOIN ProjectManagement2.`ProjectComponents` `pc` ON pc.id = i.projectComponentId
INNER JOIN ProjectManagement2.ProjectVersions `pva` ON pva.id = i.affectedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvo` ON pvo.id = i.originalFixedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvf` ON pvf.id = i.fixedProjectVersionId
INNER JOIN ProjectManagement2.IssueSecurityLevels isl ON isl.id = i.issueSecurityLevelId
我还使用以下功能运行了这些查询:
- 选择特定项目(其中i.key = 43298)
- 按i.id分组
- 排序方式(用于int FK的it.title,用于varchar FK的i.issueTypeId)
- 限制(50000,100)
- 分组和限制在一起
- 一起分组,订购和限制
这些结果包括:
查询类型:VARCHAR FK TIME / INT FK TIME
基本查询:〜4ms /〜52ms
选择特定项目:〜140ms /〜250ms
按i.id分组:〜4ms /〜2.8sec
排序:〜231ms /〜2sec
时限:〜67ms /〜343ms
分组和限制在一起:〜504ms /〜2sec
一起分组,排序和限制:〜504ms /~2.3sec
现在我不知道我可以做些什么配置来使一个或另一个(或两者都)更快,但是似乎VARCHAR FK在查询数据时看到更快(有时快很多)。
我想我必须选择提高速度是否值得额外的数据/索引大小。