我可以在 AdventureWorks 表 Person.Person 上创建以下约束:
ALTER TABLE Person.Person ADD CONSTRAINT ConstantScan CHECK (LastName <> N'Doesn''t Exist')
这告诉 SQL Server LastName 的值不能为Doesn't Exist
优化器在以下简单查询中利用了这一点:
SELECT *
FROM Person.Person
WHERE LastName = N'Doesn''t Exist'
由于约束告诉优化器列中没有任何内容可以等于我们正在平等搜索的值(假设有可信约束),因此优化器仅执行持续扫描并且“不执行任何操作”
如果我放弃上面的约束并创建一个稍微不同的约束:
ALTER TABLE Person.Person ADD CONSTRAINT ConstantScan2 CHECK (LastName <> N'Doesn''t Exist' AND FirstName <> N'Doesn''t Exist')
并使用谓词运行查询,其结果将违反检查约束:
SELECT *
FROM Person.Person
WHERE FirstName = N'Doesn''t Exist' AND
LastName = N'Doesn''t Exist'
我们通过键查找进行索引查找
但是,如果我跑
SELECT *
FROM Person.Person
WHERE FirstName = N'Doesn''t Exist' AND
LastName = N'Doesn''t Exist'
仅保留原始约束:
ALTER TABLE Person.Person ADD CONSTRAINT ConstantScan CHECK (LastName <> N'Doesn''t Exist')
我再次得到持续的扫描
当约束禁止其结果时,为什么在使用两个谓词运行查询时无法获得持续扫描?我是否正确地假设这只是优化器内功能的限制?
域分析(以及任何由此产生的简化)仅适用于列级 检查约束。
任何仅引用单个列的检查约束都是列级约束。
任何引用多个列的检查约束都是表级约束。
parent_column_id
对于列级约束, insys.check_constraints
不为零。为了清楚起见,使用哪种语法来声明或添加约束并不重要。在表级别声明但仅引用单个列的检查约束将被视为列级约束。同样,仅引用创建表后添加的单个列的检查约束将被添加为列级约束。
是的,这是一个“限制”。当仅需要针对复杂查询表达式评估列级约束时,逻辑就相当复杂了。将其扩展到多列检查约束将非常具有挑战性。
也就是说,早期的简化有意仅限于廉价且易于应用的常见案例。习惯于用编程语言优化编译器的人们通常对这类事情有不同的期望。