MySQL查詢優化一例——也說說 Using intersect


生產上面有一條sql查詢很慢,需要7到8秒左右,簡化之后的sql如下所示:

SELECT
	mingxi.*
FROM
	(
		SELECT
			btjc01.id,			
			department.`name` AS btjc01011,
			btjc01011 AS obj,
			btjc01.inibeginmonth AS beginYearMonth,
			lsbtsj.btje AS btjc01030,			
						
			CASE
		WHEN btjc01.inibeginmonth ='2019-10' THEN
			'是'
		ELSE
			'否'
		END AS isadd
		FROM
			btjc01
		INNER JOIN department ON department.Id = btjc01.btjc01038
		INNER JOIN lsbtsj ON lsbtsj.btrid = btjc01.Id
		WHERE
			btjc01.btjc01037 = '3'
		AND btjc01046 ='江西省'
		AND btjc01047 ='九江市'
		AND btjc01048 ='修水縣'		
		AND lsbtsj.btqsyf <='2019-10'
		AND lsbtsj.btjzyf >='2019-10'
		AND beginYearMonth != inibeginmonth
		UNION ALL
			SELECT
				btjc01.id,
						
				department.`name` AS btjc01011,
				btjc01011 AS obj,
				btjc01.beginYearMonth,
				btjc01.btjc01030,				
				
				CASE
			WHEN btjc01.inibeginmonth ='2019-10' THEN
				'是'
			ELSE
				'否'
			END AS isadd
			FROM
				btjc01 
			INNER JOIN department ON department.Id = btjc01.btjc01038
			INNER JOIN btgg03 ON btgg03.Id = btjc01.btjc01040
			WHERE
				btjc01.btjc01037 = '3'
		AND btjc01046 ='江西省'
		AND btjc01047 ='九江市'
		AND btjc01048 ='修水縣'
		AND (beginYearMonth <='2019-10')
	) AS mingxi

LIMIT 100,200;

 

執行計划如下所示:

  可以看到 執行計划里面出現了 Using intersect,btjc01046 btjc01048 btjc01037 btjc01047 多個索引來進行數據的過濾。

另外發現一個問題,里面的 union all 子查詢 卻只需要 0.4秒就可以執行完成:

SELECT
			btjc01.id,			
			department.`name` AS btjc01011,
			btjc01011 AS obj,
			btjc01.inibeginmonth AS beginYearMonth,
			lsbtsj.btje AS btjc01030,			
						
			CASE
		WHEN btjc01.inibeginmonth ='2019-10' THEN
			'是'
		ELSE
			'否'
		END AS isadd
		FROM
			btjc01
		INNER JOIN department ON department.Id = btjc01.btjc01038
		INNER JOIN lsbtsj ON lsbtsj.btrid = btjc01.Id
		WHERE
			btjc01.btjc01037 = '3'
		AND btjc01046 ='江西省'
		AND btjc01047 ='九江市'
		AND btjc01048 ='修水縣'		
		AND lsbtsj.btqsyf <='2019-10'
		AND lsbtsj.btjzyf >='2019-10'
		AND beginYearMonth != inibeginmonth
		UNION ALL
			SELECT
				btjc01.id,
						
				department.`name` AS btjc01011,
				btjc01011 AS obj,
				btjc01.beginYearMonth,
				btjc01.btjc01030,				
				
				CASE
			WHEN btjc01.inibeginmonth ='2019-10' THEN
				'是'
			ELSE
				'否'
			END AS isadd
			FROM
				btjc01 
			INNER JOIN department ON department.Id = btjc01.btjc01038
			INNER JOIN btgg03 ON btgg03.Id = btjc01.btjc01040
			WHERE
				btjc01.btjc01037 = '3'
		AND btjc01046 ='江西省'
		AND btjc01047 ='九江市'
		AND btjc01048 ='修水縣'
		AND (beginYearMonth <='2019-10')  

 

執行計划如下:

 

 比較一下前面和后面兩個的執行計划,可以發現 都是有了 Using intersect 但是呢后面一個卻只需要0.4秒,而在外面加上一層 select * from t,時間卻需要7到8秒。一直沒有明白什么原因。

最后的優化是去掉 Using interset ,使用 force index 手動指定使用索引 btjc01048:

SELECT
	mingxi.*
FROM
	(
		SELECT
			btjc01.id,			
			department.`name` AS btjc01011,
			btjc01011 AS obj,
			btjc01.inibeginmonth AS beginYearMonth,
			lsbtsj.btje AS btjc01030,			
						
			CASE
		WHEN btjc01.inibeginmonth ='2019-10' THEN
			'是'
		ELSE
			'否'
		END AS isadd
		FROM
			btjc01 force index(btjc01048)
		INNER JOIN department ON department.Id = btjc01.btjc01038
		INNER JOIN lsbtsj ON lsbtsj.btrid = btjc01.Id
		WHERE
			btjc01.btjc01037 = '3'
		AND btjc01046 ='江西省'
		AND btjc01047 ='九江市'
		AND btjc01048 ='修水縣'		
		AND lsbtsj.btqsyf <='2019-10'
		AND lsbtsj.btjzyf >='2019-10'
		AND beginYearMonth != inibeginmonth
		UNION ALL
			SELECT
				btjc01.id,
						
				department.`name` AS btjc01011,
				btjc01011 AS obj,
				btjc01.beginYearMonth,
				btjc01.btjc01030,				
				
				CASE
			WHEN btjc01.inibeginmonth ='2019-10' THEN
				'是'
			ELSE
				'否'
			END AS isadd
			FROM
				btjc01 force index(btjc01048)
			INNER JOIN department ON department.Id = btjc01.btjc01038
			INNER JOIN btgg03 ON btgg03.Id = btjc01.btjc01040
			WHERE
				btjc01.btjc01037 = '3'
		AND btjc01046 ='江西省'
		AND btjc01047 ='九江市'
		AND btjc01048 ='修水縣'
		AND (beginYearMonth <='2019-10')
	) AS mingxi

LIMIT 100,200;

  執行時間需要1.2秒左右,和0.4秒相比,還是有差距。執行計划如下;

 

 可以看到沒有了 Using interset. 我們強制使用索引 btjc01048.

 

總結:

如果出現 Using interset 需要注意是否mysql優化器選擇的是否是最佳的索引方案。是否可以通過force index來選擇更優的索引。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM