SQL Server表优化索引

SQL Server表优化索引,sql,sql-server,indexing,Sql,Sql Server,Indexing,我有一个非常具体的问题,这是面试测试的一部分 我有这张桌子: CREATE TABLE Teszt ( Id INT NOT NULL , Name NVARCHAR(100) , [Description] NVARCHAR(MAX) , Value DECIMAL(20,4) , IsEnabled BIT ) 这些选择: SELECT Name FROM Teszt WHERE

我有一个非常具体的问题,这是面试测试的一部分

我有这张桌子:

CREATE TABLE Teszt
(
    Id              INT NOT NULL
   , Name           NVARCHAR(100)
   , [Description]  NVARCHAR(MAX)
   , Value          DECIMAL(20,4)
   , IsEnabled      BIT
)
这些选择:

SELECT Name 
FROM Teszt 
WHERE Id = 10

SELECT Id, Value 
FROM Teszt 
WHERE IsEnabled = 1

SELECT [Description] 
FROM Teszt 
WHERE Name LIKE '%alma%'

SELECT [Description] 
FROM Teszt 
WHERE Value > 1000 AND IsEnabled = 1

SELECT Id, Name 
FROM Teszt 
WHERE IsEnabled = 1
问题是,我应该在这个表的什么位置放置索引来优化上述查询的性能。没有提供表中的其他信息,因此我的答案将包含索引的常规pro/contra参数,但我不确定上述查询

我对使用索引优化这些特定查询的想法:

Id应该有一个索引,看起来像主键,它是where子句的一部分

在Value列上创建一个也很好,因为它是where子句的一部分

现在对我来说它变得模糊了。对于Name列,仅基于上述查询,我可能不应该创建一个,因为它与LIKE一起使用,这违背了索引的目的,对吗

我试着在索引一列(表中的isEnabled列)上阅读所有内容,但我不能说这对我来说更清楚,因为参数范围很广。我应该在上面创建索引吗?是否应该对其进行过滤?它应该是一个单独索引的一部分,还是只是一个索引和其他列的一部分

同样,这都是理论上的,所以没有关于表的大小或使用的信息

提前感谢您的回答

问候,,
Tom

通常不建议在位列上建立索引。下面的讨论不仅适用于位列,而且适用于任何低基数值。在英语中,“低基数”表示列只接受少数值

原因很简单。位列有三个值(如果包括
NULL
)。这意味着列上的典型选择将返回大约三分之一的行。三分之一的行表示您(通常)将访问每个数据页。如果是这样的话,您不妨进行一次完整的表扫描

那么,让我们明确地问一个问题:位索引上的索引何时有用或合适

首先,如果您总是在查找
IsEnabled=1
,并且(比如)启用了0.001%的行,则上述参数不起作用。这是一个高度选择性的查询,索引可能会有所帮助。注意:在这种情况下,索引对
IsEnabled=0
没有帮助

第二,上述论点支持基于位值的聚集索引。如果这些值是聚集的,那么即使是30%的选择性也意味着您只读取了30%的行。缺点是,更新值意味着将记录从一个数据页移动到另一个数据页(这是一个有点昂贵的操作)

第三,bit列可以构造性地成为更大索引的一部分。尤其是位在第一位的聚集索引。例如,对于第四个查询,可以认为
(IsEnabled,Value,Description)
上的聚集索引是最佳索引


不过,老实说,我不喜欢玩弄聚集索引。我希望主键是聚集索引。我承认,对于一组很小的查询来说,性能的提高是令人印象深刻的——如果这是您的用例,那么就使用它们(访问启用的行可能是使用它们的一个很好的理由)。但是,聚集索引只能使用一次,而主键是优化
join
s的最佳通用选项。

您可以阅读本文中有关如何创建索引的详细信息:

正如你所说,使用索引有优点也有缺点

优点:选择查询将更快
缺点:插入查询速度较慢

结论:如果表的
插入操作较少,而
选择操作最多,则添加索引

<代码>在哪个栏我应该考虑添加索引?< /代码>这确实是一个很好的问题。虽然我不是DB专家,但以下是我的观点:

  • 在主键列上添加索引
  • 在联接列[内部/外部/左侧]上添加索引

  • 简短回答:关于
    Id
    IsEnabled
    (尽管对
    BIT
    字段的索引存在争议;
    Id
    应该是主键)

    通常,为了优化性能,索引应该位于字段上,其中有
    where
    JOIN
    。(在引擎盖下)要进行选择,db服务器会查找索引,如果找不到,则会在内存中动态创建一个索引,这需要时间,因此会降低性能

    正如Bhuwan所指出的,索引对于
    INSERT
    s是“不好的”(在设计数据库时要记住这一点),但是在示例中只有
    SELECT
    s是私有的

    希望你通过考试:)


    -尼克

    tldr:我可能稍后会删除这个,所以没有必要


    我对这个面试问题的回答是:“这要看情况而定。”。。。然后我可能会花太多时间在面试中谈论这个问题有多糟糕

    问题在于,对于“面试测试”来说,这只是一个糟糕的问题。我已经在这上面戳了两个小时了,我花的时间越长,我就越生气

  • 由于绝对没有关于表内容的信息,我们无法保证该表是第一个标准格式或更好的格式,因此我们甚至不能假设唯一不可为空的列
    Id
    是有效的主键

  • 由于不知道表的内容,我们甚至不知道它是否需要索引。如果它只有几行,那么整个页面都会存储在内存中,无论您对它运行什么操作,都会足够快

  • 由于没有基数信息,我们不知道
    值>1000
    是常见还是不常见。所有或任何值都可能大于1000,但我们不知道

  • 由于没有基数信息,我们不知道
    IsEnabled=1<
    
    create index ixf_Name on dbo.Teszt(Name)
    include (Id)
    where id = 10;
    
    create index ixf_Value_Enabled on dbo.Teszt(Value) 
    include (Id)
    where IsEnabled = 1;
    
    create index ixf_Value_gt1k_Enabled on  dbo.Teszt(Id)
    include (description,value,IsEnabled)
    where Value > 1000 and IsEnabled = 1;
    
    create index ixf_Name_Enabled on dbo.Teszt(Id)
    include (Name, IsEnabled)
    where IsEnabled = 1;
    
    create index ixf_Name_notNull on dbo.Teszt(Name)
    include (Description)
    where Name is not null;