【问题标题】:Unique filtered index and indexed view are ignored by optimizer优化器忽略唯一过滤索引和索引视图
【发布时间】:2013-09-25 12:06:08
【问题描述】:

假设我有一个这样的表架构:

Partners

ID      Name
1       Test

Partners_Codes

Partner_ID   Code
1            'Test_Code'

我在Partners_Codes 中的Partner_ID 上也有唯一的聚集索引:

create unique clustered index IX_Partners_Codes on Partners_Codes (Partner_ID);

现在,当我这样查询时:

select
    P.ID, P.Name
from dbo.Partners as P
    left outer join dbo.Partners_Codes as PC on PC.Partner_ID = P.ID;

SQL Server 优化器足够智能,可以查看 Partners_Codes 上的索引,而根本不查询 Partners_Codes,这对性能很有好处。

现在假设我必须在Partners_Codes 中添加一个Active 列,这样每个Partner 可以有很多代码,但其中只有一个代码可以是Active

Partners_Codes2

Partner_ID    Code               Active
1             'Test_Code'             1
1             'Test_Code_old1'        0
1             'Test_Code_old2'        0

我尝试了 2 种方法 - 在 Active = 1 上使用过滤索引或在此视图上创建视图和唯一索引:

create table Partners_Codes2 (Partner_ID int, Code nvarchar(128), Active bit);

create view vw_Partners_Codes2
with schemabinding
as
  select
      Partner_ID, Code
  from dbo.Partners_Codes2
  where Active = 1;

create unique clustered index IX_vw_Partners_Codes2 on vw_Partners_Codes2 (Partner_ID);

create table Partners_Codes3 (Partner_ID int, Code nvarchar(128), Active bit);
create unique clustered index IX_Partners_Codes31 on Partners_Codes3 (Partner_ID, Code);
create unique nonclustered index IX_Partners_Codes32 on Partners_Codes3 (Partner_ID) include(Code, Active) where (Active = 1);

但是对于这两种方法,SQL Server 优化器将查询Partners_Codes 表,即使它应该知道表中只有一行或零行并且我没有从表中获取任何数据。

我的实际架构有点复杂,我不想将数据拆分为多个表。问题是 - 是否可以创建过滤索引或索引视图,以便优化器在所示情况下使用它?

sql fiddle demo

相关链接:

【问题讨论】:

  • 您使用的是企业版和/或您在查询视图时是否指定了NOEXPAND?要考虑索引,您至少需要其中一项为真。
  • @Damien_The_Unbeliever 是的,企业版
  • @Damien_The_Unbeliever 添加了答案,谢谢,您帮助我找到了正确的方向

标签: sql sql-server database-design sql-server-2008-r2 query-optimization


【解决方案1】:

我刚刚将this article 读到最后,发现我错过了最后一个字符串:

即使在企业版中也需要 NOEXPAND 提示,以确保 视图索引提供的唯一性保证由 优化器。

我觉得这篇文章开头应该用50粗体字写。

所以我刚刚像这样更改了我的查询:

select
    P.ID
from dbo.Partners as P
    left outer join dbo.vw_Partners_Codes2 as PC with (noexpand) on PC.Partner_ID = P.ID;

效果很好!!!

sql fiddle demo

更多链接:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 2016-06-15
    • 1970-01-01
    相关资源
    最近更新 更多