Database 甲骨文索引几乎没有加速聚合计算

Database 甲骨文索引几乎没有加速聚合计算,database,oracle,indexing,Database,Oracle,Indexing,我创建了一个包含两列a和b的表。a列只是1到1亿之间的数字。列b是介于0和999(含0和999)之间的随机整数。我想用这个表来检查索引如何改进计算。因此,我检查了以下内容: select count(*) from my_table where b = 332 select avg(a) from my_table where b = 387 332和387只是随机整数,我想确定它没有缓存任何东西,所以我切换了它 然后我创建了一个索引: create bitmap index myindx

我创建了一个包含两列a和b的表。a列只是1到1亿之间的数字。列b是介于0和999(含0和999)之间的随机整数。我想用这个表来检查索引如何改进计算。因此,我检查了以下内容:

select count(*) from my_table where b = 332 

select avg(a) from my_table where b = 387
332和387只是随机整数,我想确定它没有缓存任何东西,所以我切换了它

然后我创建了一个索引:

create bitmap index myindx1 on my_table (b);
commit;
这使计数*从14秒下降到75毫秒,成功

但是avga的表现不太好。实际上情况变得更糟了,从8秒到10秒。我没有测试过很多次,根据计划,这看起来是一个侥幸,但至少它似乎没有像我预期的那样做得更好

没有索引的解释计划如下所示:

带有索引的解释计划如下所示:

所以这看起来有点帮助,但平均数字真的比数一数要昂贵得多吗?和做一个完整的表格扫描相比,平均数字要贵得多?我认为这个索引会将我的查询减少到原始成本的一小部分,而不仅仅是减少一点时间。我还能做些什么来加速这个查询吗


谢谢。

问题在于你设置测试的方式——这不现实,对索引也不好

第一:表中只有两个整数列,所以每一行都非常小。因此,Oracle可以将许多行放入每个数据库块中,就像每个数据库块可以容纳几千行一样

第二:您随机创建了索引数据,其值介于0和999之间

把这两个事实放在一起,我们能猜到什么?答:几乎每个数据库块都将至少有一行具有任何给定的B列值

所以,不管你寻找什么样的B值,你都会一次读取表中的每个块,即:顺序读取

与不使用索引(全表扫描)的计划相比,Oracle仍会读取每个块,但会一次读取几个块,即分散读取

难怪你的索引没有帮助

如果您想要更好的测试,请将C列添加到您的测试表中,该测试表仅为200-300个字符的字符串,例如XXXXXXXXX。。。。这将把每个块的行数减少到一个更实际的值,您应该可以从索引中看到更好的收益

最后注意:使用位图索引时要非常小心。它们在具有任何类型的DML插入、更新和删除的表上几乎不可用!在使用之前,请阅读所有关于它们的信息

使现代化 对此的澄清:

所以这看起来有点帮助,但平均数字真的比数一数要昂贵得多吗?和做一个完整的表格扫描相比,平均数字要贵得多

索引帮助COUNT*查询的原因是,索引本身会告诉Oracle有多少行符合条件B=332,因此它不需要读取表块,因此不会遇到我上面描述的问题,即逐个读取每个表块


并不是计数比平均值快。只是在测试中,计数可以仅使用索引计算,而平均值需要从表中获取信息。

问题在于您设置测试的方式-这不现实,对索引不利

第一:表中只有两个整数列,所以每一行都非常小。因此,Oracle可以将许多行放入每个数据库块中,就像每个数据库块可以容纳几千行一样

第二:您随机创建了索引数据,其值介于0和999之间

把这两个事实放在一起,我们能猜到什么?答:几乎每个数据库块都将至少有一行具有任何给定的B列值

所以,不管你寻找什么样的B值,你都会一次读取表中的每个块,即:顺序读取

与不使用索引(全表扫描)的计划相比,Oracle仍会读取每个块,但会一次读取几个块,即分散读取

难怪你的索引没有帮助

如果您想要更好的测试,请将C列添加到您的测试表中,该测试表仅为200-300个字符的字符串,例如XXXXXXXXX。。。。这将把每个块的行数减少到一个更实际的值,您应该可以从索引中看到更好的收益

最后注意:使用位图索引时要非常小心。它们在具有任何类型的DML插入、更新和删除的表上几乎不可用!在使用之前,请阅读所有关于它们的信息

使现代化 对此的澄清:

所以这看起来有点帮助,但平均数字真的比数一数要昂贵得多吗?而且平均数要比全t更昂贵 能扫描吗

索引帮助COUNT*查询的原因是,索引本身会告诉Oracle有多少行符合条件B=332,因此它不需要读取表块,因此不会遇到我上面描述的问题,即逐个读取每个表块


并不是计数比平均值快。只是在测试中,计数可以仅使用索引计算,而平均值需要表中的信息。

位图索引不应在OTLP系统中使用。他们的维修费用太高了

IHMO纯B*树索引就足够了。索引范围扫描从根遍历到最左边的叶起伏值332,然后从左到右迭代访问具有相同值B的所有叶。这就是您想要的


如果你想加快速度,你可以创建所谓的覆盖索引。将B列和A列按此顺序放入索引中。然后,当B匹配时,您将避免在表中查找A的值。如果表中包含许多您不关心的列,则它尤其有用。

位图索引不应在OTLP系统中使用。他们的维修费用太高了

IHMO纯B*树索引就足够了。索引范围扫描从根遍历到最左边的叶起伏值332,然后从左到右迭代访问具有相同值B的所有叶。这就是您想要的


如果你想加快速度,你可以创建所谓的覆盖索引。将B列和A列按此顺序放入索引中。然后,当B匹配时,您将避免在表中查找A的值。如果表中包含许多您不关心的列,则这一点尤其有用。

B*树索引在OP的测试用例中仍然会表现不佳,原因我在回答中已概述。覆盖指数会有所帮助;但是,如果他的测试用例更现实,那就没有必要了/那将是浪费空间。向上投票指出覆盖指数-这是一项有用的技术。但我不想让OP认为他必须创建一个覆盖索引才能使索引工作。基于我在回答中概述的原因,B*树索引在OP的测试用例中仍然会表现糟糕。覆盖指数会有所帮助;但是,如果他的测试用例更现实,那就没有必要了/那将是浪费空间。向上投票指出覆盖指数-这是一项有用的技术。但我不想让OP认为他必须制作一个覆盖索引才能让索引工作。有趣的是,这一切都是有意义的。为了澄清,我简化了我的问题,因为我的实际问题使用了我工作中的机密数据。我的问题实际上涉及一些被一些因素削减的指标。基本上,问题是有太多的因子组合,无法简单地预先聚合每个可能的平均值,但我也不希望用户每次更改因子都要等待几分钟。我之所以做位图索引,是因为我的理解是,在不同值的相对数量较低且没有大量写入/更新的列上,位图索引效果更好。为了我的钱,在最多一个ETL过程之外,不要将大量写入/更新替换为没有写入/更新。您应该从标准的B*树索引开始,看看性能如何。除了位图索引,还有其他方法可以进一步提高性能。为了澄清,我简化了我的问题,因为我的实际问题使用了我工作中的机密数据。我的问题实际上涉及一些被一些因素削减的指标。基本上,问题是有太多的因子组合,无法简单地预先聚合每个可能的平均值,但我也不希望用户每次更改因子都要等待几分钟。我之所以做位图索引,是因为我的理解是,在不同值的相对数量较低且没有大量写入/更新的列上,位图索引效果更好。为了我的钱,在最多一个ETL过程之外,不要将大量写入/更新替换为没有写入/更新。您应该从标准的B*树索引开始,看看性能如何。除了位图索引之外,还有其他方法可以进一步提高性能。