【问题标题】:SQL query does not use available index (SQL Server 2008)SQL 查询不使用可用索引 (SQL Server 2008)
【发布时间】:2009-05-14 11:18:34
【问题描述】:

我在 SQL Server 2008 中有下表:

Session
(
sessionid varchar(10)
startdate dateteime
enddate dateteime
--rest of the fields go here
)

我创建了以下两个非聚集索引:

Inddex1: SessionID,startdate,enddate
Inddex2: startdate,enddate

我有以下问题

select *
from session
where startdate>=@date1 and enddate <=@date2

在执行这个查询时,这两个索引都没有被使用。查询计划只显示表扫描。

现在我尝试删除 index1 并执行相同的 SP 仍然没有使用 index2。

关于如何让 SP 使用 index2 的任何线索? (请不要强制使用索引。)

【问题讨论】:

    标签: sql sql-server-2008 indexing


    【解决方案1】:

    您是否在 SessionID 列上有聚集索引?在这种情况下,您的索引基本上是相同的,因为任何非聚集索引都会隐式包含聚集键。

    表中有多少行,值的基数/唯一性是什么?如果表足够小,则表扫描可能比索引查找 + 书签查找更有效地检索剩余列。

    【讨论】:

    • +1--小表让我很长时间,因为他们在许多情况下拒绝使用索引(我猜是有充分理由的)
    【解决方案2】:

    首先,最好有一个主键,用作唯一的聚集索引。

    我不确定我是否明白这两个复合索引的意义。日期上的单独索引会不会更好?

    【讨论】:

      【解决方案3】:

      您说查询处理器没有使用您的索引之一,但您没有告诉我们它在做什么。我假设是表扫描...?

      您的查询没有覆盖索引。因为您正在执行“选择 *”,所以查询处理器知道,它充其量只能从您的索引中获取一个“书签”(任何一个索引都可以),然后它必须将该书签与表中的实际数据页。

      有了这些知识,查询处理器将查看表中的数据量。如果那里的数据量很小(对于一些小的定义),那么它可能会决定扫描表比书签查找后的索引查找更有效。

      考虑更改查询和/或索引,以便只选择索引完全覆盖的字段。那么我希望你能看到索引的使用情况。但这不一定是正确的做法 - 为很少使用的查询创建巨大的索引可能是错误的。

      【讨论】:

        【解决方案4】:

        任何以“startdate”作为第一列的索引都可以帮助搜索 startdate>=@date1。任何以“enddate”为第一列的索引都可以帮助搜索“enddate

        假设几乎没有 enddates 具有相同的 startdate,则 (startdate,enddate) 上的索引并不比 (startdate) 上的索引有用。

        因此,表扫描似乎是 Sql Server 的可靠选择。

        即使您搜索 startdate>=@date1,进行表扫描仍然有意义。索引扫描会为您提供对必须解析的表的大量引用,这对于大量数据来说是不值得的。

        应该使用索引的一个查询是:

        select * from session where startdate = @date1
        

        无论如何,如果您认为自己比优化器更了解,您可以强制使用如下索引:

        select *
        from session with (index indexname)
        where startdate>=@date1 and enddate <=@date2
        

        【讨论】:

        • 不正确。像 (startdate, enddate) 这样的索引非常适合使用谓词过滤 startdate first 和 enddate second 的查询。可以使用索引。如果有很多列,则单独过滤该索引并为结果进行书签查找将比进行全表扫描便宜得多。
        • 这将有助于“stardate = @a and enddate @x”中查找表。所以是的,有一些罕见的例外。
        • 这也有助于他的确切查询。拥有像 (startdate,enddate) 这样的索引 将 有助于使用 WHERE startdate >= @startdate AND enddate
        • 有趣。从 ("startdate >= @startdate") 开始索引二分搜索。结果不是按 enddate 排序的,所以这是对一半索引的索引扫描。然后查找结果行。这种查找会伤害大量行,所以我认为 Sql Server 会更喜欢暴力表扫描。
        【解决方案5】:

        不会使用复合索引,因为它不能用于优化该查询。您应该在每一列上创建一个单独的索引。

        【讨论】:

        • 不正确。只要索引的第一列上有谓词,就可以使用索引(强调可能)。不一定要平等。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多