Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 我应该使用哪个非聚集索引?_Sql Server 2008_Indexing_Non Clustered Index - Fatal编程技术网

Sql server 2008 我应该使用哪个非聚集索引?

Sql server 2008 我应该使用哪个非聚集索引?,sql-server-2008,indexing,non-clustered-index,Sql Server 2008,Indexing,Non Clustered Index,在这里,我正在研究SQLServerManagementStudio上的非聚集索引 我创建了一个包含100多万条记录的表。此表有一个主键 CREATE TABLE [dbo].[Customers]( [CustomerId] [int] IDENTITY(1,1) NOT NULL, [CustomerName] [varchar](100) NOT NULL, [Deleted] [bit] NOT NULL, [Active] [bit] NOT NULL,

在这里,我正在研究SQLServerManagementStudio上的非聚集索引

我创建了一个包含100多万条记录的表。此表有一个主键

CREATE TABLE [dbo].[Customers](
    [CustomerId] [int] IDENTITY(1,1) NOT NULL,
    [CustomerName] [varchar](100) NOT NULL,
    [Deleted] [bit] NOT NULL,
    [Active] [bit] NOT NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
(
    [CustomerId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
这是我将用来查看执行计划显示内容的查询:

SELECT CustomerName FROM Customers
执行此命令时不需要额外的非聚集索引,它会导致执行计划显示:

I/O cost = 3.45646
Operator cost = 4.57715
现在,我试图看看是否有可能提高性能,因此我为这个表创建了一个非聚集索引:

1)第一个非聚集索引

CREATE NONCLUSTERED INDEX [IX_CustomerID_CustomerName] ON [dbo].[Customers] 
(
    [CustomerId] ASC,
    [CustomerName] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_CustomerIDIncludeCustomerName] ON [dbo].[Customers] 
(
    [CustomerId] ASC
)
INCLUDE ( [CustomerName]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF,  
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF,   
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
再次执行“针对客户选择”表,执行计划显示:

I/O cost = 2.79942
Operator cost = 3.92001
看起来好多了。现在我删除了刚刚创建的非聚集索引,以便创建一个新索引:

2)第一个非聚集索引

CREATE NONCLUSTERED INDEX [IX_CustomerID_CustomerName] ON [dbo].[Customers] 
(
    [CustomerId] ASC,
    [CustomerName] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_CustomerIDIncludeCustomerName] ON [dbo].[Customers] 
(
    [CustomerId] ASC
)
INCLUDE ( [CustomerName]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF,  
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF,   
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
有了这个新的非聚集索引,我再次执行了select语句,执行计划显示了相同的结果:

I/O cost = 2.79942
Operator cost = 3.92001
那么,我应该使用哪个非聚集索引呢? 为什么I/O和操作员的执行计划成本相同? 我做错了什么,还是这是意料之中的

谢谢

这是因为“CustomerName”被
包含在第二个索引中(请参阅关于插入的列)

基本上,这两个索引的工作方式完全相同——它们是包含索引的索引,第一个索引列与WHERE子句不匹配

这意味着这两种情况下的查询都将扫描索引,但不会触及表


对于特定的查询,我希望它能更好地执行的索引将仅是CustomerName上的一个索引。

除非您使用WHERE筛选结果,按顺序排序结果,从而使用索引,否则您不会注意到有索引或没有索引有多大区别,或者将结果连接到索引列上的另一个表

尝试在没有索引的情况下执行以下查询:

SELECT *
FROM Customers
WHERE CustomerName = 'Marcus Adams'
然后在CustomerName列上添加索引并重试


表中还需要足够多的行,以便数据库系统实际使用索引,并注意到扫描行和使用索引之间的区别。

两个非聚集索引都没有多大意义

关键是:聚集索引的列(在您的例子中是
CustomerId
)已经包含在您拥有的每个非聚集索引的每个条目中。如果找到条目,那么该集群列毕竟是用于实际数据查找的。因此,将其添加到非聚集索引通常是多余的,只是浪费空间

问题更多:如何选择要显示的行?
WHERE
子句中将显示哪些列

如果您在此处找到一种模式(例如,您总是按城市进行选择),则适合您需要的非聚集索引将是

CREATE NONCLUSTERED INDEX [IX_Customer_City] ON [dbo].[Customers] 
(
    [City] ASC
)
INCLUDE ( [CustomerName]) 

这样,您就为SQL Server提供了一种方法,可以轻松地查找与给定城市匹配的行,并包括您希望返回的列(
CustomerName
),这样SQL Server就可以直接从索引页获取必要的信息(使其成为所谓的
覆盖索引
-它覆盖您的查询,例如返回所有需要的信息)-您不需要执行“书签查找”,例如从实际数据页获取整个
客户
数据行(通过非聚集索引中的
CustomerId
查找,因为它是聚集键).

事实上,当我单独在CustomerName上创建索引时,I/O成本和操作员成本会略有增加。@Junior Mayhé:DVK是100%正确的,但您没有单独在CustomerName上创建索引。如果您这样做,我预计成本会大幅下降。例如,在dbo.Customers(CustomerName)上创建索引IX_Custname评论不错!我认为这有助于我为数据库创建所需的非聚集列。在链接上,Microsoft告诉我避免添加太多不必要的列。SELECT*通常会强制进行聚集扫描。否则,它将使用昂贵的书签/键lookup@gbn,选择*
是为了简洁,但感谢您提供的信息。是的我还做了一些类似于从CustomerName(如“%Marcus%”这样的CustomerName)中选择CustomerName的操作。在CustomerName上设置非聚集索引似乎可以降低成本。我明白了你的意思。我想我错过了示例中的WHERE子句。在这里,我正在使用WHERE子句进行测试,以比较这些成本。目的是为Customer添加更多列s表,其中一些将用于where子句以及内部/外部联接。