对SQL Server 2016中包含SUBSTRING()的谓词的估计值的更改吗?


13

是否有任何有关SQL Server 2016更改的文档或研究,以了解如何估计包含SUBSTRING()或其他字符串函数的谓词的基数?

我要问的原因是我正在查看一个在兼容模式130下性能下降的查询,原因与与包含调用SUBSTRING()的WHERE子句匹配的行数估计值的更改有关。我已通过查询重写纠正了此问题,但我想知道是否有人知道SQL Server 2016中有关此区域更改的任何文档。

演示代码如下。在此测试用例中,估计值非常接近,但准确性取决于数据。

在测试用例中,在兼容级别120中,SQL Server似乎正在使用直方图进行估计,而在兼容级别130中,SQL Server似乎假定表中有固定的10%匹配。

CREATE DATABASE MyStringTestDB;
GO
USE MyStringTestDB;
GO
DROP TABLE IF EXISTS dbo.StringTest;
CREATE TABLE dbo.StringTest ( [TheString] varchar(15) );
GO
INSERT INTO dbo.StringTest
VALUES
( 'Y5_CLV' );
INSERT INTO dbo.StringTest
VALUES
( 'Y5_EG3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_NE' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_PQT' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_T2V' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_TT4' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_ZKK' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_LW6' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_QO3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_TZ7' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_UZZ' );

CREATE CLUSTERED INDEX IX_Clustered ON dbo.StringTest (TheString);

/* 
Uses fixed % for estimate; 1.1 rows estimated in this case.
    Plan for computation:
        CSelCalcFixedFilter (0.1) <----
            Selectivity: 0.1
*/
ALTER DATABASE MyStringTestDB SET compatibility_level = 130;
GO
SELECT * 
FROM dbo.StringTest 
WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);

/* 
Uses histogram to get estimate of 1
 CSelCalcPointPredsFreqBased <----
      Distinct value calculation:
          CDVCPlanLeaf
              0 Multi-Column Stats, 1 Single-Column Stats, 0 Guesses
      Individual selectivity calculations:
          (none)
    Loaded histogram for column QCOL: [DBA].[dbo].[StringTest].TheString from stats with id 1
*/
ALTER DATABASE MyStringTestDB SET compatibility_level = 120;
GO
SELECT * 
FROM dbo.StringTest 
WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);

/*
-- Simpler rewrite; works fine in both compat levels and gets better estimate.
SELECT * 
FROM dbo.StringTest 
WHERE TheString LIKE 'ZZ[_]%'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);
*/

1
不确定特定的问题,但是如果Y5_EG3字符串只是代码并且始终是大写,那么您可以随时尝试指定二进制排序规则- Latin1_General_100_BIN2可以提高筛选操作的速度。只需添加COLLATE Latin1_General_100_BIN2CREATE TABLE语句之后varchar(15)。我很想知道它是否还会影响计划的生成/估算。
所罗门·鲁兹基

Answers:


8

我不知道任何文档。我确实对此进行了调查,并提出了一些意见,但是这些意见太长了,无法发表评论。

10%的估计值并不总是退化。请看下面的例子。

TRUNCATE TABLE dbo.StringTest

INSERT INTO dbo.StringTest
SELECT TOP (1000000) 'ZZ_' + LEFT(NEWID(), 12)
FROM   master..spt_values v1,
       master..spt_values v2;

以及WHERE您问题中的子句。

WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'

该表包含一百万行。它们都与谓词匹配。在兼容级别130下,10%的猜测得出的估计值为100,000。在120以下,估算的行是1.03913。

120行为使用直方图,但仅用于获得不同的行数。在我的情况下,密度向量显示为1.039131E-06,并将其乘以表基数即可得出估计的行数。实际上,所有值都是不同的,但都与谓词匹配。

跟踪query_optimizer_estimate_cardinality扩展事件表明在130以下有两个不同的<StatsCollection Name="CStCollFilter"事件。第一个估计为100,000。第二个加载直方图,并使用CSelCalcPointPredsFreqBased / DistinctCountCalculator获得1.04估算值。第二个结果似乎未使用。

您观察到的行为在130中并不一致。我补充说,ORDER BY TheString这对于130估计器来说是一个明显的胜利,因为120努力为一行分配内存,但是这一微小的变化足以使估计的行减少到130盒也为1.03913。

加法OPTION (QUERYRULEOFF SelectToFilter)会将进入排序的估算值还原为100,000,但内存授权不会增加,并且来自排序的估算值仍基于表的不同值。

在此处输入图片说明

类似地,调整并行度的成本阈值,以使查询获得并行计划在130个案例中足以恢复为较低的估计值。相加QUERYTRACEON 8757也会导致较低的估算值。看起来10%的估算仅保留用于微不足道的计划。

您建议用

WHERE TheString LIKE 'ZZ[_]%'

两者都显示出更好的估计。输出是

  CSelCalcTrieBased

      Column: QCOL: [MyStringTestDB].[dbo].[StringTest].TheString

显示它使用了try。有关此的更多信息,请参见此处的字符串摘要统计信息部分。

但是,它与原始查询不同。由于_现在假定第一个实例始终是第三个字符,而不是动态找到。

如果此假设已硬编码到您的原始查询中

 WHERE SUBSTRING(TheString, 1, 3) = 'ZZ_'

估计方法更改为CSelCalcHistogramComparison(INTERVAL),并且估计的行变得准确。

能够将其转换为范围

WHERE TheString >=  'ZZ_' AND TheString < ???

并使用直方图估算该范围内的值的行数。

但是,这仅适用于基数估计。LIKE更好,因为它可以在运行时使用范围查找。SUBSTRING(TheString, 1, 3)LEFT(TheString, 3)不能。

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.