在SQL Server中,如何按照varbinary(MAX)或varchar(MAX)进行分组?

5
在SQL Server 2008 R2 Books Online中,暗示分组列的最大列大小为8060字节。
对于不包含CUBE或ROLLUP的GROUP BY子句,group_by_expression项的数量受到GROUP BY列大小、聚合列以及查询中涉及的聚合值的限制。该限制源于中间工作表上的8060字节限制,该工作表用于保存中间查询结果。
但是,可以通过varbinary(max)列进行分组。
create table dbo.T(
  name varchar(100),
  info varbinary(max)
);
insert into dbo.T values ('aardvark', Convert(varbinary(max),Replicate(Convert(varchar(max),'A'),100000)))
select info, count(*) from T group by info;

以上在SQL Server 2008 R2中运行良好,预计在后续版本也是如此。我是否误读了Books Online?有人知道是否允许按大对象类型分组吗?我已经尝试谷歌搜索,但没有结果。


1
此限制可能不会被明确执行或检查。尝试在这些列中编写>8k字节并运行您的代码。 - Stoleg
@Stoleg,它仍然可以正常工作。 - Martin Smith
1个回答

2

如果使用固定宽度的数据类型,你更容易遇到这个问题,因为它们总是存储在行中。可变长度的类型可以通过指向实际值的指针存储在行外。

CREATE TABLE #T
  (
     C CHAR(4027) DEFAULT REPLICATE('A', 4027)
  );

INSERT INTO #T
DEFAULT VALUES;

SELECT COUNT(*)
FROM   #T T1
       CROSS JOIN #T T2
GROUP  BY T1.C,
          T2.C

查询处理器无法生成查询计划,因为需要一个工作表,并且其最小行大小超过了最大允许的8060个字节。查询中需要工作表的典型原因是GROUP BY或ORDER BY子句。如果查询具有GROUP BY或ORDER BY子句,请考虑减少子句中字段的数量和/或大小。考虑使用字段的前缀(LEFT())或哈希(CHECKSUM())进行分组或前缀进行排序。但请注意,这将更改查询的行为。
但以下内容成功执行。
SELECT COUNT(*)
FROM   #T T1
       CROSS JOIN #T T2
GROUP  BY CAST(T1.C AS VARCHAR(4027)),
          CAST(T2.C AS VARCHAR(4027)) 

您可以按最多308个varchar(max)列进行分组 - 每列仅存储26字节(指向值和其他开销)(查看链接)。
以下代码会失败:

Cannot create a row of size 8078 which is greater than the allowable maximum row size of 8060.

但是,如果删除任何一个GROUP BY列,则会成功,因为8078-26小于8060。
注:每个单独的列具有消耗10,000字节的值,但这些值存储在行外,与上述计算无关。
drop TABLE #T

GO

CREATE TABLE #T
(
 C0 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C1 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C2 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C3 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C4 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C5 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C6 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C7 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C8 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C9 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C10 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C11 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C12 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C13 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C14 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C15 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C16 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C17 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C18 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C19 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C20 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C21 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C22 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C23 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C24 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C25 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C26 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C27 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C28 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C29 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C30 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C31 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C32 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C33 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C34 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C35 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C36 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C37 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C38 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C39 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C40 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C41 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C42 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C43 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C44 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C45 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C46 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C47 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C48 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C49 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C50 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C51 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C52 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C53 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C54 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C55 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C56 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C57 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C58 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C59 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C60 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C61 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C62 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C63 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C64 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C65 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C66 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C67 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C68 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C69 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C70 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C71 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C72 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C73 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C74 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C75 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C76 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C77 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C78 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C79 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C80 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C81 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C82 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C83 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C84 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C85 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C86 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C87 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C88 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C89 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C90 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C91 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C92 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C93 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C94 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C95 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C96 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C97 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C98 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
,C99 VARCHAR(MAX) DEFAULT REPLICATE(CAST('X' AS VARCHAR(MAX)),10000)
)


INSERT INTO #T DEFAULT VALUES


SELECT COUNT(*)
FROM #T T1,
     #T T2,
     #T T3,
     #T T4
GROUP BY 
 T1.C0
,T1.C1
,T1.C2
,T1.C3
,T1.C4
,T1.C5
,T1.C6
,T1.C7
,T1.C8
,T1.C9
,T1.C10
,T1.C11
,T1.C12
,T1.C13
,T1.C14
,T1.C15
,T1.C16
,T1.C17
,T1.C18
,T1.C19
,T1.C20
,T1.C21
,T1.C22
,T1.C23
,T1.C24
,T1.C25
,T1.C26
,T1.C27
,T1.C28
,T1.C29
,T1.C30
,T1.C31
,T1.C32
,T1.C33
,T1.C34
,T1.C35
,T1.C36
,T1.C37
,T1.C38
,T1.C39
,T1.C40
,T1.C41
,T1.C42
,T1.C43
,T1.C44
,T1.C45
,T1.C46
,T1.C47
,T1.C48
,T1.C49
,T1.C50
,T1.C51
,T1.C52
,T1.C53
,T1.C54
,T1.C55
,T1.C56
,T1.C57
,T1.C58
,T1.C59
,T1.C60
,T1.C61
,T1.C62
,T1.C63
,T1.C64
,T1.C65
,T1.C66
,T1.C67
,T1.C68
,T1.C69
,T1.C70
,T1.C71
,T1.C72
,T1.C73
,T1.C74
,T1.C75
,T1.C76
,T1.C77
,T1.C78
,T1.C79
,T1.C80
,T1.C81
,T1.C82
,T1.C83
,T1.C84
,T1.C85
,T1.C86
,T1.C87
,T1.C88
,T1.C89
,T1.C90
,T1.C91
,T1.C92
,T1.C93
,T1.C94
,T1.C95
,T1.C96
,T1.C97
,T1.C98
,T1.C99

,T2.C0
,T2.C1
,T2.C2
,T2.C3
,T2.C4
,T2.C5
,T2.C6
,T2.C7
,T2.C8
,T2.C9
,T2.C10
,T2.C11
,T2.C12
,T2.C13
,T2.C14
,T2.C15
,T2.C16
,T2.C17
,T2.C18
,T2.C19
,T2.C20
,T2.C21
,T2.C22
,T2.C23
,T2.C24
,T2.C25
,T2.C26
,T2.C27
,T2.C28
,T2.C29
,T2.C30
,T2.C31
,T2.C32
,T2.C33
,T2.C34
,T2.C35
,T2.C36
,T2.C37
,T2.C38
,T2.C39
,T2.C40
,T2.C41
,T2.C42
,T2.C43
,T2.C44
,T2.C45
,T2.C46
,T2.C47
,T2.C48
,T2.C49
,T2.C50
,T2.C51
,T2.C52
,T2.C53
,T2.C54
,T2.C55
,T2.C56
,T2.C57
,T2.C58
,T2.C59
,T2.C60
,T2.C61
,T2.C62
,T2.C63
,T2.C64
,T2.C65
,T2.C66
,T2.C67
,T2.C68
,T2.C69
,T2.C70
,T2.C71
,T2.C72
,T2.C73
,T2.C74
,T2.C75
,T2.C76
,T2.C77
,T2.C78
,T2.C79
,T2.C80
,T2.C81
,T2.C82
,T2.C83
,T2.C84
,T2.C85
,T2.C86
,T2.C87
,T2.C88
,T2.C89
,T2.C90
,T2.C91
,T2.C92
,T2.C93
,T2.C94
,T2.C95
,T2.C96
,T2.C97
,T2.C98
,T2.C99


,T3.C0
,T3.C1
,T3.C2
,T3.C3
,T3.C4
,T3.C5
,T3.C6
,T3.C7
,T3.C8
,T3.C9
,T3.C10
,T3.C11
,T3.C12
,T3.C13
,T3.C14
,T3.C15
,T3.C16
,T3.C17
,T3.C18
,T3.C19
,T3.C20
,T3.C21
,T3.C22
,T3.C23
,T3.C24
,T3.C25
,T3.C26
,T3.C27
,T3.C28
,T3.C29
,T3.C30
,T3.C31
,T3.C32
,T3.C33
,T3.C34
,T3.C35
,T3.C36
,T3.C37
,T3.C38
,T3.C39
,T3.C40
,T3.C41
,T3.C42
,T3.C43
,T3.C44
,T3.C45
,T3.C46
,T3.C47
,T3.C48
,T3.C49
,T3.C50
,T3.C51
,T3.C52
,T3.C53
,T3.C54
,T3.C55
,T3.C56
,T3.C57
,T3.C58
,T3.C59
,T3.C60
,T3.C61
,T3.C62
,T3.C63
,T3.C64
,T3.C65
,T3.C66
,T3.C67
,T3.C68
,T3.C69
,T3.C70
,T3.C71
,T3.C72
,T3.C73
,T3.C74
,T3.C75
,T3.C76
,T3.C77
,T3.C78
,T3.C79
,T3.C80
,T3.C81
,T3.C82
,T3.C83
,T3.C84
,T3.C85
,T3.C86
,T3.C87
,T3.C88
,T3.C89
,T3.C90
,T3.C91
,T3.C92
,T3.C93
,T3.C94
,T3.C95
,T3.C96
,T3.C97
,T3.C98
,T3.C99
,T4.C0
,T4.C1
,T4.C2
,T4.C3
,T4.C4
,T4.C5
,T4.C6
,T4.C7
,T4.C8

那么,可以这样说吗?由于varchar(max)和varbinary(max)是存储在行外的,它们只使用指针大小的GROUP BY行大小限制,而不是实际数据。这似乎就是正在发生的事情。 - Ubercoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接