Oracle count(*)花费了太多时间

时间:2013-06-24 06:48:03

标签: sql performance oracle

我试图从表中获取count(*),该表有近700万条记录,返回结果需要一个多小时。

此外,该表还有153列,其中已为列123创建了索引,因此尝试并行运行以下查询,但它没有帮助。

select /*+ parallel (5) */ count(123) from <table_name>

请建议是否有替代方式。

当我在Toad的表上运行desc时,索引选项卡保存值no。的行。知道如何在那里更新该值吗?

3 个答案:

答案 0 :(得分:2)

计算大表的行数需要很长时间。这很自然。有些DBMS存储了记录数,但是,这种DBMS限制了并发性。它应该在表上的DML操作之前锁定整个表。 (整个表锁是正确更新计数所必需的。)

ALL_TABLES.NUM_ROWS(或USER_TABLES.NUM_ROWS)中的值只是analyze table ...dbms_stats.gather_table_stats程序生成的统计信息。这不准确,不是实时信息。

如果您不需要确切的行数,则可以使用统计信息。但是你不应该依赖它。它由Oracle优化器使用,但不应该在应用程序中使用。

我不确定为什么你要计算表的行数。 如果您在不经常运行的批处理程序中需要它,可以对表进行分区以增加并行性。如果您需要在线程序中的计数,您应该找到一种不使用计数的方法。

答案 1 :(得分:2)

要提几个问题:

  1. 对于“从表中选择count(*)”来使用索引,索引列必须是非可空的,或者索引必须是位图类型。
  2. 如果列中已知没有空值但是没有空约束,则使用“select column(*)from table其中column_name不为空”。
  3. 扫描索引当然必须比表格更有效,但是如果有很多表格列,你可能会很好。
  4. 如果您真的想要并行索引扫描,请使用parallel_index提示,而不是并行。但是只有700万行,你可能不会发现需要并行性。
  5. 您需要检查执行计划,以查看是否正在使用索引和/或并行查询。
  6. 如果您可以使用估计的行数,请考虑使用示例子句:例如“从表格样本中选择1000 * count(*)(0.1)”

答案 2 :(得分:0)

select /*+ parallel (5) */ 

似乎是并行度的奇数。嗯,明显的5是奇数,这很奇怪。 DoP应该是 power 的两倍(见下文更多)。

无论如何,你有理由使用并行查询吗?你有至少五个备用处理器吗?如果没有,管理PQ从站的开销很可能至少导致性能不佳。


为什么DOP = n * 2?基于排队论的已建立的启发式方法是,同时运行两个以上的批处理作业会导致性能下降。 Find out more.(我认为排队理论实际上建议使用1.8的数字,但由于数据库作业通常受I / O或磁盘约束,我们通常可以使用2。)

我最初说的是“2的强大”但这主要是因为多核服务器往往拥有多个CPU的功率为2,但2的倍数更准确,因为有些盒子有12个CPU或其他一些数。

现在,如果我们有一个64核盒,那么5或37的DOP就可以了,因为我们有足够的CPU同时运行那么多线程。但是如果我们有一个小的四核盒子,只有2,4或8是有意义的,因为这些是确保在所有四个处理器上均匀分配工作的唯一值。在四核盒子上运行五个线程意味着一个CPU将比其他三个线程做更多的工作;有可能需要更长的时间才能完成,其他三个奴隶等待。因此,DOP=5实际上可以导致比DOP=4更长的时间。

DOP=n*2只是一个经验法则,而不是一成不变的。然而,它基于合理的推理,我们应该知道为什么我们做了不同的事情。显然,我们应该进行一些实验来确认我们选择了正确的DOP(无论我们采用什么价值)。