是否有任何经验法则可以优化这样的 sql 查询

use*_*201 2 db2

这是我在这里的第一个问题。虽然我已经从这个论坛上得到了一百多次帮助。我在优化 sql 查询时遇到了困难。执行需要几个小时。记录集也足够大。查询不是我写的。因此,为了找到瓶颈,我尝试删除条件子句,但这没有任何区别。索引 ID 已完成。

这里的任何 sql 大师都可以对此有所了解。下面的查询中是否还有微调空间?在 DB2 中托管数据库的服务器。我在 sql 方面不太专业。一如既往的感谢。问候, 努

这是查询:

SELECT
HEALTH_INSURANCE.RISK_DETAIL_ID ,
POLICY_RISK_COVER.RISK_COVER_ID ,
HEALTH_INSURANCE.RD_POLICY_SYSTEM_NO ,
RD_POLICY_END_NO_IDX ,
HEALTH_INSURANCE.RD_POLICY_ID ,
HEALTH_INSURANCE.RD_LEVEL1_ID ,
HEALTH_INSURANCE.RD_SUM_INSURED_AMT_LC ,
HEALTH_INSURANCE.RD_PREMIUM_AMT_LC ,
POLICY_RISK_COVER.PREMIUM_AMOUNT_FC ,
POLICY_RISK_COVER.SUM_INSURED_AMT_FC ,
HEALTH_INSURANCE.RD_REC_TYPE ,
HEALTH_INSURANCE.RD_EFFECT_FROM_DT ,
HEALTH_INSURANCE.RD_EFFECT_TO_DT ,
HEALTH_INSURANCE.RD_END_EFFECT_FROM_DT ,
HEALTH_INSURANCE.SEX_MAS_CD ,
HEALTH_INSURANCE.MARITAL_STATUS_CD ,
HEALTH_INSURANCE.EMP_CATG ,
HEALTH_INSURANCE.NO_OF_DEPENDENTS ,
CAST((
CASE 
    WHEN HEALTH_INSURANCE.AUTHORITY_LETTER_NO IS NULL 
    THEN HEALTH_INSURANCE.EMP_AL_NO 
    ELSE HEALTH_INSURANCE.AUTHORITY_LETTER_NO 
END) AS INT) AS EMP_AL_NO ,
HEALTH_INSURANCE.DOB ,
HEALTH_INSURANCE.EFF_DATE ,
HEALTH_INSURANCE.EFF_DATE2 ,
HEALTH_INSURANCE.NAME ,
CAST((SUBSTR(HEALTH_INSURANCE.RELATIONSHIP_CD, 5,2)) AS INT) AS 
RELATIONSHIP_CD_S ,
HEALTH_INSURANCE.RELATIONSHIP_CD ,
HEALTH_INSURANCE.DESIGNATION ,
HEALTH_INSURANCE.BRANCH ,
HEALTH_INSURANCE.BANK_ACCOUNT ,
HEALTH_INSURANCE.BANK_BRANCH_NAME ,
HEALTH_INSURANCE.PRE_EXISTING_AILMENT ,
HEALTH_INSURANCE.AUTHORITY_LETTER_NO ,
HEALTH_INSURANCE.AGE ,
HEALTH_INSURANCE.REGION ,
HEALTH_INSURANCE.CNIC ,
HEALTH_INSURANCE.CO_CODE ,
HEALTH_INSURANCE.EMP_LOCATION ,
HEALTH_INSURANCE.SUB_LOCATION ,
CATEGORY_LIMIT_HEADER.CLH_SYSTEM_NO ,
CATEGORY_LIMIT_HEADER.CTH_SYS_ID ,
CATEGORY_LIMIT_HEADER.CTH_POL_SYS_ID ,
CATEGORY_LIMIT_HEADER.CTH_END_NO_IDX ,
CATEGORY_LIMIT_HEADER.CTH_END_SR_NO ,
CATEGORY_LIMIT_HEADER.CTH_CATEGORY ,
CATEGORY_LIMIT_DETAIL.CLD_SYS_ID ,
CATEGORY_LIMIT_DETAIL.CLDH_SYS_ID ,
CATEGORY_LIMIT_DETAIL.CLD_COVER_CD ,
CATEGORY_LIMIT_DETAIL.CLD_END_IDX ,
CATEGORY_LIMIT_DETAIL.CLD_COVER_DESC ,
CATEGORY_LIMIT_DETAIL.CLD_CLM_TYPE_LIMIT ,
CATEGORY_LIMIT_DETAIL.CLD_CLM_REL ,
CATEGORY_LIMIT_DETAIL.CLD_CLM_AGE_FROM ,
CATEGORY_LIMIT_DETAIL.CLD_CLM_AGE_TO ,
CATEGORY_LIMIT_DETAIL.CLD_CLM_RB_LIMIT ,
CATEGORY_LIMIT_DETAIL.CLD_CATEGORY_LIMIT_FC ,
CATEGORY_LIMIT_DETAIL.CLD_CATEGORY_PREM_FC 
FROM
DB2ADMIN.HEALTH_INSURANCE AS HEALTH_INSURANCE 
    INNER JOIN DB2ADMIN.POLICY_RISK_COVER AS POLICY_RISK_COVER 
    ON HEALTH_INSURANCE.RD_POLICY_SYSTEM_NO = POLICY_RISK_COVER.
    RC_POLICY_SYSTEM_NO AND
    TRIM(RD_LEVEL1_ID) = TRIM(RC_LEVEL1_ID) 
        INNER JOIN DB2ADMIN.CATEGORY_LIMIT_HEADER AS CATEGORY_LIMIT_HEADER 
        ON HEALTH_INSURANCE.RD_POLICY_ID = CATEGORY_LIMIT_HEADER.
        CTH_POL_SYS_ID AND
        HEALTH_INSURANCE.EMP_CATG = CATEGORY_LIMIT_HEADER.CTH_CATEGORY 
            INNER JOIN DB2ADMIN.CATEGORY_LIMIT_DETAIL AS 
            CATEGORY_LIMIT_DETAIL 
            ON CATEGORY_LIMIT_HEADER.CTH_SYS_ID = CATEGORY_LIMIT_DETAIL.
            CLDH_SYS_ID AND
            POLICY_RISK_COVER.RISK_COVER_CD = CATEGORY_LIMIT_DETAIL.
            CLD_COVER_CD AND
            HEALTH_INSURANCE.RELATIONSHIP_CD = CATEGORY_LIMIT_DETAIL.
            CLD_CLM_REL 
WHERE
COALESCE(HEALTH_INSURANCE.AGE, 1) BETWEEN CATEGORY_LIMIT_DETAIL.
CLD_CLM_AGE_FROM AND
CATEGORY_LIMIT_DETAIL.CLD_CLM_AGE_TO
Run Code Online (Sandbox Code Playgroud)

Mik*_*ll' 5

一些可能与您相关的经验法则。. .

  • 切勿尝试在没有代表性 EXPLAIN 计划的情况下调整查询。代表性意味着从生产数据库或开发/测试数据库中获取 EXPLAIN 计划,这些数据库具有几乎相同的行数和几乎相同的值分布,理想情况下在类似的硬件上运行。不同的行数和不同的值分布通常意味着不同的执行计划。

  • 确保统计数据是最新的。

  • 对 JOIN 子句中使用的每个列和 WHERE 子句中使用的每个列进行索引(或验证索引)。我认为每个dbms 都使用索引实现主键约束和外键约束。有使用会有一些,不会让你删除此类索引,以及一个或两个放了你。由于我处理了很多不同的 dbms,因此我不会费心去记住哪个是哪个。我只是在需要知道的时候查看它。所以就看看吧。

  • 一个多列索引的性能可能优于三个单列索引。考虑合并索引。

  • 编写 sargable WHERE 子句。您的表达式COALESCE(HEALTH_INSURANCE.AGE, 1) BETWEEN one_column AND another_column必须为每一行评估 COALESCE() 函数——它不能使用索引。如果可能,将 NULL 替换为文字整数 1,并使该列不可为空。(这并不总是实用的,但不可 sargable WHERE 子句通常是性能杀手,尤其是在其他考虑因素引发全表扫描的情况下。)