我们遇到了一个问题,表上的索引被忽略,而 SQL Server 2000 正在执行表扫描。我们可以通过使用 WITH (INDEX=<index_name>)
强制使用索引条款,但不想这样做。
作为一名开发人员,我在编写 T-SQL 时对 SQL Server 非常熟悉,但分析和性能调优并不是我的强项。我正在寻找有关为什么会发生这种情况的任何建议和指导。
更新:
我应该说我们已经重建了所有索引并更新了索引统计信息。
罪魁祸首之一的表定义如下:
CREATE TABLE [tblinvoices]
(
[CustomerID] [int] NOT NULL,
[InvoiceNo] [int] NOT NULL,
[InvoiceDate] [smalldatetime] NOT NULL,
[InvoiceTotal] [numeric](18, 2) NOT NULL,
[AmountPaid] [numeric](18, 2) NULL
CONSTRAINT [DF_tblinvoices_AmountPaid] DEFAULT (0),
[DateEntered] [smalldatetime] NULL
CONSTRAINT [DF_tblinvoices_DateEntered] DEFAULT (getdate()),
[PaymentRef] [varchar](110),
[PaymentType] [varchar](10),
[SyncStatus] [int] NULL,
[PeriodStart] [smalldatetime] NULL,
[DateIssued] [smalldatetime] NULL
CONSTRAINT [DF_tblinvoices_dateissued] DEFAULT (getdate()),
CONSTRAINT [PK_tblinvoices] PRIMARY KEY NONCLUSTERED
(
[InvoiceNo] ASC
) ON [PRIMARY]
) ON [PRIMARY]
该表上还有另一个索引(我们希望 SQL 使用的索引):
CustomerID (Non-Unique, Non-Clustered)
以下查询执行表扫描,而不是使用 CustomerID
索引:
SELECT
CustomerID,
Sum(InvoiceTotal) AS SumOfInvoiceTotal,
Sum(AmountPaid) AS SumOfAmountPaid
FROM tblInvoices
WHERE CustomerID = 2112
GROUP BY customerID
更新:
回复Autocracy's question ,这两个查询都执行表扫描。
更新:
回复Quassnoi's question关于DBCC SHOW_STATISTICS
,数据为:
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1667 246 454 8 27.33333
2112 911 3427 16 56.9375
2133 914 775 16 57.125
最佳答案
最好的办法是通过在 CustomerID 索引中包含 InvoiceTotal 和 AmountPaid 列,使索引成为覆盖索引。 (在 SQL 2005 中,您可以将它们添加为“包含”列”。在 SQL 2000 中,您必须将它们添加为附加键列。)如果您这样做,我将保证查询优化器将选择您的索引*。
说明: 索引看起来总是有用的,但是使用(非覆盖)索引有一个隐藏的成本,那就是检索任何书签必须执行的“书签查找” >主表中可能需要的其他列。此书签查找是一项昂贵的操作,并且是查询优化器可能不选择使用您的索引的(一个可能的)原因。
通过在索引本身中包含所有需要的列,可以完全避免此书签查找,并且优化器不必玩这个小游戏来确定使用索引是否“值得”。
(*) 或者我将退还您的 StackOverflow 积分。只需将一个写好自己地址、贴好邮票的信封发送至...
编辑:是的,如果您的主键不是聚集索引,那么请务必也这样做!但即使进行了这样的更改,使您的 CustomerID 索引成为覆盖索引也应该将性能提高一个数量级(10 倍或更好)!!
关于sql - 为什么我的 SQL 索引被忽略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/969575/