Oracle Sql Query 需要一天的时间才能使用 dblink 返回结果
Posted
技术标签:
【中文标题】Oracle Sql Query 需要一天的时间才能使用 dblink 返回结果【英文标题】:Oracle Sql Query taking a day long to return results using dblink 【发布时间】:2011-01-06 10:50:37 【问题描述】:伙计们,我有以下 oracle sql 查询,它为我提供了日期之间的月度报告。基本上对于 11 月,我想要日期 01nov 到 11 月 30 日之间的值总和。 正在查询的表位于另一个数据库中并使用 dblink 进行访问。 DT 列是 NUMBER 类型(例如 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
我今天要做的事情如下,任何额外的提示都会有所帮助。
-
我将收集该表的表格统计信息,这可能会提供最佳的
执行计划。
检查是否为分区创建了本地索引。
使用 BETWEEN 代替 >= 和 <.>
【问题讨论】:
只是好奇,直接在远程数据库上运行需要多长时间?如果查询本身只是花费很长时间,则 DB 链接可能是一条红鲱鱼。 十亿行!难怪需要很长时间! 【参考方案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"'))
【讨论】:
我已经在这里发布了解释计划供您参考。请注意 int。 @Suresh:我从来没有那么擅长阅读并行查询或分区的执行计划,所以 prob 帮不上什么忙。不过看起来确实是一张非常大的桌子!我发现表/分区压缩可以帮助处理大型表,尽管这仅适用于 10g 中的静态数据的批量加载(在 11 中更好),但我认为您可以根据需要压缩历史分区。【参考方案2】:可能是因为几个问题: 1.网络速度,因为数据库可能驻留在不同的硬件上。 但是你可以参考这个链接 http://www.experts-exchange.com/Database/Oracle/Q_21799513.html。 有类似的问题。
【讨论】:
刚刚突出显示了其中一个参数 你不能在另一个数据库中运行查询来创建丢失的表。如果它工作正常,那么你可能需要调整 SQL 查询【参考方案3】:在不知道表结构、约束、索引、数据量、结果集大小、网络速度、并发级别、执行计划等的情况下无法回答。
我会调查的一些事情:
如果表是分区的,查询命中的分区是否存在统计信息?一个常见的问题是在插入数据之前在空分区上收集统计信息。然后当您查询它时(在刷新统计信息之前)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 实现(散列而不是排序)。看起来您基本上是在对从日期过滤器(14 GB)返回的 3.42 亿行进行排序。你有内存来备份吗?否则,您将进行多遍排序,溢出到磁盘。这很可能是正在发生的事情。
根据计划,将返回大约 790 行。这是在正确的球场吗? 如果是这样,您可以排除网络问题:)
另外,我并不完全熟悉该计划的格式。表子分区了吗?否则我没有得到分区 #11 的引用。
【讨论】:
以上是关于Oracle Sql Query 需要一天的时间才能使用 dblink 返回结果的主要内容,如果未能解决你的问题,请参考以下文章
sql Oracle SQL:返回当前月份第一天的字符串(如果其他月份为ar,则替换SYSDATE的任何日期字段/值