我是sql的新手,我有一个需要永远运行的声明。
SELECT
sum(a.amountcur)
FROM
custtrans a
WHERE
a.transdate <= '2013-12-31';
我是一张大桌子,但状态约需6分钟! 有什么想法吗?
答案 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语句创建索引可能有点无用。