Oracle 查询性能优化
Posted
技术标签:
【中文标题】Oracle 查询性能优化【英文标题】:Oracle Query Performance Optimization 【发布时间】:2020-06-10 21:05:37 【问题描述】:我目前正在优化以下查询,运行时间超过 60 分钟。查询中提供的日期由在执行期间计算日期的变量替换。目标是让此查询在 10 分钟内运行。
SELECT
clm.clcl_payee_pr_id,
clm.sbsb_ck,
clm.clcl_id,
clm.meme_ck,
clm.clcl_paid_dt,
Row_number()
OVER (
ORDER BY clm.clcl_payee_pr_id, clm.sbsb_ck, clm.clcl_id) AS reccount
FROM cmc_mepe_prcs_elig MEPE
INNER JOIN cmc_meme_member MEME
ON MEPE.meme_ck = MEME.meme_ck
AND MEPE.grgr_ck = '41'
INNER JOIN cmc_mepr_prim_prov MEPR
ON MEPE.meme_ck = MEPR.meme_ck
AND MEPR.grgr_ck = '41'
INNER JOIN cmc_sbsb_subsc SBSB
ON MEME.sbsb_ck = SBSB.sbsb_ck
AND SBSB. grgr_ck = '41'
INNER JOIN cmc_prpr_prov PROV
ON MEPR.prpr_id = PROV.prpr_id
INNER JOIN cmc_prer_relation PRER
ON PRER.prpr_id = MEPR.prpr_id
AND PRER.prer_prpr_entity = 'I'
AND PRER.prer_prpr_id IN ( '02549455' )
INNER JOIN cmc_clcl_claim CLM
ON MEME.meme_ck = CLM.meme_ck
AND CLM.clcl_prpr_id_pcp = MEPR.prpr_id
INNER JOIN cmc_prpr_prov PRPR
ON CLM.prpr_id = PRPR.prpr_id
INNER JOIN cmc_plds_plan_desc PLDS
ON MEPE.cspi_id = PLDS.cspi_id
INNER JOIN cmc_pdds_prod_desc PDDS
ON MEPE.pdpd_id = PDDS.pdpd_id
WHERE MEPE.mepe_elig_ind = 'Y'
AND CLM.clcl_low_svc_dt BETWEEN MEPE.mepe_eff_dt AND MEPE.mepe_term_dt
AND CLM.clcl_low_svc_dt BETWEEN MEPR.mepr_eff_dt AND MEPR.mepr_term_dt
AND CLM.clcl_cur_sts = '02'
AND CLM.clcl_cl_type = 'M'
AND CLM.clcl_cl_sub_type = 'H'
AND CLM.grgr_ck IN ( 41 )
AND ( PLDS.plds_desc LIKE '%risk%' OR PDDS.pdds_desc LIKE '%risk%' )
AND CLM.clcl_paid_dt BETWEEN '24-APR-19 12.00.00.000000 AM' AND '30-APR-19 11.59.59.997000 PM';
以下是使用的每个表的总行数。
cmc_mepe_prcs_elig: 103,974,973 cmc_meme_member: 22,433,154 cmc_mepr_prim_prov: 53,498,452 cmc_sbsb_subsc: 22,433,154 cmc_prpr_prov: 5,266,062 cmc_prer_relation: 4,735,086 cmc_clcl_claim: 897,405,800 cmc_plds_plan_desc:19,122 cmc_pdds_prod_desc: 4,776所有这些表都驻留在主数据库中,该数据库是只读的,我不允许创建任何索引来提高性能。唯一的选择是使用提示并玩弄查询。以下是上述查询的当前执行计划。
在性能调整方面我是新手,如果您能告诉我是否应该提供有关表的任何其他信息,以便您就调整查询提出建议,我将不胜感激。
【问题讨论】:
【参考方案1】:试试下面。一般来说,您可以像我将解释的那样考虑优化:
尽可能避免使用OR
和LIKE
语句。
当您构建一个连接时,您不应交互两个以上的表。(CLM 同时与 MEME 和 MEPR 连接。如果您需要连接这 3 个表,请尝试使用另一个别名(如 CLM2)添加另一个连接,然后加入此其他表的新别名。)
SELECT CLM.CLCL_PAYEE_PR_ID,
CLM.SBSB_CK,
CLM.CLCL_ID,
CLM.MEME_CK,
CLM.CLCL_PAID_DT,
ROW_NUMBER ()
OVER (ORDER BY CLM.CLCL_PAYEE_PR_ID, CLM.SBSB_CK, CLM.CLCL_ID)
AS RECCOUNT
FROM CMC_MEPE_PRCS_ELIG MEPE
INNER JOIN CMC_PLDS_PLAN_DESC PLDS ON MEPE.CSPI_ID = PLDS.CSPI_ID
INNER JOIN CMC_PDDS_PROD_DESC PDDS ON MEPE.PDPD_ID = PDDS.PDPD_ID
INNER JOIN CMC_MEME_MEMBER MEME
ON MEPE.MEME_CK = MEME.MEME_CK AND MEPE.GRGR_CK = '41'
INNER JOIN CMC_SBSB_SUBSC SBSB
ON MEME.SBSB_CK = SBSB.SBSB_CK AND SBSB.GRGR_CK = '41'
INNER JOIN CMC_MEPR_PRIM_PROV MEPR
ON MEPE.MEME_CK = MEPR.MEME_CK AND MEPR.GRGR_CK = '41'
INNER JOIN CMC_PRPR_PROV PROV ON MEPR.PRPR_ID = PROV.PRPR_ID
INNER JOIN CMC_PRER_RELATION PRER
ON PRER.PRPR_ID = MEPR.PRPR_ID AND PRER.PRER_PRPR_ENTITY = 'I'
INNER JOIN CMC_PRPR_PROV PRPR ON CLM.PRPR_ID = PRPR.PRPR_ID
INNER JOIN CMC_CLCL_CLAIM CLM
ON MEME.MEME_CK = CLM.MEME_CK
-- AND CLM.CLCL_PRPR_ID_PCP = MEPR.PRPR_ID
WHERE MEPE.MEPE_ELIG_IND = 'Y'
AND CLM.CLCL_LOW_SVC_DT BETWEEN MEPE.MEPE_EFF_DT AND MEPE.MEPE_TERM_DT
AND CLM.CLCL_LOW_SVC_DT BETWEEN MEPR.MEPR_EFF_DT AND MEPR.MEPR_TERM_DT
AND CLM.CLCL_CUR_STS = '02'
AND CLM.CLCL_CL_TYPE = 'M'
AND CLM.CLCL_CL_SUB_TYPE = 'H'
AND CLM.GRGR_CK IN (41)
-- AND (PLDS.PLDS_DESC LIKE '%risk%' OR PDDS.PDDS_DESC LIKE '%risk%')
AND CLM.CLCL_PAID_DT BETWEEN '24-APR-19 12.00.00.000000 AM'
AND '30-APR-19 11.59.59.997000 PM'
AND PRER.PRER_PRPR_ID = '02549455';
【讨论】:
感谢您的建议。我不能更改查询中的 LIKE 子句,因为这是一个基本条件。如果我可以通过创建阶段/临时表来获得相同的结果,我会尝试。以上是关于Oracle 查询性能优化的主要内容,如果未能解决你的问题,请参考以下文章