0

我有一个关于 SQL Server 2008 R2 索引使用的问题,特别是过滤索引的使用。这是我的场景:

@@版本输出:

  • Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
  • 2010 年 4 月 2 日 15:48:46
  • 版权所有 (c) 微软公司
  • Windows NT 6.1(内部版本 7601:Service Pack 1)上的企业版(64 位)

有问题的表有52.114.057条记录(带有主键 Id 字段)。它由一个 ID (int) 主键 IDFK (int)(唯一,外键)、TypeID (int) 字段(不是主键!)和多个自定义元数据字段(vcValue001 - vcValue020 用于 varchar 值,dcValue - dcValue020 用于数字值(十进制 sql 类型)和 dtValue001 - dtValue020 用于日期时间字段)。

简单的布局将是:

  • ID (int) (主键)
  • IDFK (int) (唯一,外键) (已编辑)
  • 类型 ID (int)
  • vcValue001 (varchar)
  • ...
  • vcValue020 (varchar)
  • dcValue001(十进制(38,8))
  • ...
  • dcValue020(十进制(38,8))
  • dtValue001(日期时间)
  • ...
  • dtValue020(日期时间)

该表中不同的 TypeID 是71,而有问题的 TypeID 是 131 (数字实际上不相关,只是碰巧这是使用的实际数字)。对于这个 TypeID=131,一个表中有27.583.573条记录。在每个单独的 TypeID +(“vc”、“dc”和“dt”字段)上创建索引(这意味着它有 60 个索引 + 其他一些)。例如“TypeID, vcValue001”上的索引(因为我在构建查询时总是使用 TypeID 作为标准)。

现在到查询部分:

select top 1000 m.IDFK, m.dtValue002 [MyDate]
from dbo.Metadata m
where (m.nTypeID = 131) and
      (m.vcValue001 = 'A') and
      (m.dtValue002 between '20131212' and '20140312 23:59:59') and
      (m.vcValue003 = 'B') and
      (m.vcValue011 = 'C')
order by m.dtValue002 desc, m.IDFK desc

我用 A、B 和 C 替换了实际值,只有 datepart 是正确的。不同范围的计数如下:

  • 对于 nFileTypeID = 131 和 vcValue001 = 'A':180
  • 对于 nFileTypeID = 131 和 dtValue002 范围:1.179.463
  • 对于 nFileTypeID = 131 和 vcValue003 = 'B':2.380.090
  • 对于 nFileTypeID = 131 和 vcValue011 = 'C':33

为了获得更快的性能,我还创建了过滤索引:

CREATE NONCLUSTERED INDEX IX_Metadata_nTypeID000131_vcValue001_dtValue002_vcValue003_vcValue005_IDFK ON dbo.Metadata
(
    vcValue001 asc,
    dtValue002 asc
    vcValue003 asc,
    vcValue005 asc,
    IDFK asc
)
WHERE (nTypeID = 131 AND vcValue001 IS NOT NULL AND dtValue002 IS NOT NULL)

以我目前的 SQL 知识,上述查询应该受益于使用过滤索引,但不幸的是没有。最奇怪的部分是,如果我按列从“m.IDFK”中删除“desc”关键字,那么它使用过滤索引。我还尝试了两列(m.dtValue002 和 m.IDFK)的 asc 顺序,但它仍然不会使用它。如果未使用过滤索引,则查询使用 (nTypeID, dtValue002) 上的索引,结果约为。5.000.000 次读取,而使用过滤索引时,我得到 17 次读取。我也无法使用索引表提示强制过滤索引,因为 SQL Server 不允许这样做,尽管过滤索引中使用了 WHERE 条件匹配条件。

这是“排序依据”组合和过滤索引使用情况的表:

  • (m.dtValue002 asc, m.IDFK asc):过滤索引未使用(5mio 读取)
  • (m.dtValue002 asc, m.IDFK desc):过滤索引USED(17次读取)
  • (m.dtValue002 desc, m.IDFK asc):过滤索引USED(17次读取)
  • (m.dtValue002 desc, m.IDFK desc):过滤索引未使用(5mio 读取)

仅当“order by”字段的方向(asc,dec)不匹配时,才可能使用过滤索引。我已经搜索过这个问题,但没有找到任何解决方案。我还尝试按所有降序、备用顺序创建过滤索引,但没有运气。但是,我确实需要以相同的方式对这两个字段进行排序。任何方向或建议都会对我有很大帮助。

就在我认为我知道一些 SQL 知识的时候,像这样的谜题却动摇了我的知识;)

编辑:如果我不使用 IDFK 而是使用 ID 字段进行排序,它可以正常工作(例如,我得到的读取次数要少得多,并且两种排序都可以变成相同的方向)。

PS我是新手,所以如果我的问题有问题,请告诉我。

此致!

4

0 回答 0