我正在浏览一些没有注释的pl / sql代码。试图理解它并优化它。以下是样本:
INSERT INTO gtt1 --75711 rows
(USER_ID, role_id, participant_code, status_id )
SELECT
r.user_id, r.role_id, r.participant_code, MAX(status_id)
FROM
user_role r,
cmp_role c
WHERE
r.role_id = c.role_id
AND r.participant_code IS NOT NULL
AND c.group_id = 3
GROUP BY
r.user_id, r.role_id, r.participant_code;
然后
DELETE gtt1
WHERE ROWID IN (SELECT ROWID FROM gtt1
MINUS
SELECT a.ROWID FROM gtt1 a, UIV_CMP_USER_ROLE b
WHERE a.status_id = b.status_id
AND (b.ACTIVE = 1 OR ( b.ACTIVE IN ( 0,3 )
AND SYSDATE BETWEEN b.effective_from_date AND b.effective_to_date
)
)
);
最后(这需要最长时间)
OPEN cv_1 FOR
SELECT c.role_id,
c.subgroup,
c.subgroup_description,
COUNT(a.USER_ID) user_count
FROM
(SELECT b.user_id, b.role_id FROM gtt1 b, pt_user e
--pt_user table has 73000 rows
WHERE e.user_id = RTRIM(b.user_id)
) a
RIGHT OUTER JOIN CMP_ROLE c ON a.role_id = c.role_id
WHERE c.group_id = v_group_id
GROUP BY c.role_id,c.subgroup,c.subgroup_description
ORDER BY c.subgroup;
有没有办法可以避免从gtt1中删除,最初只是获取我们想要的行?
运行解释计划我注意到对此查询进行了一些全表扫描:
SELECT
r.user_id, r.role_id, r.participant_code, MAX(status_id)
FROM
user_role r,
cmp_role c
WHERE
r.role_id = c.role_id
AND r.participant_code IS NOT NULL
AND c.group_id = 3
GROUP BY
r.user_id, r.role_id, r.participant_code
HAVING MAX(status_id) IN (SELECT b.status_id FROM UIV_CMP_USER_ROLE b
WHERE (b.ACTIVE = 1 OR ( b.ACTIVE IN ( 0,3 )
AND SYSDATE BETWEEN b.effective_from_date AND b.effective_to_date
))
)
user_role = 803507行
cmp_role = 27行
user_role有5个索引:
idx 1 = role_id
idx 2 = last_updt_user_id
idx 3 = actv_id,participant_code,effective_from_Date,effective_to_date
idx 4 = user_id,role_id,effective_from_Date,effective_to_date
idx 5 = participant_code,user_id,roke_id,actv_cd
答案 0 :(得分:1)
您想要优化查询本身还是只需要给出结果所需的时间? 其次需要一些关于行数的数据,等等......
答案 1 :(得分:0)
INSERT和DELETE在我看来等同于:
INSERT INTO gtt1 --75711 rows
(USER_ID, role_id, participant_code, status_id )
SELECT
r.user_id, r.role_id, r.participant_code, MAX(status_id)
FROM
user_role r,
cmp_role c
WHERE
r.role_id = c.role_id
AND r.participant_code IS NOT NULL
AND c.group_id = 3
GROUP BY
r.user_id, r.role_id, r.participant_code
HAVING MAX(status_id) IN (SELECT b.status_id FROM UIV_CMP_USER_ROLE b
WHERE (b.ACTIVE = 1 OR ( b.ACTIVE IN ( 0,3 )
AND SYSDATE BETWEEN b.effective_from_date
AND b.effective_to_date
))
);
这是否更有效率我不知道 - 我需要更多地了解表格,索引和数据。
然后你可以进一步将GTT变成子查询,例如:
WITH gtt1 AS
(SELECT
r.user_id, r.role_id, r.participant_code, MAX(status_id)
FROM
user_role r,
cmp_role c
WHERE
r.role_id = c.role_id
AND r.participant_code IS NOT NULL
AND c.group_id = 3
GROUP BY
r.user_id, r.role_id, r.participant_code
HAVING MAX(status_id) IN (SELECT b.status_id FROM UIV_CMP_USER_ROLE b
WHERE (b.ACTIVE = 1 OR ( b.ACTIVE IN ( 0,3 )
AND SYSDATE BETWEEN b.effective_from_date AND b.effective_to_date
))
)
)
SELECT c.role_id,
c.subgroup,
c.subgroup_description,
COUNT(a.USER_ID) user_count
FROM
(SELECT b.user_id, b.role_id FROM gtt1 b, pt_user e
--pt_user table has 73000 rows
WHERE e.user_id = RTRIM(b.user_id)
) a
RIGHT OUTER JOIN CMP_ROLE c ON a.role_id = c.role_id
WHERE c.group_id = v_group_id
GROUP BY c.role_id,c.subgroup,c.subgroup_description
ORDER BY c.subgroup;
同样,我不知道这是否比当前代码效率更高或更低。