【问题标题】:why my query is not sargable为什么我的查询不是 sargable
【发布时间】:2013-10-29 08:03:41
【问题描述】:

我有一个很奇怪的问题。

我有这样的查询,我在 SQL Server 2008 R2 中运行:

SELECT TOP (20) *
FROM MyTable
WHERE a = 0
    AND b = 0
    AND c = 0

在 MyTable 上使用我的索引

但这个没有:

SELECT TOP (20) *
FROM MyTable
WHERE a = 0
    OR b = 0
    OR c = 0

我想在我的程序中执行第二个查询。如何更改第二个查询以使用索引?

索引是:

CREATE NONCLUSTERED INDEX [MyIndex] ON [dbo].[MyTable] (
[a] ASC,
[b] ASC,
[c] 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]

【问题讨论】:

  • 不会的。它必须搜索整个索引才能找到与LicenseDelete=0 条件匹配的行(因为IRDeleteColorDelete 值可以是任何值)
  • 出于同样的原因,您可以轻松地使用电话簿查找名字为“Martin”且姓氏为“Smith”的人,但查找名字为“Martin”的人或 姓“Smith”的工作量更大。电话簿不是按名字排序的,所以找到 Martins 需要阅读整本书。
  • 您的意思是“或”运算符总是会破坏索引吗?没有办法修复 MyIndex 以覆盖 where 子句吗?
  • @user1121366 - 是的。 “或”不能使用索引。除了在 or-ed 列上有单独索引的情况外,在这种情况下,您可能会获得一个索引联合计划,该计划会寻找多个索引并组合结果。

标签: sql sql-server performance sql-server-2008-r2


【解决方案1】:

对于在条件之间具有or 的查询,您不能使用该索引。想想看:任何一个值都可以匹配,所以索引匹配不能保证没有其他记录匹配该条件。

这真的就像运行单独的搜索然后将它们匹配在一起。

【讨论】:

    【解决方案2】:

    为了使用索引,SQL-Server 会检查很多东西

    1) 如果过滤器是 SARG。

    2) 索引使用似然比(唯一记录数:记录总数)

    3) 要获取的记录数(如果记录较少,则可能使用索引或表扫描。因为 sql-server 发现扫描整个表比查找和使用索引更容易,如果记录的数量很大。)

    4) 在您的查询中,因为您使用OR,记录数增加,在这种情况下,sql-server 发现扫描整个表比定位/使用索引容易.如果是AND,索引使用的可能性会增加。

    【讨论】:

      【解决方案3】:

      其他回答者说的是真的。但是,您可以使用一个技巧:

      SELECT TOP (20) *
      (
      select TOP(20) *
      FROM MyTable
      WHERE a = 0
      
      union
      
      SELECT TOP(20) *
      FROM MyTable
      WHERE b = 0
      
      union
      
      SELECT TOP(20) *
      FROM MyTable
      WHERE c = 0
      )
      

      每个单独的子查询都可以使用单独的索引。因此,现在您只需要 3 个单独的索引(前导列分别为 a、b 和 c),您就可以开始了。

      【讨论】:

        猜你喜欢
        • 2019-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-14
        • 1970-01-01
        • 1970-01-01
        • 2014-08-07
        相关资源
        最近更新 更多