为啥索引视图不能有 MAX() 聚合?
Posted
技术标签:
【中文标题】为啥索引视图不能有 MAX() 聚合?【英文标题】:Why can't indexed views have a MAX() aggregate?为什么索引视图不能有 MAX() 聚合? 【发布时间】:2011-01-09 05:15:59 【问题描述】:我一直在尝试一些索引视图并印象深刻,但我几乎总是需要一个最大值或一个最小值,并且无法理解为什么它不适用于这些,谁能解释为什么?
我知道他们是不允许的,我就是不明白为什么!!!计数等是允许的,为什么不是 MIN/MAX,我正在寻找解释...
【问题讨论】:
【参考方案1】:如果您只想在使用视图时查看排序的内容而不添加排序依据,我只需在其中添加一列并排序。
id = row_number() over (order by col1, col2)
【讨论】:
【参考方案2】:不允许使用这些聚合,因为它们不能仅根据更改的值重新计算。
某些聚合,如COUNT_BIG()
或SUM()
,只需查看更改的数据即可重新计算。这些在索引视图中是允许的,因为如果基础值发生更改,则可以直接计算该更改的影响。
其他聚合,如 MIN()
和 MAX()
,不能仅通过查看正在更改的数据来重新计算。如果您删除当前为最大值或最小值的值,则必须在 整个 表中搜索并找到新的最大值或最小值。
同样的原则适用于其他聚合,例如 AVG()
或标准变体聚合。 SQL 不能仅根据更改的值重新计算它们,而是需要重新扫描整个表以获取新值。
【讨论】:
如果您将表限制为仅允许insert
操作,而不是 update
或 delete
,则可以支持它们。 (如果你想做其中一个,你必须删除索引视图并在之后重新创建它。)很多表在实际使用中是只插入的,并且会受益于加速max
和min
查询。
实际上改变的行只能和缓存的数据结果比较,选择最高的MAX和最低的MIN。为什么他们不这样做?
@Iúri dos Anjos 因为如果您更新了曾经是 MAX 的行并使其变小,那么它仍然必须扫描整个表的其余部分以查找较低的值。所以你想知道“我为什么不做决定!!”我想这归结为保证性能,允许的操作仅在该单行上运行,如果您允许运行 MAX,则每次插入时可能会扫描一百万行。但是,如果您期望 MAX 值只会增加(就像我的数据一样),那绝对是一种痛苦
我对 AVG 有点困惑。既然支持 Count_BIG 和 SUM,为什么不支持 AVG?无需重新扫描。
您可以通过分别存储总和和总计 SUM(CatsQty) AS TotalCats, COUNT_BIG(*) AS TotalCount
并在您的 SELECT 中使用 SELECT TotalCats / TotalCount AS AverageCatsQty FROM AnimalsView
立即计算它来制作自己的 AVG。当然,这只是 MEAN 平均值。【参考方案3】:
除了 Remus 指定的原因之外,支持 MIN 和 MAX 的实际需求较少。与 COUNT() 或 SUM() 不同,MAX 和 MIN 的计算速度很快 - 只需一次查找即可完成;您不需要读取大量数据。
【讨论】:
可能是有充分理由需要 MIN 或 MAX 的人。我在寻找创建这样一个索引的方法时发现了这个问题,因为它需要从几分钟到几秒钟的查询。手动维护它似乎是唯一的解决方案,但它不是我特别喜欢的...... 我会详细说明 :-) 你倒过来了。关键是在创建索引时,所有的 COUNT、SUM、MAX 和 MIN 都很简单,并且都需要相同的时间。但是当你添加、删除或更新一行时,都需要重新计算。因此,对于 COUNT,如果您删除了,那么您只需减去一个,对于 SUM,如果您添加一行,您只需将相应行的值添加到“运行总计”中。但是,对于 MAX 和 MIN,如果新插入或更改的值在 MIN 到 MAX 的当前范围内,您将始终需要进行扫描。这可能是数百万条记录,可能会阻塞。等等等等。 我也不确定你所说的“不太实际的需要”是什么意思。它们是否常见或是否需要将完全取决于您的数据代表什么。 @Simon_Weaver ... 这只是部分正确。如果要添加一行,则可以将当前值与存储的最小值/最大值进行比较,因为先前的记录与当前存储的值是确定性的。如果要删除一行,则仅当当前值等于当前最小值或最大值时才需要重新计算所有行。添加案例对计数/总和没有有效差异,而删除行产生影响的机会相当有限。【参考方案4】:索引视图不支持 MIN/MAX 等聚合函数。您必须在围绕视图的查询中执行 MIN/MAX。
关于索引视图here (SQL 2005) 中允许和不允许的内容的完整定义。 引用:
AVG、MAX、MIN、STDEV、STDEVP、VAR、 或 VARP 聚合函数。如果 AVG(表达式)在 引用索引视图的查询, 优化器可以经常计算 如果视图选择所需的结果 列表包含 SUM(表达式) 和 COUNT_BIG(表达式)。例如,一个 索引视图 SELECT 列表不能 包含表达式 AVG(column1)。 如果视图 SELECT 列表包含 表达式 SUM(column1) 和 COUNT_BIG(column1),SQL Server 可以 计算查询的平均值 引用视图并指定 AVG(第 1 列)。
【讨论】:
这篇文章没有回答 OP 的为什么 MIN/MAX 是不允许的问题。以上是关于为啥索引视图不能有 MAX() 聚合?的主要内容,如果未能解决你的问题,请参考以下文章