Rom*_*kar 5 sql sql-server database-design query-optimization sql-server-2008-r2
假设我有一个这样的表模式:
Partners 表
ID Name
1 Test
Run Code Online (Sandbox Code Playgroud)
Partners_Codes 表
Partner_ID Code
1 'Test_Code'
Run Code Online (Sandbox Code Playgroud)
我也有独特的聚集索引Partner_ID中Partners_Codes:
create unique clustered index IX_Partners_Codes on Partners_Codes (Partner_ID);
Run Code Online (Sandbox Code Playgroud)
现在,当我这样查询时:
select
P.ID, P.Name
from dbo.Partners as P
left outer join dbo.Partners_Codes as PC on PC.Partner_ID = P.ID;
Run Code Online (Sandbox Code Playgroud)
SQL Server优化器非常智能,可以查看索引,Partners_Codes而不是查询Partners_Codes,这有利于提高性能.
现在假设我必须添加一个Active列Partners_Codes,因此我可以为每个列添加许多代码Partner,但只有一个代码可以Active.
Partners_Codes2 表
Partner_ID Code Active
1 'Test_Code' 1
1 'Test_Code_old1' 0
1 'Test_Code_old2' 0
Run Code Online (Sandbox Code Playgroud)
我尝试了两种方法 - 使用过滤索引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);
Run Code Online (Sandbox Code Playgroud)
但对于这两种方法,SQL Server优化器将查询Partners_Codes表,即使它应该知道表中只有一行或零行,而我不从表中获取任何数据.
我的实际架构有点复杂,我不想将数据拆分成几个表.问题是 - 是否可以创建过滤索引或索引视图,以便优化程序在显示的情况下使用它?
相关链接:
我刚刚读完这篇文章,发现我错过了最后一个字符串:
即使在企业版中也需要 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;
Run Code Online (Sandbox Code Playgroud)
并且效果很好!
更多链接: