如果数据库只有一个插入,那么索引每个可能的列组合是否不好?


23

我正在一个需要大量选择查询的报表系统上工作,但是该报表系统基于仅填充一次的数据库。数据库管理系统是Microsoft SQL Server2017。可能有更好的方法来设计这样的系统,但让我们从理论上解决这个问题。

从理论上讲:

  1. 如果我们有一个非常大的数据库(几张表上有1.5亿行)
  2. 我们可以假设数据库只会被填充一次。

索引每个可能的列组合是否会对选择查询产生负面的性能影响?


4
通常,每种可能的组合都不切实际。一种更明智的方法是手动索引但非常慷慨。那绝对是有道理的。
usr

12
我建议您改写您的标题或粗体文本,以便它们保持一致。乍一看,我对最高投票的答案是“是”感到困惑
-aaaaaa

对于一个表,1.5亿行大,但对于数据库却不大。实际上,报告系统仅使用可能的列组合的一小部分,最好至少一开始就将重点放在键组合上,然后仅在需要时使其更为复杂。
pojo-guy

Answers:


36

是的,这将影响初始计划的编译时间,因为优化器将具有许多额外的数据访问路径以供考虑。

由于您使用的是SQL Server 2017,因此只能加载一次并运行报告,为什么不只使用集群列存储索引呢?

对于您需要为每种可能的列组合编制索引的索引,这似乎是理想的解决方案。

列存储索引-概述


我也想去Columnstore,但是我只是想知道……优化器的工作与您描述的相反吗?我的意思是不是扫描可用的索引并“想知道”它们中的哪一个有用,是不是例如扎扎明查询和“认为”该查询的完美索引,然后它检查是否存在?(如果没有,则会生成丢失的索引消息。)如果我是对的(我不知道,只是猜测),那么即使有大量的索引,它的出现时间也不应该比仅包含几个索引的时间长得多。其中。
利蒙卡

26

如果表中有N列,则每种可能的列组合都是2 ^ N-1(除去空集)。对于表示1023个索引的10列,对于20列,我们最终得到1048575个索引。大多数索引将永远不会使用,但优化程序必须将其考虑在内。优化器可能会选择次优索引而不是更好的索引。我不会采用生成各种索引的方法,而不会尝试找出哪些索引实际上是有益的。

编辑更正的可能索引数

正如Jeff指出的那样,由于(3,2,1)明显不同于(1,2,3),因此它甚至比2 ^ N(幂集)还差。对于N列,我们可以选择以N种方式包含所有列的索引中的第一个位置。对于以N-1方式表示的第二个位置,依此类推。因此,我们最终得到N!全尺寸的不同索引。这些索引中没有一个被该集合中的另一个索引归类。另外,我们不能添加另一个较短的索引,这样它就不会被任何完整的索引覆盖。因此,索引数为N!。因此,10列的示例变为10!= 3628800索引,对于20(鼓)为2432902008176640000索引。这是一个非常荒谬的数字,如果我们为每个索引的一个点放置一个点,每个点的长度为1毫米,则光束需要94天才能通过所有点。全部,全部;-)


6
更糟糕的是:索引中列的顺序可能很重要。因此,您获得的最大值为N!索引。
杰夫

2
但是您不需要作为其他索引前缀的索引。
Barmar

3
更糟的是。每个索引都有ASC和DESC组合。
ypercubeᵀᴹ

2
更糟糕的是,有INCLUDE索引。
ypercubeᵀᴹ

2
以及大量的局部索引。
ypercubeᵀᴹ

7

没有。

为“所有”建立索引是不实际的,但是您可以为“所有”建立索引。

就是这个 如果表中有N列,则可能的索引数为N!。假设一个表有10列,那么您不仅有10可能的索引,而且还有10!。一张桌子上就是3,628,800 ...。那是很多磁盘空间,磁盘I / O,缓存和查找时间。

为什么?原因如下:

  • 轻量级索引通常会被缓存,这会使它们快速变亮。如果您有300万,则将不会对其进行缓存。

  • SQL优化器可能会花费大量时间来决定使用哪个更好,特别是在使用连接时。

  • SQL优化器可能会放弃使用综合算法,而尝试使用启发式算法。这可能是“不够理想”。例如,PostgreSQL对于“少于8个表查询”和“大于8个表查询”具有不同的选项。

  • 索引应该比堆轻。如果您正在对所有内容建立索引,那么索引将变得像堆一样重...这有损于索引的目的。


数字不是2 ^ 10吗?每列都包含在给定索引中或从给定索引中排除。顺序重要吗?
RemcoGerlich

2
@RemcoGerlich是的,顺序很重要。
ypercubeᵀᴹ

2

不,它可能不会对SELECT查询产生负面影响,但是

  • 这将导致高磁盘使用率。
  • 它将大大增加INSERT成本。
  • 您的大多数索引将永远不会使用。
  • 许多 WHERE条件表达式仍然不使用索引,主要是更复杂的条件。
  • 所需索引的数量将随着列的数量呈指数增加。例如,如果您有8列,则所有可能的组合都需要256个索引。

它可能完全导致编译时出现问题。
Erik Darling

@sp_BlitzErik您是否认为应用程序中的ORM?
彼得说恢复莫妮卡

不,请看我的答案。
Erik Darling

@sp_BlitzErik哇,很高兴见到!
彼得说恢复莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.