web-dev-qa-db-ja.com

列ストア集計プッシュダウンは、float / realデータ型では機能しません

_float/real_データ型の集約プッシュダウンに問題があります。 ドキュメント によると、「すべてのデータ型<= 64ビット」または8バイト()に対して集約プッシュダウンがサポートされています。

  • サポートされている集計演算子は、MIN、MAX、SUM、COUNT、AVGです。
  • 64ビット以下の任意のデータ型がサポートされています。たとえば、bigintはサイズが8バイトであるためサポートされていますが、10進数(38,6)はサイズが17バイトであるためサポートされていません。また、文字列型はサポートされていません
  • 集計演算子はSCANノードまたはグループ化されたSCANノードの上にある必要があります

私が何をしてもそれは機能しません。列をnull可能にし、nullにしないようにしました。グループ化とグループ化なし。

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
_

Microsoftは documentation を更新し、floatがサポートされていないことを示しました*。

集計プッシュダウンのドキュメントは、一部の場所で不正確であり、すべての制限が記載されていません。 1週間前に行ったいくつかのテストで、float型がサポートされていないこともわかりました。さらに、numeric(10,0)は、9バイトのストレージを必要とするにもかかわらずサポートされています。サポートされているデータ型の最も正確な概要は次のとおりです。

datetimeoffsetを除くすべての日時データ型がサポートされています。 10バイト未満の場合、すべての正確な数値データ型がサポートされます。

さらにトラブルシューティングを行う場合は、query_execution_dynamic_Push_down_statistics拡張イベントを使用して何かを発見できる可能性があります。

興味がある場合は、私のブログ投稿 here で、集約プッシュダウンに関して見つけたいくつかの制限について読むことができます。 Paul Whiteは Grouped Aggregate Pushdown の詳細についても書いています。


* Floatとrealは、SQL Server 2017 CU 16(およびそれ以前)でのみ、COUNTおよびCOUNT_BIGの集約プッシュダウンで動作するように見えます。実行時にデータ(バッチ形式)が64ビットに収まる限り、datetimeoffsetや18を超える精度の数値など、以前はサポートされていなかった他の型も機能します

8
Joe Obbish