伙计们我有以下oracle sql查询,它给出了日期之间的月度报告。基本上对于新的一个月,我想要日期01nov到30 nov之间的值之和。 正在查询的表驻留在另一个数据库中,并使用dblink进行访问。 DT列为NUMBER类型(对于ex 20101201)。
SELECT /*+ PARALLEL (A 8) */ /*+ DRIVING_STATE(A) */
TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')- 1,'MM'),'MONYYYY') "MONTH",
TYPE AS "TYPE", COLUMN, COUNT (DISTINCT A) AS "A_COUNT",
COUNT (COLUMN) AS NO_OF_COLS, SUM (DURATION) AS "SUM_DURATION",
SUM (COST) AS "COST" FROM **A@LN_PROD A**
WHERE DT >= TO_NUMBER(TO_CHAR(add_months(SYSDATE,-1),'YYYYMM"01"'))
AND DT < TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMM"01"'))
GROUP BY TYPE, COLUMN
查询的执行需要一天时间并且未完成。请建议我,如果他们是可以在dblink上向我的DBA建议的任何优化,或者可以在查询上进行的任何调整,或者重写它。
更新表
该表在日期栏中被分割,并且有近10亿条记录。
下面我从 TOAD
中提供了 EXPLAIN PLAN**Plan**
SELECT STATEMENT REMOTE ALL_ROWSCost: 1,208,299 Bytes: 34,760 Cardinality: 790
12 PX COORDINATOR
11 PX SEND QC (RANDOM) SYS.:TQ10002 Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
10 SORT GROUP BY Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
9 PX RECEIVE Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
8 PX SEND HASH SYS.:TQ10001 Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
7 SORT GROUP BY Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
6 PX RECEIVE Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
5 PX SEND HASH SYS.:TQ10000 Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
4 SORT GROUP BY Cost: 1,208,299 Bytes: 34,760 Cardinality: 790
3 FILTER
2 PX BLOCK ITERATOR Cost: 1,203,067 Bytes: 15,066,833,144 Cardinality: 342,428,026 Partition #: 11 Partitions accessed #1 - #5
1 TABLE ACCESS FULL TABLE CDRR.FRD_CDF_DATA_INTL_IN_P Cost: 1,203,067 Bytes: 15,066,833,144 Cardinality: 342,428,026 Partition #: 11
我今天要做的事情如下,任何其他提示都会有所帮助。
答案 0 :(得分:1)
可能是因为几个问题: 1.网络速度,因为数据库可能驻留在不同的硬件上。 但是,您可以参考此链接 http://www.experts-exchange.com/Database/Oracle/Q_21799513.html。 还有类似的问题。
答案 1 :(得分:1)
在不知道表结构,约束,索引,数据量,结果集大小,网络速度,并发级别,执行计划等的情况下,无法回答。
我会调查一些事情:
如果表是分区的,那么查询所针对的分区是否存在统计信息?一个常见问题是,在插入数据之前,会在空分区上收集统计信息。然后,当您查询它时(在刷新统计信息之前),Oracle会选择索引扫描,而实际上它应该在该分区上使用FTS。
还与统计相关:确保
WHERE DT >=TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')-1,'MM'),'YYYYMMDD'))
AND DT < TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM'),'MM'),'YYYYMMDD'))
生成与:
相同的执行计划WHERE DT >= 20101201
AND DT < 20110101
<强>更新强> 您使用的是哪个版本的Oracle?我问的原因是在Oracle 10g及更高版本中,在这种情况下应该选择另一个group by的实现(散列而不是排序)。看起来你基本上是对日期过滤器返回的3.42亿行进行排序(14千兆字节)。你有RAM备份吗?否则,您将进行多通道排序,溢出到磁盘。这很可能发生了什么。
根据计划,将返回约790行。那是在正确的球场吗? 如果是这样,您可以排除网络问题:)
另外,我并不完全熟悉该计划的格式。表子分区了吗?否则我没有得到分区#11引用。
答案 2 :(得分:1)
正如此类问题一样,解释计划会很有用。它将帮助我们计算出数据库中实际发生的事情。
理想情况下,您希望确保查询在远程数据库上运行,然后发送结果集,而不是通过链接发送数据并在本地运行查询。这可确保通过链接发送的数据更少。 DRIVING_SITE
提示可以帮助解决这个问题,尽管Oracle通常对它很聪明,所以它可能根本没用。
Oracle似乎在运行远程查询方面做得更好,但仍然存在问题。
此外,简化部分日期转换可能需要付费。
例如,替换它:
TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')- 1,'MM'),'MONYYYY')
用这个:
TO_CHAR(add_months(TRUNC(SYSDATE,'MM'), -1),'MONYYYY')
它可能稍微高效但也更容易阅读。
同样替换它:
WHERE DT >=TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')-1,'MM'),'YYYYMMDD'))
AND DT < TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM'),'MM'),'YYYYMMDD'))
带
WHERE DT >=TO_NUMBER(TO_CHAR(add_months(TRUNC(SYSDATE,'MM'), -1),'YYYYMMDD'))
AND DT < TO_NUMBER(TO_CHAR(TRUNC(SYSDATE,'MM'),'YYYYMMDD'))
甚至
WHERE DT >=TO_NUMBER(TO_CHAR(add_months(SYSDATE,-1),'YYYYMM"01"'))
AND DT < TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMM"01"'))