Sql server 2008 我应该使用哪个非聚集索引?
在这里,我正在研究SQLServerManagementStudio上的非聚集索引 我创建了一个包含100多万条记录的表。此表有一个主键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,
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子句以及内部/外部联接。