一次mysql的sql优化

先上原sql语句(萌新写的),

四张表,TPS_QMCH 5万左右数据,TPS_WWFCT表 5万,TPS_XMCH20万,ST_LPM50万
执行时间30秒

SELECT
    	M.*
    FROM
    	(
    		SELECT DISTINCT
    			N.ID,
    			N.qxdm,
    			N.ywslid,
    			N.xmdz,
    			N.kfqymc,
    			N.chdwmc,
    			N.rksj,
    			n.xmmc
    		FROM
    			(
    				SELECT
    					qmch.ID,
    					lpm.qxdm,
    					lpm.ZRZZL,
    					qmch.ywslid,
    					qmch.xmdz,
    					qmch.kfqymc,
    					qmch.chdwmc,
    					qmch.rksj,
    					qmch.xmmc
    				FROM
    					TPS_QMCH qmch,
    					ST_LPM lpm
    				WHERE
    					qmch.ID = lpm.chid
    				AND lpm.JCNF = '2016'
    				AND qmch.ID IN (
    					SELECT
    						qmchid
    					FROM
    						TPS_WWFCT
    					WHERE
    						lsbz = 0
    				)
    				AND qmch.ID IN (
    					SELECT
    						lpm.chid
    					FROM
    						ST_LPM lpm
    					WHERE
    						lpm.zrzid IN (
    							SELECT
    								zrzid
    							FROM
    								TPS_XMCH xmch
    							WHERE
    								xmch.bjbz = 1
    							AND xmch.sffb = 1
    						)
    				)
    			) N
    	) M
    WHERE
    	1 = 1
    AND M.QXDM IS NOT NULL
    AND M.xmmc IS NOT NULL
    ORDER BY
    	M.rksj DESC

一. 第一步

第一反应,肯定有关联字段没有加索引
看执行计划
在这里插入图片描述
type全是all,看rows基本上是全表扫描,看extra没有用到索引
在ST_LPM表的chid和zrzid上加上索引,执行时间缩短到2秒
再看执行计划
在这里插入图片描述
可以看到type出现ref,rows的扫描行数也急剧减少

二. 第二步

再仔细观察sql,多处用了in关键字,其中还有嵌套,肯定会有性能问题
我们先看下mysql帮我们自动优化后的语句长什么样

  /* select#1 */
    SELECT
    	`m`.`ID` AS `ID`,
    	`m`.`qxdm` AS `qxdm`,
    	`m`.`ywslid` AS `ywslid`,
    	`m`.`xmdz` AS `xmdz`,
    	`m`.`kfqymc` AS `kfqymc`,
    	`m`.`chdwmc` AS `chdwmc`,
    	`m`.`rksj` AS `rksj`,
    	`m`.`xmmc` AS `xmmc`
    FROM
    	(
    		/* select#2 */
    		SELECT DISTINCT
    			`oracle2mysql`.`qmch`.`ID` AS `ID`,
    			`oracle2mysql`.`lpm`.`QXDM` AS `qxdm`,
    			`oracle2mysql`.`qmch`.`YWSLID` AS `ywslid`,
    			`oracle2mysql`.`qmch`.`XMDZ` AS `xmdz`,
    			`oracle2mysql`.`qmch`.`KFQYMC` AS `kfqymc`,
    			`oracle2mysql`.`qmch`.`CHDWMC` AS `chdwmc`,
    			`oracle2mysql`.`qmch`.`RKSJ` AS `rksj`,
    			`oracle2mysql`.`qmch`.`XMMC` AS `xmmc`
    		FROM
    			`oracle2mysql`.`tps_qmch` `qmch` semi
    		JOIN (
    			`oracle2mysql`.`st_lpm` `lpm`
    			JOIN `oracle2mysql`.`tps_xmch` `xmch`
    		) semi
    		JOIN (`oracle2mysql`.`tps_wwfct`)
    		JOIN `oracle2mysql`.`st_lpm` `lpm`
    		WHERE
    			(
    				(
    					`oracle2mysql`.`lpm`.`ZRZID` = `oracle2mysql`.`xmch`.`ZRZID`
    				)
    				AND (
    					`oracle2mysql`.`tps_wwfct`.`LSBZ` = 0
    				)
    				AND (
    					`oracle2mysql`.`xmch`.`SFFB` = 1
    				)
    				AND (
    					`oracle2mysql`.`xmch`.`BJBZ` = 1
    				)
    				AND (
    					`oracle2mysql`.`lpm`.`JCNF` = 2016
    				)
    				AND (
    					`oracle2mysql`.`qmch`.`ID` = `<subquery4>`.`qmchid`
    				)
    				AND (
    					`<subquery5>`.`chid` = `<subquery4>`.`qmchid`
    				)
    				AND (
    					`oracle2mysql`.`lpm`.`CHID` = `<subquery4>`.`qmchid`
    				)
    			)
    	) `m`
    WHERE
    	(
    		(`m`.`qxdm` IS NOT NULL)
    		AND (`m`.`xmmc` IS NOT NULL)
    	)
    ORDER BY
    	`m`.`rksj` DESC |

可以看到mysql已经自动把in转化成join来实现,那么我们可以自己直接用join来替代in,减少mysql的自动优化,来提高效率
下面是用join改写最终的sql

SELECT
    	M.*
    FROM
    	(
    		SELECT DISTINCT
    			N.ID,
    			N.qxdm,
    			N.ywslid,
    			N.xmdz,
    			N.kfqymc,
    			N.chdwmc,
    			N.rksj,
    			n.xmmc
    		FROM
    			(
    				SELECT
    					qmch.ID,
    					lpm.qxdm,
    					lpm.ZRZZL,
    					qmch.ywslid,
    					qmch.xmdz,
    					qmch.kfqymc,
    					qmch.chdwmc,
    					qmch.rksj,
    					qmch.xmmc
    				FROM
    					ST_LPM lpm
    				JOIN TPS_QMCH qmch ON qmch.ID = lpm.chid
    				JOIN TPS_WWFCT WWFCT ON lpm.chid = WWFCT.qmchid
    				JOIN TPS_XMCH xmch ON lpm.zrzid = xmch.zrzid
    				WHERE
    					lpm.JCNF = '2016'
    				AND xmch.bjbz = 1
    				AND xmch.sffb = 1
    			) N
    	) M
    WHERE
    	1 = 1
    AND M.QXDM IS NOT NULL
    AND M.xmmc IS NOT NULL
    ORDER BY
    	M.rksj DESC

执行时间0.7秒,再看执行计划,就清爽了许多,执行阶段也变少了
在这里插入图片描述

三.第三步

其实最有效的lpm.JCNF字段上一直没有加索引,是为了之前的优化更加明显,加上索引后
执行时间0.1秒,再看执行计划
在这里插入图片描述

可以看到基本上都用的了索引,rows扫描很少,extra里面包含了Using index

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值