【发布时间】:2018-06-02 15:07:06
【问题描述】:
我不是 DBA 专家,我们有一个现有的 Oracle 查询来提取特定日期的数据,我们遇到的问题是如果一天的业务量非常大,查询需要 8 多个小时并且超时.我们无法在数据库本身内部进行优化,那么我们通常如何处理这种极端情况呢?我粘贴了下面的查询,内容被屏蔽以显示 SQL 结构,寻找有关如何优化此查询或任何替代方法以避免超时的建议。
WHENEVER SQLERROR EXIT 1
SET LINESIZE 9999
SET ECHO OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SET HEADING OFF
SET TRIMSPOOL ON
SET COLSEP ","
SELECT co.cid
|| ',' || DECODE(co.cid,'xxxxx','xxxx',null,'N/A','xxxxx')
|| ',' || d.name
|| ',' || ti.rc
|| ',' || DECODE(cf.side_id,1,'x',2,'xx',5,'xx','')
|| ',' || cf.Quantity
|| ',' || cf.price
|| ',' || TO_CHAR(time,'YYYY-mm-dd hh24:mi:ss')
|| ',' || DECODE(co.capacity_id,1,'xxxx',2,'xxxx','')
|| ',' || co.type
|| ',' || cf.id
|| ',' || CASE
WHEN (cf.account_id = xxx OR cf.account_id = xxx) THEN SUBSTR(cf.tag, 1, INSTR(cf.tag, '.')-1) || '_' || ti.ric || '_' || DECODE(cf.side_id,1,'xx',2,'xx',5,'xx','')
WHEN INSTR(cf.clientorder_id, '#') > 0 THEN SUBSTR(cf.clientorder_id, 1, INSTR(cf.clientorder_id, '#')-1)
ELSE cf.clientorder_id
END
|| ',' || co.tag
|| ',' || t.description
|| ',' || CASE
WHEN cf.id = xxx THEN 'xxxx'
ELSE (SELECT t.name FROM taccount t WHERE t.account_id = cf.account_id)
END as Account
FROM clientf cf, tins ti, thistory co, tdk d, tra t
WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
AND cf.orderhistory_id = co.orderhistory_id
AND cf.reporttype_id = 1
AND ti.inst_id = cf.inst_id
AND (ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' )
AND d.de_id = t.de_id
AND t.tr_id = co.tr_id
AND nvl(co.type_id,0) <> 3
AND cf.trid not in (SELECT v2.pid FROM port v2 WHERE v2.sessiondate = cf.sessiondate AND v2.exec_id = 4)
ORDER BY co.cid, time, cf.quantity;
【问题讨论】:
-
“我们无法在数据库本身内部进行优化” ...如果您不能这样做,则很难优化查询。唯一让我印象深刻的是
AND (ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' )这一行,因为它显然不使用索引,但很难说它最终是否重要。 -
你制定了解释计划吗?
-
你有一个相关的子查询
..AND cf.trid not in (SELECT v2.pid FROM port v2 ..这将被重复执行。尝试使用端口上的临时表删除它(过滤掉 exec_id)或尝试以某种方式在连接中包含端口。 -
如果没有解释计划,我们将只是猜测。请出示解释计划。
-
+1 请求解释计划(或者,更好的是,请参阅:stackoverflow.com/a/50605440/5174436 了解如何使用 DBMS_XPLAN 了解更多详细信息)。同时,
CLIENTF(reportype_id,sessiondate)上是否有索引?