zoukankan      html  css  js  c++  java
  • 一些关于SQL优化的总结

    由于这个项目一直都是mysql所以写点mysql的

    1.数据存储引擎的选择,MyISAM 和 InnoDB 的选择 

    InnoDB 一般都会选择这个,但是如果真的涉及到一些不涉及增删的表,可以考虑下MyISAM 该引擎不支持事务,不支持外键,优点就是访问速度快,如果都是查询的话,这个存储引擎可能会使你的效率更高点

    2.查询SQL中添加 limit 我们项目组SQL规范中都有写,任何查询都应该加上 limit ,这么做有两个原因:1.防止表中数据过大,导致大量数据一把捞出,导致内存溢出,GG 2.在查询一条数据是加上 limit 1 会时效率更高

    3.not exexists 代替 not in  not exists 查询时会走索引,而not in就没戏了,在数据量比较大的时候尤其能看出显著的效果。

    4.like 关键字的使用 ‘关键字%’ 不要使用两侧都有%% 这样也会使索引失效

    5.适当的创建索引

    《以下都是扯犊子,一点点蛋用,还是别看下面的了》

    慢SQL核查

    NO.1 :com.cmos.dao.basesr.TSrProblemProcesExceptionMapper.queryExceptionCount

    SELECT

        count(1)

    FROM

        t_sr_problem_proces t1,

        (

           SELECT

               WRKFM_ID

           FROM

               t_sr_problem_process_modify

           GROUP BY

               WRKFM_ID

        ) t2

    WHERE

        t1.ACPT_TIME >= '2018-07-31 00:00:00'

    AND t1.ACPT_TIME <= '2018-08-31 23:59:59'

    AND t1.TENANT_ID = '100000'

    AND t1.PROV_CODE = '00030016'

    AND t1.WRKFM_ID = t2.WRKFM_ID

    AND t1.WRKFM_STS_CD IN ('3', '4', '5', '7', '8');

    分析:

    子查询的结果集t2在与t1表联合时会走全表扫描,且没有索引。

    改造:

    SELECT

        count(distinct t1.WRKFM_ID)

    FROM

        t_sr_problem_proces t1,

        t_sr_problem_process_modify t2

    WHERE

        t1.ACPT_TIME >= '2018-07-31 00:00:00'

    AND t1.ACPT_TIME <= '2018-08-31 23:59:59'

    AND t1.TENANT_ID = '100000'

    AND t1.PROV_CODE = '00030016'

    AND t1.WRKFM_ID = t2.WRKFM_ID

    AND t1.WRKFM_STS_CD IN ('3', '4', '5', '7', '8');

    改造后的SQL两条执行计划均走索引查询

    NO.2  com.cmos.dao.basesr.TSrProblemProcesExceptionMapper.queryExceptionCount_His

    SELECT

     count(1)

    FROM

     t_sr_problem_proces_h_2018 t1,

     (

      SELECT

       WRKFM_ID

      FROM

       t_sr_problem_process_modify_his_2018

      GROUP BY

       WRKFM_ID

     ) t2

    WHERE

     t1.ACPT_TIME >= ?

    AND t1.ACPT_TIME <= ?

    AND t1.TENANT_ID = ?

    AND t1.PROV_CODE = ?

    AND t1.WRKFM_ID = t2.WRKFM_ID

    分析:

    子查询的结果集t2在与t1表联合时会走全表扫描,且没有索引。

    NO.3   com.cmos.service.commonsv.generator.TSrCfgHotSrtypeMapper.selectByCond

    SELECT

        REC_ID,

        TENANT_ID,

        PROV_CODE,

        SRV_REQST_TYPE_ID,

        CITY_CODE,

        SRV_REQST_BIG_CLA_ID,

         HTPOINT_SRV_REQST_TYPE_NM,

        HTPOINT_SRV_REQST_TYPE_FULL_NM,

        OP_STAFF_ID,

        ARGE_SEQNO,

        ORG_BRNCH_ID,

        CRT_TIME,

        MODF_TIME,

        HTPOINT_SRV_TYPE_CD,

        BATCH_NUM,

        VALID_FLAG,

        ACPT_FLAG,

        BIG_CLA_NM,

        LTSZ_WRKFM_FLAG,

        EFF_TIME,

        INVLD_TIME,

        FRONT_SHOW_NM

    FROM

        t_sr_cfg_hot_srtype

    ORDER BY

        ?

    LIMIT ?,?

    分析:

    手动热点服务请求类型查询:

    1.该SQL是简单的单标查询,经过排查该xml中的sql语句可以删除

    distinct

    2.该sql查询的字段可以看出,包含主键,因此distinct 将毫无意义,如果误传的话还会降低该查询的性能

    该查询是简单的单表查询,经核查 t_sr_cfg_hot_srtype 在配置库,所有省份共用一张表,该表主键是REC_ID,在查询是REC_ID不会由前台传过来,因此where 子句中不会有 REC_ID 导致查询不会走索引查

    改造: 建议对于该表新增其他列的索引

    NO.4 com.cmos.service.commonsv.generator.TSrCfgHotSrtypeRuleMapper.selectByCond

    SELECT

        RULE_ID,

        TENANT_ID,

        PROV_CODE,

        HTPOINT_SRV_TYPE_CD,

        EMBR_CITY_FLAG,

        EMBR_BIG_CLA_FLAG,

        INTERVALG,

        TOPN,

        OP_STAFF_ID,

        ORG_BRNCH_ID,

        CRT_TIME,

        MODF_TIME

    FROM

        t_sr_cfg_hot_srtype_rule

    WHERE

        ?

    ORDER BY

        ?

    分析:

    1.该SQL是简单的单标查询,经过排查该xml中的sql语句可以删除distinct

    该sql查询的字段可以看出,包含主键,因此distinct 将毫无意义,如果误传的话还会降低该查询的性能

    2.该表位于配置库,多省共用一张表存储数据,经查询该表仅有主键一个索引,在查询时不会传主键到where 子句中,因此导致该简单查询为全表扫描且不走索引,无论哪个省的数据量足够大都会影响其他省的正常查询。

    改进:建议该表新增索引

    NO.5 com.cmos.dao.basesr.TSrProcessDetailHisMapper.selectByRouteLgIds

    SELECT

        DSPS_PROC_ID,

        TENANT_ID,

        LG_ID,

        ROUTE_LG_ID,

        WRKFM_ID,

        OP_TYPE_CD,

        FCT_NO,

        FCT_NM,

        FCT_VAL,

        DSPS_STAFF_ID,

        DSPS_ORG_BRNCH_ID,

        CRT_TIME,

        MODF_TIME,

        PROV_CODE,

        ELEMENT_DISPLAY_NAME

    FROM

        t_sr_process_detail_his_201808

    WHERE

        ROUTE_LG_ID IN (?,?,?)

    分析:

    1.排查xml的时候,发现#{id} 没有添加jdbcType

    2.以 t_sr_process_detail_his_201808 为例,该表中除主键外 还有在WRKFM_ID上有索引,但是针对该SQL WRKFM_ID 不在where子句中,因此查询为全表扫面且不走索引

    改进:在 ROUTE_LG_ID 字段上添加索引

    NO.6 SrPageInfo.selectCfgPageType

    SELECT DISTINCT

        (APP_CLFC_CD)

    FROM

        t_sr_page_info

    WHERE

        TENANT_ID = ?

    AND PROV_CODE = ?

    分析:

    t_sr_page_info位于配置库,主键:PAGE_ID 除主键外无其他索引

    该查询虽然是简单查询,但是在数据量很大的时候,全表扫面会效率极低。

    改进:在PROV_CODE 字段上新增索引

    查询表中索引:

    show index from table_name

  • 相关阅读:
    词云
    结巴分词
    重复值处理
    异常值判断
    MySQL基本使用
    缺失值处理
    fit_transform和transform的区别
    sklearn学习笔记之简单线性回归
    图解机器学习
    Unity---UNet学习(1)----基本方法介绍
  • 原文地址:https://www.cnblogs.com/zhaiyt/p/9571014.html
Copyright © 2011-2022 走看看