_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を超える精度の数値など、以前はサポートされていなかった他の型も機能します 。