为什么SQL Server Optimizer不使用检查约束定义来查找包含行的表?
我使用SQL Server 2012,我有一个很大的表,我将我的表分为以下几个表:为什么SQL Server Optimizer不使用检查约束定义来查找包含行的表?,sql,sql-server,sql-server-2012,sql-view,Sql,Sql Server,Sql Server 2012,Sql View,我使用SQL Server 2012,我有一个很大的表,我将我的表分为以下几个表: Create Table A2013 ( Id int identity(1,1), CountA int , Name varchar(50), ADate DATETIME NULL CHECK (DATEPART(yy, ADate) = 2013) ) Create Table A2014 ( Id int identity(1,1), Cou
Create Table A2013
(
Id int identity(1,1),
CountA int ,
Name varchar(50),
ADate DATETIME NULL
CHECK (DATEPART(yy, ADate) = 2013)
)
Create Table A2014
(
Id int identity(1,1),
CountA int ,
Name varchar(50),
ADate DATETIME NULL
CHECK (DATEPART(yy, ADate) = 2014)
)
Insert Into A2013 Values ( 102 , 'A','20131011' )
Insert Into A2013 Values (15 , 'B' ,'20130211' )
Insert Into A2013 Values ( 54, 'C' ,'20131211' )
Insert Into A2013 Values ( 54, 'D' ,'20130611' )
Insert Into A2013 Values ( 95, 'E' ,'20130711' )
Insert Into A2013 Values (8754 , 'F' ,'20130310' )
Insert Into A2014 Values ( 102 , 'A','20141011' )
Insert Into A2014 Values (15 , 'B' ,'20140911' )
Insert Into A2014 Values ( 54, 'C' ,'20140711' )
Insert Into A2014 Values ( 54, 'D' ,'20141007' )
Insert Into A2014 Values ( 95, 'E' ,'20140411' )
Insert Into A2014 Values (8754 , 'F' ,'20140611' )
我创建了一个分区视图,如下所示:
Create View A
As
Select * From A2013
Union
Select * From A2014
我希望SQL Optimizer
使用一个好的计划,并使用我的检查约束定义来确定哪个成员表包含行,但在运行此查询时它会扫描两个表:
Select * From A Where A.ADate = '20140611'
我希望SQL Optimizer不会使用table
A2013
检查约束表达式必须正确,以便优化器消除执行计划中不需要的表。以下约束避免将函数应用于列,并且是可修改的:
CREATE TABLE dbo.A2013
(
Id int IDENTITY(1, 1)
, CountA int
, Name varchar(50)
, ADate datetime NULL
CONSTRAINT CK_A2013_ADate
CHECK ( ADate >= '20130101'
AND ADate < '20140101' )
);
CREATE TABLE dbo.A2014
(
Id int IDENTITY(1, 1)
, CountA int
, Name varchar(50)
, ADate datetime NULL
CONSTRAINT CK_A2014_ADate
CHECK ( ADate >= '20140101'
AND ADate < '20150101' )
);
创建表dbo.A2013
(
Id int标识(1,1)
,CountA int
,姓名varchar(50)
,ADate datetime NULL
约束CK_A2013_ADate
检查(日期>='20130101'
和ADate<'20140101')
);
创建表dbo.A2014
(
Id int标识(1,1)
,CountA int
,姓名varchar(50)
,ADate datetime NULL
约束CK_A2014_ADate
检查(日期>='20140101'
和ADate<'20150101')
);
检查约束表达式必须正确,以便优化器消除执行计划中不需要的表。以下约束避免将函数应用于列,并且是可修改的:
CREATE TABLE dbo.A2013
(
Id int IDENTITY(1, 1)
, CountA int
, Name varchar(50)
, ADate datetime NULL
CONSTRAINT CK_A2013_ADate
CHECK ( ADate >= '20130101'
AND ADate < '20140101' )
);
CREATE TABLE dbo.A2014
(
Id int IDENTITY(1, 1)
, CountA int
, Name varchar(50)
, ADate datetime NULL
CONSTRAINT CK_A2014_ADate
CHECK ( ADate >= '20140101'
AND ADate < '20150101' )
);
创建表dbo.A2013
(
Id int标识(1,1)
,CountA int
,姓名varchar(50)
,ADate datetime NULL
约束CK_A2013_ADate
检查(日期>='20130101'
和ADate<'20140101')
);
创建表dbo.A2014
(
Id int标识(1,1)
,CountA int
,姓名varchar(50)
,ADate datetime NULL
约束CK_A2014_ADate
检查(日期>='20140101'
和ADate<'20150101')
);
问题不在于表达式是否可搜索。据我所知,术语“sargable”适用于查询中索引的使用。问题是SQL Server是否将where
子句识别为与check
约束匹配
您拥有的检查约束是:
CHECK (DATEPART(yy, ADate) = 2014)
其中
子句为:
Where A.ADate = '20140611'
问题在于,第二个未被识别为第一个的子集。您可以通过添加冗余来解决此问题:
Where A.ADate = '20140611' and DATEPART(yy, A.ADate) = 2014
或者,您可以通过使用范围来解决这个问题——但是要小心数据类型,因为数据类型转换肯定会混淆优化器。我认为以下措施会奏效:
CHECK ADate BETWEEN '2014-01-01' and '2014-12-31'
WHERE A.ADate = '2014-06-11'
(连字符是可选的,可以删除。)
(据我所知)原因并不明确:
SQL Server查询优化器可识别中的搜索条件
此SELECT语句仅引用1998年5月销售和销售记录中的行
1998年6月销售表。因此,它将搜索限制在这些表上
分区视图返回时不需要检查约束
正确的结果。但是,如果尚未设置检查约束
定义后,查询优化器必须搜索所有表,而不是
仅包含分区列上的搜索条件。
在没有检查约束的情况下,视图的操作与任何其他视图一样
和所有人一起。查询优化器无法对
存储在不同表中的值,不能跳过搜索
参与视图定义的表
问题不在于表达式是否可搜索。据我所知,术语“sargable”适用于查询中索引的使用。问题是SQL Server是否将where
子句识别为与check
约束匹配
您拥有的检查约束是:
CHECK (DATEPART(yy, ADate) = 2014)
其中
子句为:
Where A.ADate = '20140611'
问题在于,第二个未被识别为第一个的子集。您可以通过添加冗余来解决此问题:
Where A.ADate = '20140611' and DATEPART(yy, A.ADate) = 2014
或者,您可以通过使用范围来解决这个问题——但是要小心数据类型,因为数据类型转换肯定会混淆优化器。我认为以下措施会奏效:
CHECK ADate BETWEEN '2014-01-01' and '2014-12-31'
WHERE A.ADate = '2014-06-11'
(连字符是可选的,可以删除。)
(据我所知)原因并不明确:
SQL Server查询优化器可识别中的搜索条件
此SELECT语句仅引用1998年5月销售和销售记录中的行
1998年6月销售表。因此,它将搜索限制在这些表上
分区视图返回时不需要检查约束
正确的结果。但是,如果尚未设置检查约束
定义后,查询优化器必须搜索所有表,而不是
仅包含分区列上的搜索条件。
在没有检查约束的情况下,视图的操作与任何其他视图一样
和所有人一起。查询优化器无法对
存储在不同表中的值,不能跳过搜索
参与视图定义的表
如果显式地添加
和DATEPART(yy,ADate)=2014会怎么样?为什么不使用分区,在这种情况下不需要多个表。@RADAR我最常使用分区视图的时间是哪一次?@ardalanshagholi,,实际上是将数据拆分到不同的文件中groups@RADAR谢谢你的回应,但我们最常使用分区视图的时间是什么时候?如果您显式地添加和DATEPART(yy,ADate)=2014
?为什么不使用分区,在这种情况下不需要多个表。@RADAR我最常使用分区视图的时间是什么时候?@ardalanshagholi,,实际上是将数据拆分到不同的文件中groups@RADAR谢谢你的回应,但是,我们最常使用分区视图的时间是什么时候?如果使用where DATEPART(yy,ADate)=2014,它不会产生更好的执行计划吗?我不认为