我要按出货月份转换汇率统计销售额,用下面的统计查询竟然用了616.797秒(合10分钟),晕死了-_-#请大侠帮忙看看:要如何优化才能加快查询的执行速度:
SELECT ROUND(SUM(D.QTY*D.UNIT_PRICE* GG_PO.GF_CURR_RATE(M.ORG_ID,M.MONEY_UNIT,'USD',TO_CHAR(D.SALES_DATE,'YYYYMM'))),2)
FROM SALES_M M,SALES_D D
WHERE M.ORG_ID=100
AND M.PERIOD>='200804'
AND M.PERIOD<='200804'
AND M.SALES_ID = D.SALES_ID
AND DECODE(GG_R1.GF_SEID_TYPE(D.ORG_ID,D.SE_ID),1,'P',2,'S',4,'O')='P'
AND DECODE(GG_SH.GF_SALESNO_SHIPTYPE(D.ORG_ID,D.SALES_NO),1,'a',2,'a',3,'b')='a'
AND M.SALES_TYPE = 1
AND M.PAY_NO <> '022'
SELECT ROUND(SUM(D.QTY*D.UNIT_PRICE* GG_PO.GF_CURR_RATE(M.ORG_ID,M.MONEY_UNIT,'USD',TO_CHAR(D.SALES_DATE,'YYYYMM'))),2)
FROM SALES_M M,SALES_D D
WHERE M.ORG_ID=100
AND M.PERIOD>='200804'
AND M.PERIOD<='200804'
AND M.SALES_ID = D.SALES_ID
AND DECODE(GG_R1.GF_SEID_TYPE(D.ORG_ID,D.SE_ID),1,'P',2,'S',4,'O')='P'
AND DECODE(GG_SH.GF_SALESNO_SHIPTYPE(D.ORG_ID,D.SALES_NO),1,'a',2,'a',3,'b')='a'
AND M.SALES_TYPE = 1
AND M.PAY_NO <> '022'
不会用执行计划的话
在sql plus 环境下
set autotrace on
然后执行语句,最后几行就是执行计划
说一下你表里一个月有多少数据,索引列的情况
SELECT ROUND (SUM ( d.qty
* d.unit_price
* gg_po.gf_curr_rate (m.org_id,
m.money_unit,
'USD',
TO_CHAR (d.sales_date, 'YYYYMM')
)
),
2
)
FROM sales_d d, sales_m m
WHERE DECODE (gg_r1.gf_seid_type (d.org_id, d.se_id),
1, 'P',
2, 'S',
4, 'O'
) = 'P'
AND DECODE (gg_sh.gf_salesno_shiptype (d.org_id, d.sales_no),
1, 'a',
2, 'a',
3, 'b'
) = 'a'
AND m.sales_id = d.sales_id
AND m.sales_type = 1
AND m.pay_no <> '022'
AND m.org_id = 100
AND m.period >= '200804'
AND m.period <= '200804'语句顺序换成这样试试看
不过以前我也有张报表,月销售统计明细报表,原来执行一次大概1分钟左右
后来财务要求改计算方式,结果也只能改成像你这样在where里调用函数来判断,执行时间延长到8分钟
不过你这是汇总应该要快点
索引列:RG_ID, SALES_ID上面的數据查詢匯總的目的:其實是為了導銷售匯總報表
我的報表里有好几條那樣的查詢匯總語句,執行速度太慢了,一個多小時都導不出,暈死了-_-#
贴一下你的表结构,以及你的函数内容
2K条不算多,我们现在大概一个万把条
我原先 个报表,一个月大概5万条纪录,全是拉明细,你只是汇总的不过你应该在m.period建索引,一般来说这种销售表,日期查询的是最多
全表扫描是肯定的了,不过看样子,你的gg_sh.gf_salesno_shiptype 和
gg_r1.gf_seid_type效率不怎么高。。
--==>FUNCTION GF_SALESNO_SHIPTYPE (P_ORGID NUMBER,
P_SALESNO VARCHAR2)
RETURN VARCHAR2 IS
V_SHIPTYPE VARCHAR2(1);
V_SHIPID SP_SHIP_M.SHIP_ID%TYPE;
BEGIN
BEGIN
SELECT COLUMN4 INTO V_SHIPID
FROM SH_SALES_M
WHERE ORG_ID = P_ORGID
AND SALES_NO = P_SALESNO;
BEGIN
SELECT SHIP_TYPE INTO V_SHIPTYPE
FROM SP_SHIP_M
WHERE ORG_ID = P_ORGID
AND SHIP_ID = V_SHIPID;
EXCEPTION WHEN NO_DATA_FOUND THEN
NULL;
END;
EXCEPTION WHEN NO_DATA_FOUND THEN
NULL;
END;
RETURN V_SHIPTYPE;
END;
原來我的明細表TABLE ACCESS (FULL) OF 'SALES_D' (TABLE) 是全表掃描。。
給這個表加上索引應該能解決問題,謝謝樓上各位朋友:)
set autotrace onExecute Plan
------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=219 Card=1 Bytes=77)
1 0 SORT (AGGREGATE)
2 1 NESTED LOOPS (Cost=219 Card=4 Bytes=308)
3 2 TABLE ACCESS (FULL) OF 'SALES_D' (TABLE) (Cost=215 Card=4 Bytes=204)
4 2 TABLE ACCESS (BY INDEX ROWID) OF 'SALES_M' (TABLE) (Cost=1 Card=1 Bytes=26)
5 4 INDEX (UNIQUE SCAN) OF 'PK_AR_SALES_M' (INDEX (UNIQUE)) (Cost=0 Card=1)
-- Create/Recreate primary, unique and foreign key constraints
alter table SALES_D
add constraint PK_SALES_D primary key (ORG_ID,SALES_ID,ITEM_ID)
using index
tablespace SADB_INDEX02
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
其它的就不说了。
但是楼主有一些陋习还是改改较好。
明明可以等于的就不要用一个>=和一个<=来处理。
明明可以直接比较的,就不要加上多于的decode处理了。
光这些函数处理也能耗费不少时间。
此外如果你有权限, 最好还是把函数转换为表格处理(多对多记录rate),这些关联比函数来的更快些,因为你的数据并不大,不是几百几千万。
最后,decode中函数不应该使用,也应该直接在表格中加列,预先计算结果。
不会用执行计划的话
在sql plus 环境下
SET autotrace trace explain
然后执行语句,最后几行就是执行计划
收獲很大,謝謝各位參與指教,謝謝~