【问题标题】:Getting count from large tables从大表中获取计数
【发布时间】:2016-11-02 04:39:03
【问题描述】:

我试图从包含数百万条目的表中获取计数。我的查询有点像这样:

Select count(*)
from Users
where status = 'A' and office_id = '000111' and user_type = 'C'

状态可以是A或C,用户类型可以是C或R。 Status、Office_id 和 User_type 是字符串

结果大约有 1000 万行,这需要很长时间。我只想要总数。

如果有人能告诉我为什么要花这么多时间以及解决方法(如果有的话),我将不胜感激。

如果需要更多详细信息,请告诉我。

数据库引擎是Oracle 11g

编辑:我为所有三个列添加了索引。仍然没有任何改善。也尝试了下面的查询,但它总是返回表中的总数而不检查条件。

SELECT COUNT(office_id_key) 
FROM Users
WHERE EXISTS (SELECT * FROM Users WHERE status = 'A' AND office_id = '000111' AND user_type = 'C')

【问题讨论】:

  • 您的年龄字段是文本字段吗?只是想知道
  • 对您的查询运行解释计划(并发布输出?)。 age 列是什么数据类型? Employee 表上存在哪些索引?
  • 能否在 MySQL 中提供表定义?
  • 是的,它是一个文本字段。抱歉,我刚刚粘贴了一个示例查询。我马上更新
  • @Chillax 显而易见的问题是为什么将数字存储为文本字段?

标签: oracle count


【解决方案1】:

为什么不简单地在ageplace 上的表上创建索引,这样您的搜索会比简单地扫描整个表中的这些值更快。

CREATE INDEX age_index ON Employee(age);
CREATE INDEX place_index ON Employee(place);

这应该会加快这个过程。

根据查询更改修改

CREATE INDEX status_index ON Users(status);
CREATE INDEX office_id_index ON Users(office_id);
CREATE INDEX user_type_index ON Users(user_type);

【讨论】:

  • 作者更改了表/字段的名称,但这个建议是可靠的。为相应的列添加一些索引。
  • 感谢您的建议。直到明天我才能尝试。明天更新。
  • @gfortune 修改了答案。 :)
  • @Karlson 有一个疑问,添加索引不会减慢表的更新速度吗?
  • @Karlson 更新了我的问题。你能调查一下吗?
【解决方案2】:

您需要在Users 表上创建以下多列索引以改进查询:

(office_id, status, user_type)

数据库可以使用带有COUNT(*) 的“覆盖”索引。由于基数,按该顺序使用列创建索引。

【讨论】:

  • 谢谢。是这样的吗:CREATE INDEX count_index ON Users(office_id, status, user_type); ?
  • @Chillax,是的,这很好,但从技术上讲,我会在 Users( 之间放置一个空格。
  • 添加索引并没有改善。还有其他建议吗?
  • 让我们看看完整的查询。你是在展示全部吗?另外,请显示解释结果。
  • 是的,这就是完整的查询。结果是 36355199,这是表中的总数(不包括条件)。
【解决方案3】:

添加索引后,我认为更改存在的位置和子查询也可能会有所帮助。

Edit2:removed 存在,因为它返回所有有效,通常子查询有多个连接,但我猜一个表的情况返回所有 true。我读到当它只有一个表并且没有 where 子句时,计数被优化为类似于存在,所以我将结果视为一个表。希望这会有同样的快速结果。

select count(1) from
(select 1 from Employee where age = '25' and place = 'bricksgate')

编辑:当您使用“where exists”时,数据库服务器不会将您的数据加载到内存中,并且还会利用索引,因为您将从索引中读取值而不是进行昂贵的表查找。您可能还想将 count(*) 更改为 count(place) - 这样它也会将字段限制为索引字段。

在您的原始查询中,您的数据正在执行表查找,然后将它们加载到内存中以进行计数。

【讨论】:

  • 谢谢。明天会做,会告诉你进展如何。
  • 刚刚试过上面的查询。它返回表中的总数。我在这里做错了吗?
  • 我编辑了查询以使用优化的计数形式,希望这会有所帮助。 :)
【解决方案4】:

count(1) 比 count(*) 工作得更快

【讨论】:

  • 您可能想要更具体一点,但如果您不必扫描整个表格,您将获得更大的收获。
  • COUNT(1) 和 COUNT(*) 没有逻辑上的区别,也没有性能上的区别。
  • 在 7.x 及更低版本 (Oracle) 上,count(1) 的性能优于 count(*)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-25
  • 2020-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
相关资源
最近更新 更多