Oracle 使用 with as 优化重复查询
2016-09-23 09:40
411 查看
我们有时写的sql 会多次查询和使用相同的结果集,而事实上每次查询都会消耗资源和降低sql的整体查询效率,特别是对大量数据表,耗时特别长。
使用with as 将想要查询的数据集保存到一张虚表中,数据查询均从这张虚拟表(视图)中查询获得,减少对数据库的直接访问。
1、该sql性能太低,其中有两张表(数据量均比较大)数据拼接操作,没有先过滤掉不需要的数据,全表扫描两张大表然后拼接,然后过滤
SELECT A.CUST_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,
E.MDN_STATE MSISDN_STATE
FROM CUST A,
CERT B,
CERT_TYPE C,
ECONET_CUST_STATE D,
(SELECT G.CUST_ID, WM_CONCAT(G.MDN_STATE) MDN_STATE
FROM (SELECT *
FROM (SELECT F.CUST_ID,
F.MDN_STATE,
ROW_NUMBER() OVER(PARTITION BY F.CUST_ID ORDER BY F.MDN_STATE) TOP
FROM (SELECT DISTINCT S.CUST_ID,
S.PREFIX || S.ACC_NBR || '|' ||
P.PROD_STATE MDN_STATE
FROM SUBS S, PROD P
WHERE S.SUBS_ID = P.PROD_ID) F)
WHERE TOP <= 5) G
WHERE G.CUST_ID IS NOT NULL
GROUP BY G.CUST_ID) E
WHERE 1 = 1
AND A.CUST_ID = D.CUST_ID
AND A.CERT_ID = B.CERT_ID(+)
AND B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CUST_ID = E.CUST_ID(+)
AND D.STATE IN ('F', 'A', 'D')
2、第一次优化,先过滤掉数据然后拼接,然而部分数据由于拼接元素为null,通过条件过滤的话会漏掉,因此要单独查询 然后union(性能有所提高)
SELECT G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE, WM_CONCAT(G.MDN_STATE) MDN_STATE
FROM (SELECT *
FROM (SELECT F.CUST_ID,
F.CUST_CODE,
F.CUST_NAME,F.CREATED_DATE,F.CUST_TYPE,F.CERT_TYPE_NAME,
F.CERT_NBR,F.STATE,F.STATE_DATE,
F.MDN_STATE,
ROW_NUMBER() OVER(PARTITION BY F.CUST_ID ORDER BY F.MDN_STATE) TOP
FROM ( SELECT A.CUST_ID,
4000
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,S.PREFIX || S.ACC_NBR || '|' ||P.PROD_STATE MDN_STATE
FROM SUBS S, PROD P, CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D
WHERE S.SUBS_ID = P.PROD_ID
AND B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CERT_ID = B.CERT_ID(+)
AND A.CUST_ID = S.CUST_ID(+)
AND A.CUST_ID = D.CUST_ID
AND D.STATE IN ('F', 'A', 'D')) F)
WHERE TOP <= 5) G
WHERE G.CUST_ID IS NOT NULL
GROUP BY G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE
UNION ALL
SELECT A.CUST_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,WM_CONCAT(S.CUST_ID) MDN_STATE
FROM CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D,SUBS S
WHERE 1=1
AND B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CERT_ID = B.CERT_ID(+)
AND A.CUST_ID = D.CUST_ID
AND D.CUST_ID = S.CUST_ID(+)
AND D.STATE IN ('F', 'A', 'D')
AND S.CUST_ID IS NULL
GROUP BY A.CUST_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE
3、第二次优化(第一次优化 使用了union all,其中SUBS S,CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D 这些个关联查询在union all 两边 都做了,如果只查询一次的话,性能会更好点,因此抽出来,用with as 先做一次查询 保存SCCCE 这张虚表中 这样只会对subs 这张数据量很大的表做一次全表扫描)
WITH SCCCE AS (SELECT A.CUST_ID,
S.SUBS_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,
S.PREFIX || S.ACC_NBR MISDN
FROM SUBS S,CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D
WHERE B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CERT_ID = B.CERT_ID(+)
AND A.CUST_ID = S.CUST_ID(+)
AND A.CUST_ID = D.CUST_ID
AND D.STATE IN ('F', 'A', 'D'))
SELECT G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE, WM_CONCAT(G.MDN_STATE) MDN_STATE
FROM (SELECT *
FROM (SELECT F.CUST_ID,
F.CUST_CODE,
F.CUST_NAME,F.CREATED_DATE,F.CUST_TYPE,F.CERT_TYPE_NAME,
F.CERT_NBR,F.STATE,F.STATE_DATE,
F.MDN_STATE,
ROW_NUMBER() OVER(PARTITION BY F.CUST_ID ORDER BY F.MDN_STATE) TOP
FROM (SELECT SC.CUST_ID,
SC.CUST_CODE,
SC.CUST_NAME,
SC.CREATED_DATE,
SC.CUST_TYPE,
SC.CERT_TYPE_NAME,
SC.CERT_NBR,
SC.STATE,
SC.STATE_DATE,
SC.MISDN|| '|' ||P.PROD_STATE MDN_STATE
FROM PROD P,SCCCE SC
WHERE SC.SUBS_ID = P.PROD_ID)F)
WHERE TOP <= 5) G
WHERE G.CUST_ID IS NOT NULL
GROUP BY G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE
UNION ALL
SELECT SC.CUST_ID,
SC.CUST_CODE,
SC.CUST_NAME,
SC.CREATED_DATE,
SC.CUST_TYPE,
SC.CERT_TYPE_NAME,
SC.CERT_NBR,
SC.STATE,
SC.STATE_DATE,WM_CONCAT( SC.MISDN) MDN_STATE
FROM SCCCE SC
WHERE 1=1
AND SC.SUBS_ID IS NULL
GROUP BY SC.CUST_ID,
SC.CUST_CODE,
SC.CUST_NAME,
SC.CREATED_DATE,
SC.CUST_TYPE,
SC.CERT_TYPE_NAME,
SC.CERT_NBR,
SC.STATE,
SC.STATE_DATE
使用with as 将想要查询的数据集保存到一张虚表中,数据查询均从这张虚拟表(视图)中查询获得,减少对数据库的直接访问。
1、该sql性能太低,其中有两张表(数据量均比较大)数据拼接操作,没有先过滤掉不需要的数据,全表扫描两张大表然后拼接,然后过滤
SELECT A.CUST_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,
E.MDN_STATE MSISDN_STATE
FROM CUST A,
CERT B,
CERT_TYPE C,
ECONET_CUST_STATE D,
(SELECT G.CUST_ID, WM_CONCAT(G.MDN_STATE) MDN_STATE
FROM (SELECT *
FROM (SELECT F.CUST_ID,
F.MDN_STATE,
ROW_NUMBER() OVER(PARTITION BY F.CUST_ID ORDER BY F.MDN_STATE) TOP
FROM (SELECT DISTINCT S.CUST_ID,
S.PREFIX || S.ACC_NBR || '|' ||
P.PROD_STATE MDN_STATE
FROM SUBS S, PROD P
WHERE S.SUBS_ID = P.PROD_ID) F)
WHERE TOP <= 5) G
WHERE G.CUST_ID IS NOT NULL
GROUP BY G.CUST_ID) E
WHERE 1 = 1
AND A.CUST_ID = D.CUST_ID
AND A.CERT_ID = B.CERT_ID(+)
AND B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CUST_ID = E.CUST_ID(+)
AND D.STATE IN ('F', 'A', 'D')
2、第一次优化,先过滤掉数据然后拼接,然而部分数据由于拼接元素为null,通过条件过滤的话会漏掉,因此要单独查询 然后union(性能有所提高)
SELECT G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE, WM_CONCAT(G.MDN_STATE) MDN_STATE
FROM (SELECT *
FROM (SELECT F.CUST_ID,
F.CUST_CODE,
F.CUST_NAME,F.CREATED_DATE,F.CUST_TYPE,F.CERT_TYPE_NAME,
F.CERT_NBR,F.STATE,F.STATE_DATE,
F.MDN_STATE,
ROW_NUMBER() OVER(PARTITION BY F.CUST_ID ORDER BY F.MDN_STATE) TOP
FROM ( SELECT A.CUST_ID,
4000
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,S.PREFIX || S.ACC_NBR || '|' ||P.PROD_STATE MDN_STATE
FROM SUBS S, PROD P, CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D
WHERE S.SUBS_ID = P.PROD_ID
AND B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CERT_ID = B.CERT_ID(+)
AND A.CUST_ID = S.CUST_ID(+)
AND A.CUST_ID = D.CUST_ID
AND D.STATE IN ('F', 'A', 'D')) F)
WHERE TOP <= 5) G
WHERE G.CUST_ID IS NOT NULL
GROUP BY G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE
UNION ALL
SELECT A.CUST_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,WM_CONCAT(S.CUST_ID) MDN_STATE
FROM CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D,SUBS S
WHERE 1=1
AND B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CERT_ID = B.CERT_ID(+)
AND A.CUST_ID = D.CUST_ID
AND D.CUST_ID = S.CUST_ID(+)
AND D.STATE IN ('F', 'A', 'D')
AND S.CUST_ID IS NULL
GROUP BY A.CUST_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE
3、第二次优化(第一次优化 使用了union all,其中SUBS S,CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D 这些个关联查询在union all 两边 都做了,如果只查询一次的话,性能会更好点,因此抽出来,用with as 先做一次查询 保存SCCCE 这张虚表中 这样只会对subs 这张数据量很大的表做一次全表扫描)
WITH SCCCE AS (SELECT A.CUST_ID,
S.SUBS_ID,
A.CUST_CODE,
A.CUST_NAME,
A.CREATED_DATE,
A.CUST_TYPE,
C.CERT_TYPE_NAME,
B.CERT_NBR,
D.STATE,
D.STATE_DATE,
S.PREFIX || S.ACC_NBR MISDN
FROM SUBS S,CUST A,CERT B,CERT_TYPE C, ECONET_CUST_STATE D
WHERE B.CERT_TYPE_ID = C.CERT_TYPE_ID(+)
AND A.CERT_ID = B.CERT_ID(+)
AND A.CUST_ID = S.CUST_ID(+)
AND A.CUST_ID = D.CUST_ID
AND D.STATE IN ('F', 'A', 'D'))
SELECT G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE, WM_CONCAT(G.MDN_STATE) MDN_STATE
FROM (SELECT *
FROM (SELECT F.CUST_ID,
F.CUST_CODE,
F.CUST_NAME,F.CREATED_DATE,F.CUST_TYPE,F.CERT_TYPE_NAME,
F.CERT_NBR,F.STATE,F.STATE_DATE,
F.MDN_STATE,
ROW_NUMBER() OVER(PARTITION BY F.CUST_ID ORDER BY F.MDN_STATE) TOP
FROM (SELECT SC.CUST_ID,
SC.CUST_CODE,
SC.CUST_NAME,
SC.CREATED_DATE,
SC.CUST_TYPE,
SC.CERT_TYPE_NAME,
SC.CERT_NBR,
SC.STATE,
SC.STATE_DATE,
SC.MISDN|| '|' ||P.PROD_STATE MDN_STATE
FROM PROD P,SCCCE SC
WHERE SC.SUBS_ID = P.PROD_ID)F)
WHERE TOP <= 5) G
WHERE G.CUST_ID IS NOT NULL
GROUP BY G.CUST_ID,
G.CUST_CODE,
G.CUST_NAME,G.CREATED_DATE,G.CUST_TYPE,G.CERT_TYPE_NAME,
G.CERT_NBR,G.STATE,G.STATE_DATE
UNION ALL
SELECT SC.CUST_ID,
SC.CUST_CODE,
SC.CUST_NAME,
SC.CREATED_DATE,
SC.CUST_TYPE,
SC.CERT_TYPE_NAME,
SC.CERT_NBR,
SC.STATE,
SC.STATE_DATE,WM_CONCAT( SC.MISDN) MDN_STATE
FROM SCCCE SC
WHERE 1=1
AND SC.SUBS_ID IS NULL
GROUP BY SC.CUST_ID,
SC.CUST_CODE,
SC.CUST_NAME,
SC.CREATED_DATE,
SC.CUST_TYPE,
SC.CERT_TYPE_NAME,
SC.CERT_NBR,
SC.STATE,
SC.STATE_DATE
相关文章推荐
- 如何使用Oracle查询并删除重复记录的SQL语句
- 使用Oracle内存机制优化ArcSDE图层空间查询的实验
- 如何使用Oracle查询并删除重复记录的SQL语句
- Oracle查询优化-使用字符串
- 在使用 ST_Geometry 空间索引时优化 Oracle 查询性能和存储
- ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下
- ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下
- 使用oracle的olap函数优化分页查询
- ORACLE使用EXCEPTIONS表查询出表中重复记录
- oracle查询常用的知识点之日期,重复字段,groupby,查询大量数据时优化
- oracle使用with as提高查询效率
- ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下
- 在使用 ST_Geometry 空间索引时优化 Oracle 查询性能和存储
- oracle使用with as提高查询效率
- oracle查询使用order by变慢的优化
- oracle优化,hint的使用! (系统自动优化有时不是最好的,我们可以手动添加hint来提高查询效率
- ORACLE使用EXCEPTIONS表查询出表中重复记录
- Oracle查询优化-使用字符串
- Oracle临时表 优化查询速度
- Oracle的update语句set里使用子查询的例子解释