Sql 如果只想搜索firstname这就是你需要注意的关于复合索引的技巧。但是,如果您总是使用索引中的所有列,它们的顺序通常不是真正相关的-查询优化器将为您处理这个问题

Sql 如果只想搜索firstname这就是你需要注意的关于复合索引的技巧。但是,如果您总是使用索引中的所有列,它们的顺序通常不是真正相关的-查询优化器将为您处理这个问题,sql,database,indexing,sql-server-2014,database-performance,Sql,Database,Indexing,Sql Server 2014,Database Performance,至于包含的列——这些列只存储在非聚集索引的叶级——它们不是索引搜索结构的一部分,并且不能在WHERE子句中为这些包含的列指定筛选值 这些包含的列的主要好处是:如果您在非聚集索引中搜索,最终,您实际上找到了您要查找的值—此时您有什么可用的?非聚集索引将存储非聚集索引定义中的列(ShortDate和Source),并且它将存储聚集键(如果您有一个,并且应该!),但不存储其他内容 因此,在这种情况下,一旦找到匹配项,并且您的查询希望从该表中查找所有内容,SQL Server必须执行所谓的键查找(通常也

至于包含的列——这些列只存储在非聚集索引的叶级——它们不是索引搜索结构的一部分,并且不能在
WHERE
子句中为这些包含的列指定筛选值

这些包含的列的主要好处是:如果您在非聚集索引中搜索,最终,您实际上找到了您要查找的值—此时您有什么可用的?非聚集索引将存储非聚集索引定义中的列(
ShortDate
Source
),并且它将存储聚集键(如果您有一个,并且应该!),但不存储其他内容

因此,在这种情况下,一旦找到匹配项,并且您的查询希望从该表中查找所有内容,SQL Server必须执行所谓的键查找(通常也称为书签查找),在该查找中,它获取聚集键,然后对聚集索引执行搜索操作,以访问包含您要查找的所有值的实际数据页

如果索引中包含,则非聚集索引的叶级页面包含

  • 非聚集索引中定义的列
  • 群集键列
  • 您的
    INCLUDE
    语句中定义的所有附加列
如果这些列“覆盖”了您的查询,例如提供了您的查询所需的所有值,那么SQL Server在非聚集索引中找到您搜索的值后即完成—它可以从非聚集索引的叶级页面中获取它所需的所有值,并且它不需要执行另一项操作(昂贵)键查找到聚类索引中,以获取实际值


因此,尝试总是显式地指定
SELECT
中真正需要的列是有益的-在这种情况下,您可能能够创建一个有效的覆盖索引,为您的
SELECT
提供所有值-始终使用
SELECT*
会使这变得非常困难或几乎不可能….

标记您正在使用的dbms。这是一个特定于产品的问题。添加了标签sql-server-2014。t是否需要使用
选择*
?在聚集索引中包含列是没有意义的。你是对的:)我只是复制了他建议的索引。现在我已经删除了包含的列。我不知道“选择*”是一种不好的做法,我更改了它,尽管这不是不使用索引的原因。聚集索引不会减少很多写入时间吗?如果我首先按源搜索,索引是否应作为([source]、[ShortDate])进行?TY聚集索引是数据在物理文件中的存储顺序。所以你总是有一个。索引定义中列的顺序无关紧要。这可能是个坏主意-聚集索引会影响记录在数据库中的存储顺序,如果记录顺序不正确,则必须在插入或更新时重新洗牌整个表。我知道,对于我的使用,超过数百万行,我可能会有多达10个不同的来源。短日期可能超过1000个。那么我应该如何制作索引呢?也许只是约会?谢谢Neville如果是这样的话,如果我包括了所有的列,为什么还要使用索引呢@内维尔首先感谢你纠正了我的错误和这个信息丰富的答案!在读了你的评论3次之后,我可以自信地说,我更了解索引的工作原理。如果我错了,请纠正我,但我认为在我不包括列时不使用索引的原因是因为它可以找到数千行,然后需要对所有这些行进行键查找,以获得所有未包含的列,但效率不高。目前,我认为覆盖索引将是我的最佳方法,因为我不是在搜索特定行,而是在同一查询中搜索很多行。因为我包含的专栏很少,而且篇幅不大,我希望它不会占用太多空间。。。尽管仍然不能完全确定它对表的插入有多大影响。再次感谢您的评论@marc_s:)@Ben:没错-如果您在非聚集索引中发现太多点击,那么对聚集索引进行数千次键查找的成本可能会非常高-因此查询优化器只需切换到聚集索引扫描即可。
CREATE TABLE [dbo].[reports]
(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [IsDuplicate] [bit] NOT NULL,
    [IsNotValid] [bit] NOT NULL,
    [Time] [datetime] NOT NULL,
    [ShortDate] [date] NOT NULL,
    [Source] [nvarchar](350) NULL,
    [Email] [nvarchar](350) NULL,

    CONSTRAINT [PK_dbo.reports] 
        PRIMARY KEY CLUSTERED ([id] ASC)
) ON [PRIMARY]
SELECT * 
FROM [db].[dbo].[reports]
WHERE Source = 'name1' 
  AND ShortDate BETWEEN '2017-10-13' AND '2017-10-15'
CREATE NONCLUSTERED INDEX [Source&Time] 
ON [dbo].[reports]([Source] ASC, [ShortDate] ASC)
SELECT * 
FROM [db].[dbo].[reports]
WHERE Source = 'name1' 
  AND ShortDate BETWEEN '2017-10-10' AND '2017-10-15'
SELECT * 
FROM [db].[dbo].[reports]
WHERE Source = 'name1' 
  AND ShortDate = '2017-10-13'
/* The Query Processor estimates that implementing the following 
   index could improve the query cost by 86.2728%. */

/*
USE [db]
GO

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[reports] ([ShortDate], [Source])
INCLUDE ([id], [IsDuplicate], [IsNotValid], [Time], [Email])
GO
*/
USE [db]
GO
CREATE CLUSTERED INDEX CIX_reports
    ON [dbo].[reports] ([ShortDate],[Source])
GO