在文本列上创建索引是否会使搜索成本更高?

Does creating an index on a text column make search costlier?

将字符串列而不是整数列作为主键是否会对搜索时间 and/or 插入时间产生不利影响?

场景

一个。任何应用程序的常见场景是每次有人创建新用户帐户时都进行此查询:

该用户名是否已存在或已被他人占用?

b。当一个人登录时,需要像这样进行另一个查找用户名的查询:

User table 中是否存在包含 UserName 的行?

c。同样,当用户说他们忘记了密码时,我们需要根据他们的电子邮件进行搜索。

User table 中是否存在包含 Email 的行?

d。仅在 link 将 User table 与其他用户相关的 table 连接在一起的情况下,例如 UserRoleUserClaim 等. 我们可能需要根据整数 Id 加入它们,如下所示:

  SELECT * 
  FROM User, UserClaim
  WHERE User.Id = UserClaim.UserId;

将整数作为主键与将字符串作为主键

直到现在,我一直只有一个用户 table 有一个整数主键(和聚簇索引),像这样:

User
-----
Id int primary key identity(1, 1),
UserName nvarchar(50) not null,
Email nvarchar(100) not null,
PasswordHash nvarchar(32) not null

但是,现在考虑我上面描述的用例,我想知道完全消除整数主键并创建 UserName 或 [=16= 之一是否更有成效] 字段作为主键,如下所示:

User
-----
UserName nvarchar(50) primary key,
Email nvarchar(100) not null,
PasswordHash nvarchar(32) not null

这将在 UserName 字段上创建聚集索引,可能会在上面列出的场景 ab 中加速查询,但我不确定影响场景 cd 因为这将取决于速度或比较整数与比较索引的速度一个字符串列。

问题

但是,这给我留下了一些失败的结局,我需要先解决这个问题,然后才能进行此设计:

  1. 像上面那样在文本字段上创建聚簇索引对性能有影响吗?它如何影响插入时间?搜索次数?

    我认为在整数上创建索引比在字符串上创建索引更快?

  2. 我们只能有一个聚簇索引。如果我允许我的用户使用用户名或电子邮件登录,他们喜欢的任何人,那么我将不得不同样频繁地搜索 UserNameEmail 字段。我该如何管理?我应该在 Email 字段上创建非聚集索引吗?

  3. 将字符串列作为主键是否会对我与其他 link table 进行的连接的性能产生影响,如下所示:

    SELECT * FROM User, UserRole
    WHERE User.UserName = UserRole.UserName;
    
  4. 考虑到#3,看起来我应该只在 User table 中保留整数 Id 列并在每个上创建一个非聚集索引UserNameEmail 列?

我正在使用 Microsoft SQL Server 2014。

Does making a clustered index on a text field like the above have any performance implications? How does it affect insertion times? Search times?

  • 每个非聚集索引的每一行都将包含聚集索引键作为rowkey。 INT = 4 bytes,您的 unicode 字符串列 Email 可能会占用 NVARCHAR(100) = up to 200 bytes
  • 聚簇索引适用于范围扫描。几乎不期望对电子邮件地址进行范围扫描。
  • 由于没有页面拆分,基于身份的聚集索引保证接近零碎片和快速插入

We can have only one clustered index. If I allow my users to login using either a user name or email, anyone they like, then I am going to have to make searches on both the UserName and Email fields just as frequently. How do I manage that? Should I make a non-clustered index on the Email field?

是的,如果您决定在 UserName 上创建唯一聚集索引,您将希望在 Email 上创建另一个非聚集索引。如果用户将按 Email 列进行搜索,则用户名列将自动成为此类索引的一部分(由于上文中解释的原因),并且此类索引将被覆盖。

Would having a string column as the primary key have an impact on performance of the joins

UserName 列上的聚簇索引最适合此类连接,因为它会保持数据预先排序,因此在大型数据集上 HASH 连接更有可能被 MERGE加入

Considering #3, it looks like I should just keep the integer Id column in the User table and create a non-clustered index each on the UserName and Email columns?

这在很大程度上取决于您的工作量。如果您必须经常在列 UserName 上连接 table,那么此类列上的聚簇索引可能适合您。在这种情况下,您可以在字段 Email 上创建非聚集唯一索引并在 ID 上保留主键,但也使其成为非聚集索引

(此post 完全基于个人意见)