表达式中的类型转换可能会影响查询计划选择中的“ CardinalityEstimate”吗?


10

我维护一个存档数据库,该数据库将历史数据存储在分区视图中。分区列是日期时间。该视图下的每个表都存储一个月的数据。

我们使用datetime列上的检查约束来约束每个表上的事件。这使优化器可以限制在搜索表中查找在事件datetime列上进行过滤的查询。

检查约束的名称由SQL Server生成,因此很难通过查看其名称来知道它们的作用。

我希望约束名称的格式为“ CK_TableName_Partition”。

我可以使用此查询并从sql_text列复制数据来生成重命名脚本。WHERE子句匹配检查约束,其名称看起来像是由SQL Server生成的:

SELECT
  checks.name AS check_name,
  tabs.name AS table_name,
  skemas.name AS schema_name,
  cols.name AS column_name,
  N'
EXECUTE sys.sp_rename
  @objname = N''' + skemas.name + N'.' + checks.name + N''',
  @newname = N''CK_' + tabs.name + N'_Partition'',
  @objtype = ''OBJECT'';' AS sql_text
FROM sys.check_constraints AS checks
INNER JOIN sys.tables AS tabs ON
  tabs.object_id = checks.parent_object_id
INNER JOIN sys.schemas AS skemas ON
  skemas.schema_id = tabs.schema_id
INNER JOIN sys.columns AS cols ON
  tabs.object_id = cols.object_id AND
  cols.column_id = checks.parent_column_id
WHERE checks.name LIKE (
  N'CK__' + SUBSTRING(tabs.name, 1, 9) +
  N'__' + SUBSTRING(cols.name, 1, 5) +
  N'__' + REPLACE(N'xxxxxxxx', N'x', N'[0-9A-F]') COLLATE Latin1_General_BIN2
)
ORDER BY table_name;

输出看起来像这样:

check_name  table_name  schema_name column_name sql_text
CK__tbAcquisi__Acqui__5C4299A5  tbAcquisitions_201301   Archive AcquisitionDT   EXECUTE sys.sp_rename  @objname = N'Archive.CK__tbAcquisi__Acqui__5C4299A5',  @newname = N'CK_tbAcquisitions_201301_Partition',  @objtype = 'OBJECT';
CK__tbAcquisi__Acqui__76026BA8  tbAcquisitions_201302   Archive AcquisitionDT   EXECUTE sys.sp_rename  @objname = N'Archive.CK__tbAcquisi__Acqui__76026BA8',  @newname = N'CK_tbAcquisitions_201302_Partition',  @objtype = 'OBJECT';
CK__tbAcquisi__Acqui__7D6E8346  tbAcquisitions_201303   Archive AcquisitionDT   EXECUTE sys.sp_rename  @objname = N'Archive.CK__tbAcquisi__Acqui__7D6E8346',  @newname = N'CK_tbAcquisitions_201303_Partition',  @objtype = 'OBJECT';
...
CK__tbRequest__Reque__60132A89  tbRequests_201301   Archive RequestDT   EXECUTE sys.sp_rename  @objname = N'Archive.CK__tbRequest__Reque__60132A89',  @newname = N'CK_tbRequests_201301_Partition',  @objtype = 'OBJECT';
CK__tbRequest__Reque__1392CE8F  tbRequests_201302   Archive RequestDT   EXECUTE sys.sp_rename  @objname = N'Archive.CK__tbRequest__Reque__1392CE8F',  @newname = N'CK_tbRequests_201302_Partition',  @objtype = 'OBJECT';
CK__tbRequest__Reque__1AFEE62D  tbRequests_201303   Archive RequestDT   EXECUTE sys.sp_rename  @objname = N'Archive.CK__tbRequest__Reque__1AFEE62D',  @newname = N'CK_tbRequests_201303_Partition',  @objtype = 'OBJECT';

查询的结果似乎是正确的,服务器将快速执行它。

但是执行计划的根节点有一个警告:

表达式中的类型转换(CONVERT_IMPLICIT(nvarchar(128),[o]。[名称],0))可能会影响查询计划选择中的“ CardinalityEstimate”

在这种情况下是什么意思?如此复杂的过滤器会混淆优化器吗?我应该担心吗?


2
COLLATE Latin1_General_BIN2使上表达checks.nameunsargable。对于您的特定查询,不确定是否会对基数估计值产生多少影响。
马丁·史密斯

2
假设二COLLATE是只有在那里做的范围内表达正常工作,你可以替换N'[0-9A-F]')使用N'[0123456789ABCDEF]',丢弃COLLATE Latin1_General_BIN2
马丁·史密斯

Answers:


16

查询的结果似乎是正确的,服务器将快速执行它。

但是执行计划的根节点有一个警告:

表达式中的类型转换(CONVERT_IMPLICIT(nvarchar(128),[o]。[名称],0))可能会影响查询计划选择中的“ CardinalityEstimate”

在这种情况下是什么意思?如此复杂的过滤器会混淆优化器吗?我应该担心吗?

该警告仅供参考。如果查询执行缓慢,或者您发现基数估计不正确,则警告将为您提供有关在何处寻找可能原因的信息。

该警告由用于排序规则更改的隐式转换触发。如果使用归类是获得正确结果的最简单方法,请随时保留它。或者,如果您解释了为什么需要它的更多信息,则有人会建议您。

顺便说一句,REPLACE可以将替换为:

REPLICATE(N'[0-9A-F]', 8);

(此答案是对该问题的评论的摘要。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.