非常大的表上的Oracle sql语句

时间:2014-01-08 13:17:42

标签: sql oracle

我是sql的新手,我有一个需要永远运行的声明。

SELECT
  sum(a.amountcur)
FROM
  custtrans a
WHERE
  a.transdate <= '2013-12-31';

我是一张大桌子,但状态约需6分钟! 有什么想法吗?

5 个答案:

答案 0 :(得分:2)

您的选择,当您发布时,将读取整个表格的99%(2013-12-31就在一周前,我假设大多数条目在该日期之前,之后只有很少)。如果您的表有许多大列(如varchar2(4000)),那么当oracle扫描表时,所有数据都将被读取。因此,您可能会读取每行几KB,以获得amountcur和transdate所需的30个字节。

如果你有这种情况。在transdate和amountcur:

上创建一个组合索引
CREATE INDEX myindex ON custtrans(transdate, amountcur)

使用组合索引,oracle可以读取索引以完成查询,而不必触及主表,这可能会导致需要从磁盘读取的数据少得多。

答案 1 :(得分:1)

确保该表具有transdate索引。

  create index custtrans_idx on custtrans (transdate);

此外,如果此字段在表格中定义为日期,则执行

 SELECT sum(a.amountcur)
   FROM custtrans a
   WHERE a.transdate <= to_date('2013-12-31', 'yyyy-mm-dd');

答案 2 :(得分:1)

如果表格非常大,则查询必须扫描给定的transdate以下的每一行。

即使您在transdate上有一个索引并且它有助于提前停止扫描(可能没有),当匹配行的数量非常高时,扫描它们需要相当长的时间。总结价值。

为了加快速度,您可以计算部分总和,例如:对于每个过去的月份,假设您的数据是历史数据而过去没有变化。然后,您只需要扫描custtrans仅1-2个月,然后使用每月总和快速扫描表格,并添加结果。

答案 3 :(得分:0)

一个选项是在where子句中使用的列上创建索引(如果您希望使用索引列仅检索10-15%的行,这很有用。)

另一个选择是如果表有数百万行,则对表进行分区。在这种情况下,如果您尝试检索70-80%的数据,它也无济于事。

最好的选择是首先分析您的要求,然后做出选择。

每当你处理日期函数时,最好使用to_date()函数。不要依赖隐式数据类型转换。

答案 4 :(得分:0)

尝试仅在列amountcur:

上创建索引
CREATE INDEX myindex ON custtrans(amountcur)

在这种情况下,Oracle最有可能只读取索引(索引完全扫描),没有别的。

更正,如评论中所述。它必须是综合索引:

CREATE INDEX myindex ON custtrans(transdate, amountcur)

但是,为单个select语句创建索引可能有点无用。