sql - 为什么我的 SQL 索引被忽略?

标签 sql sql-server indexing

我们遇到了一个问题,表上的索引被忽略,而 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 索引中包含 InvoiceTotalAmountPaid 列,使索引成为覆盖索引。 (在 SQL 2005 中,您可以将它们添加为“包含”列”。在 SQL 2000 中,您必须将它们添加为附加键列。)如果您这样做,我将保证查询优化器将选择您的索引*。

说明: 索引看起来总是有用的,但是使用(非覆盖)索引有一个隐藏的成本,那就是检索任何书签必须执行的“书签查找” >主表中可能需要的其他列。此书签查找是一项昂贵的操作,并且是查询优化器可能不选择使用您的索引的(一个可能的)原因。

通过在索引本身中包含所有需要的列,可以完全避免此书签查找,并且优化器不必玩这个小游戏来确定使用索引是否“值得”。

(*) 或者我将退还您的 StackOverflow 积分。只需将一个写好自己地址、贴好邮票的信封发送至...

编辑:是的,如果您的主键不是聚集索引,那么请务必也这样做!但即使进行了这样的更改,使您的 CustomerID 索引成为覆盖索引也应该将性能提高一个数量级(10 倍或更好)!!

关于sql - 为什么我的 SQL 索引被忽略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/969575/

相关文章:

sql - 标准化要走多远?

sql - 使用单个 SQL 关联子查询获取两列

javascript - 如何从按钮网格中获取点击按钮的索引?

MongoDB 查询具有不存在的字段和索引的记录

sql - 查询没有结果数据的目的地 - PostgreSQL

mysql - 使用 select 语句从数据库获取最大匹配项

sql - 在函数内设置事务隔离级别

c# - 获取超时已过期。在从池中获取连接之前超时期限已过。 。异常(exception)

sql-server - SQL 注入(inject) : isn't replace ("' ", "' '") 足够好了吗?

sql - 在 PL/PgSQL EXECUTE 动态查询中正确插入文字