列存储聚合下推不适用于浮点/真实数据类型

Ale*_*rov 6 performance sql-server aggregate columnstore sql-server-2016

我对float/real数据类型的聚合下推有问题。根据文档,“任何数据类型 <= 64 位”或 8 字节 () 支持聚合下推:

  • 支持的聚合运算符有 MIN、MAX、SUM、COUNT、AVG
  • 支持任何 <= 64 位的数据类型。例如,支持 bigint 是因为它的大小是 8 个字节,但不支持十进制 (38,6),因为它的大小是 17 个字节。此外,不支持字符串类型
  • 聚合运算符必须位于 SCAN 节点或带有 group by 的 SCAN 节点之上

无论我做什么,它都不起作用。我尝试使列可以为空而不为空。分组和无分组。

我们在最新版本的 SQL Server 2016 (SP1-CU3) 上运行。我想知道有人经历过吗?这对我来说似乎是一个错误。我错过了什么吗?

如果您遇到同样的问题,请为我的 SQL Server 反馈请求点赞。现在我面临着将float列转换为numeric. 但是numeric类型的操作通常比较慢。所以我可能在一个地方赢了,在另一个地方输了。我已成功测试numeric(15,12)

这是说明问题的脚本(请启用实际执行计划以查看问题):

DROP TABLE IF EXISTS dbo.TestTable;

CREATE TABLE dbo.TestTable 
(
     cKey             INT               NOT NULL
   , cGroup           INT               NOT NULL
   , cNumeric36_3     NUMERIC(36, 3)    NULL
   , cNumeric18_3     DECIMAL(18, 3)    NULL
   , cNumeric18_9     DECIMAL(18, 9)    NULL
   , cNumeric15_12    DECIMAL(15, 12)   NULL
   , cMoney           MONEY             NULL
   , cFloat53         FLOAT(53)         NULL
   , cFloat53Less1    FLOAT(53)         NULL
   , cFloat24         FLOAT(24)         NULL
   , cReal            REAL              NULL
);

;WITH _Numbers0 AS (
    SELECT TOP 3000  column_id  FROM  sys.all_columns 
)
, _Numbers AS (
    SELECT cKey = ROW_NUMBER() OVER (ORDER BY (SELECT 1))
    FROM _Numbers0 a CROSS JOIN _Numbers0 b
)
, _Keys AS (
    SELECT
            cKey = n.cKey
          , Divder10    = CONVERT(INT, FLOOR(CHECKSUM(NewId()) % 10))
          , Divder100   = CONVERT(INT, FLOOR(CHECKSUM(NewId()) % 100))
          , Divder10000 = CONVERT(INT, FLOOR(CHECKSUM(NewId()) % 10000))
    FROM _Numbers n
)
, _RandomValues AS 
(
    SELECT 
          cKey  
        , cGroup        = ABS(CHECKSUM(NewId())) % 100          
        , cNumeric36_3  = CONVERT(NUMERIC(36,3) , CHECKSUM(NewId())           )                         / CONVERT(NUMERIC(36,3) , NULLIF(Divder10000          , 0.00))
        , cNumeric18_3  = CONVERT(NUMERIC(18,3) , CHECKSUM(NewId())           )                         / CONVERT(NUMERIC(36,3) , NULLIF(Divder100            , 0.00))
        , cNumeric18_9  = CONVERT(NUMERIC(18,9) , CHECKSUM(NewId()) % 1000000 )                         / CONVERT(NUMERIC(36,3) , NULLIF(Divder10000          , 0.00))
        , cNumeric15_12 = CONVERT(NUMERIC(15,12), CHECKSUM(NewId()) % 100     )                         / CONVERT(NUMERIC(36,3) , NULLIF(Divder10000          , 0.00))
        , cMoney        = CONVERT(MONEY, CHECKSUM(NewId()))                                             / CONVERT(MONEY         , NULLIF(Divder10000          , 0.00))
        , cFloat53      = CONVERT(FLOAT, CHECKSUM(NewId())) * CONVERT(FLOAT, CHECKSUM(NewId()))         / CONVERT(FLOAT(53)     , NULLIF(Divder10000          , 0.00))
        , cFloat53Less1 = CONVERT(FLOAT, 1.00)                                                          / CONVERT(FLOAT(53)     , NULLIF(CHECKSUM(NewId())    , 0.00))
        , cFloat24      = CONVERT(FLOAT(24), CHECKSUM(NewId())) * CONVERT(FLOAT(24), CHECKSUM(NewId())) / CONVERT(FLOAT(24)     , NULLIF(Divder10000          , 0.00))
        , cReal         = CONVERT(REAL, CHECKSUM(NewId())) * CONVERT(REAL, CHECKSUM(NewId()))           / CONVERT(REAL          , NULLIF(Divder10000          , 0.00))
    FROM _Keys
)
INSERT INTO dbo.TestTable 
SELECT *       
FROM _RandomValues
GO

CHECKPOINT;
GO

CREATE CLUSTERED COLUMNSTORE INDEX IDXCC_dboTestTable
    ON dbo.TestTable WITH (MAXDOP = 4);
GO

SELECT COUNT(*) 
FROM dbo.TestTable tt
GO

SELECT MAX(tt.cNumeric36_3) FROM dbo.TestTable tt;
SELECT MAX(tt.cNumeric18_3) FROM dbo.TestTable tt;
SELECT MAX(tt.cNumeric18_9) FROM dbo.TestTable tt;
SELECT MAX(tt.cNumeric15_12) FROM dbo.TestTable tt;
SELECT MAX(tt.cMoney) FROM dbo.TestTable tt;
SELECT MAX(tt.cFloat53) FROM dbo.TestTable tt;
SELECT MAX(tt.cFloat53Less1) FROM dbo.TestTable tt;
SELECT MAX(tt.cFloat24) FROM dbo.TestTable tt;
SELECT MAX(tt.cReal) FROM dbo.TestTable tt;
GO
Run Code Online (Sandbox Code Playgroud)

Joe*_*ish 8

Microsoft 已更新文档以说明不支持浮动*。

聚合下推的文档在某些地方不准确,并且没有说明所有限制。在我一周前进行的一些测试中,我还发现不支持浮点类型。除此之外,numeric(10,0)尽管需要九个字节的存储空间,但仍受支持。以下是我所知道的受支持数据类型的最准确摘要:

支持所有日期和时间数据类型,但datetimeoffset. 支持所有小于 10 字节的精确数字数据类型。

如果您想排除更多故障,您可以通过query_execution_dynamic_push_down_statistics扩展事件发现一些问题。

在情况下,它的兴趣,你可以阅读一些我周围聚集在下推我的博客文章中发现的局限性这里。Paul White 还撰写了有关Grouped Aggregate Pushdown的详细信息。


* float和real现在看起来与骨料下推工作COUNT,并COUNT_BIG仅在SQL Server 2017年16 CU(可能更早)。其他以前不受支持的类型,如 datetimeoffset 和精度 > 18 的数字也可以使用,只要数据(以批处理格式)在运行时适合 64 位。