技能提升数据库优化理论实践

Posted AI脑力波

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技能提升数据库优化理论实践相关的知识,希望对你有一定的参考价值。

SQL是Structured QueryLanguage的简称,指结构化查询语言。


SQL在网上有很多的优化理论,但在实际工作中可以使用这些规范优化理论的场景很少。


近日,收到一封运维邮件警告,发现SQL耗时较长且执行次数较多,对SQL进行优化就显得很有必要。


一、SQL优化前情况


1、具体SQL语句如下:

SELECT COUNT(DISTINCT A.ID_NO) FROM TM_APP_MAIN M,TM_APP_PRIM_APPLICANT_INFO A, TM_APP_PRIM_CONTACT_INFO C

WHERE 1=1 AND M.APP_NO=C.APP_NO(+) ANDM.APP_NO=A.APP_NO AND C.TEL_SOURCE='APPLY'

AND C.DELETE_FLAG='0' ANDA.ID_NO<>'510215********0016' AND M.STATUS NOT IN ('J', 'C') AND(A.CELLPHONE = '138******74' OR C.CONTACT_MOBILE ='138******74' ) ANDA.CREATE_TIME >= to_date('2016-01-01','yyyy-mm-dd')


2、从现实情况来看,每条SQL语句执行时间长达55秒左右。


3、执行计划如下:

1        SIMPLE  A       ALL   ID_NO,CREATE_TIME,APP_NO,ID_NO_2,CELLPHONE                              1452930  Using where

1        SIMPLE  M     ref    APP_NO,APP_NO_2,APP_NO_3,STATUSAPP_NO   63     buzi_data_tm.A.APP_NO         1       Usingwhere

1        SIMPLE  C       ref    APP_NO,CONTACT_MOBILE,CONTACT_MOBILE_2        APP_NO   63     buzi_data_tm.A.APP_NO         2       Usingwhere



二、SQL优化过程


上面SQL没有太大的问题 ,但发现以下地方可作进一步优化:


一是从执行计划看,TM_APP_MAIN 主表都是全表扫描,每次都要查询140万的记录。


二是根据身份证号查询使用了 <> ,即使有索引也不会执行。


三是根据手机号查询条件中使用了 OR,即使有索引也不会执行,从上面的执行计划可以看到,且辅助表的数据远远超过140万的记录再做全表扫描就非常效率低下了。


对以上几个地方,特别是不能使用查询的地方进行了优化。


根据一般SQL查询的优化方案,对于OR一般采用UNION来代替,这样对于手机号码的查询就能用到很好的索引,修改后查询SQL如下:

SELECT

         COUNT(DISTINCTA.ID_NO)

FROM

         (

                   SELECT

                            APP_NO

                   FROM

                            TM_APP_MAIN

                   WHERE

                            STATUSNOT IN ('J', 'C')

         )M left join

         (

                   SELECT

                            APP_NO,

                            ID_NO

                   FROM

                            TM_APP_PRIM_APPLICANT_INFO

                   WHERE

                            CREATE_TIME>= to_date('2016-01-01','yyyy-mm-dd')

                   ANDcellphone = '138******74'

                   ANDid_no <> '510215********0016'

                   UNIONALL

                            SELECT

                                     app_no,

                                     ''ID_NO

                            FROM

                                     TM_APP_PRIM_CONTACT_INFO

                            WHERE

                                     contact_mobIle= '138******74'

                            ANDTEL_SOURCE = 'APPLY'

                            ANDDELETE_FLAG = '0'

                            ANDNOT EXISTS (

                                     SELECT

                                               1

                                     FROM

                                               TM_APP_PRIM_APPLICANT_INFO

                                     WHERE

                                               TM_APP_PRIM_APPLICANT_INFO.app_no= TM_APP_PRIM_CONTACT_INFO.app_no

                                     ANDTM_APP_PRIM_APPLICANT_INFO.id_no = '510215********0016'

                            )

         )A

on M.APP_NO = A.APP_NO;

执行计划如下:mysql版本

1       PRIMARY<derived3>       ALL                                        4       Using where

1       PRIMARY<derived2>       ref    <auto_key0>    <auto_key0>    63     A.APP_NO        13884       Usingindex

3       DERIVEDdws_dsst_rmps_TM_APP_PRIM_APPLICANT_INFO      ref    ID_NO,CREATE_TIME,ID_NO_2,CELLPHONE         CELLPHONE     63     const        1       Usingindex condition; Using where

4       UNION     dws_dsst_rmps_TM_APP_PRIM_CONTACT_INFO         ref    CONTACT_MOBILE,CONTACT_MOBILE_2         CONTACT_MOBILE63     const        1       Usingindex condition; Using where

5       DEPENDENTSUBQUERYdws_dsst_rmps_TM_APP_PRIM_APPLICANT_INFO      ref    ID_NO,APP_NO,ID_NO_2         ID_NO      93     const        1       Using index condition; Using where

         UNIONRESULT         <union3,4>       ALL                                                 Usingtemporary

2       DERIVEDdws_dsst_rmps_TM_APP_MAIN    ALL   STATUS                                 1452930  Using where


三、结语

SQL优化以后,从MYSQL执行情况来看,对于两个辅助的大表,都能正常的使用手机号作为查询条件,并且执行时间由55秒下降为0.3秒,一个非常小的优化规范就带来如此巨大的优化效果,真可谓于细微处见真章!


以上是关于技能提升数据库优化理论实践的主要内容,如果未能解决你的问题,请参考以下文章

淘宝小程序体验优化:数据分析和优化实践

转发算力提升117%,资源使用下降50%,打开集群优化正确姿势

如何做SQL优化?优化SQL语句,提高SQL查询效率。Effective MySQL之SQL语句最优化

开发者应该掌握的Java代码优化技能

clickhouse优化最佳实践(易企秀)

mysql数据库索引优化与实践