列儲存聚合下推不適用於浮點/真實數據類型
我在
float/real
數據類型的聚合下推方面遇到問題。根據文件,“任何數據類型 <= 64 位”或 8 字節()支持聚合下推:
- 支持的聚合運算符有 MIN、MAX、SUM、COUNT、AVG
- 支持任何 <= 64 位的數據類型。例如,支持 bigint 是因為它的大小是 8 個字節,但十進制 (38,6) 不是因為它的大小是 17 個字節。此外,不支持任何字元串類型
- 聚合運算元必須在 SCAN 節點或 SCAN 節點之上,group by
無論我做什麼,它都不起作用。我嘗試使列可以為空而不是空。分組和無分組。
我們在最新版本的 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 已更新文件以說明不支持浮動*。
聚合下推的文件在某些地方不准確,並且沒有說明所有限制。在我一周前進行的一些測試中,我還發現不支持浮點類型。除此之外,
numeric(10,0)
儘管需要九個字節的儲存空間,但仍受支持。這是我所知道的受支持數據類型的最準確摘要:支持除 之外的所有日期和時間數據類型
datetimeoffset
。如果它們小於 10 個字節,則支持所有精確的數字數據類型。如果您想解決更多問題,您可以通過
query_execution_dynamic_push_down_statistics
擴展事件發現一些問題。如果有興趣,您可以在此處的部落格文章中閱讀我發現的關於聚合下推的一些限制。Paul White 還寫過有關Grouped Aggregate Pushdown的詳細資訊。
COUNT
* 浮點數和實數現在似乎COUNT_BIG
僅適用於 SQL Server 2017 CU 16(可能更早)的聚合下推。只要數據(批處理格式)在執行時適合 64 位,其他以前不受支持的類型(如 datetimeoffset 和精度 > 18 的數字)也可以使用。