MySQL Join 튜닝 문의 0 5 1,004

by 꿈을향해 [SQL Query] [2018.06.27 09:33:45]


안녕하세요.

 

아래와 같은 쿼리가 있습니다. 상품테이블의 카테고리를 보여주려고 join을 하고 있는데 제 생각엔 모델링부터가 잘못된 것 같습니다.

 

SELECT G.*
	, C.T1_CTG_NM
	, C.T2_CTG_NM
	, C.T3_CTG_NM
	, CONCAT_WS(',',T.T1_CTG_NO,T.T2_CTG_NO,T.T3_CTG_NO,T.T4_CTG_NO ) AS CTG_NO_ARR
FROM 
(
	SELECT     
	       T1.CTG_NO AS T1_CTG_NO
	     , T1.CTG_NM AS T1_CTG_NM
	     , T2.CTG_NO AS T2_CTG_NO
	     , T2.CTG_NM AS T2_CTG_NM
	     , T3.CTG_NO AS T3_CTG_NO
	     , T3.CTG_NM AS T3_CTG_NM
	     , T4.CTG_NO AS T4_CTG_NO
	     , T4.CTG_NM AS T4_CTG_NM
	FROM CTG T1
		LEFT OUTER JOIN CTG T2 ON T2.UP_CTG_NO = T1.CTG_NO
		LEFT OUTER JOIN CTG T3 ON T3.UP_CTG_NO = T2.CTG_NO
		LEFT OUTER JOIN CTG T4 ON T4.UP_CTG_NO = T3.CTG_NO
	) C, (
		SELECT PR.*
			, CTG.CTG_NO
			, CTG.CTG_LVL
		FROM PRODUCT PR
			LEFT OUTER JOIN PRODUCT_CTG PRC ON PRC.GOODS_NO = PR.GOODS_NO AND PRC.DLGT_CTG_YN = 'Y' AND IFNULL(PRC.DEL_YN,'N') = 'N'
			LEFT OUTER JOIN CTG CTG ON CTG.CTG_NO = PRC.CTG_NO
	) G
WHERE G.CTG_NO=CASE G.CTG_LVL WHEN 1 THEN T1_CTG_NO
					WHEN 2 THEN T2_CTG_NO
					WHEN 3 THEN T3_CTG_NO
					WHEN 4 THEN T4_CTG_NO
					ELSE '' END

 

 

C라는 인라인뷰는 0.041초가 나오고 (2499 rows)

G라는 인라인뷰는 0.32초가 나옵니다. (58636 rows)

여기까진 문제 없습니다.

그런데 둘을 JOIN하면 25초라는 수치가 나옵니다. 참고로 페이징처리는 할 수 없습니다. 전체 row가 다 나와야해서요.

Hash Join이 있으면 속도가 나올것 같지만 아쉽게 MySQL이여서... 대신 Join Buffer와 Block Nested Join 기법을 사용하여 JOIN을 하는데 속도가 나지 않습니다. 일반 NL Join을 하면 28초 정도 걸립니다.

좋은 방안이 있을까요.?? 

 

감사합니다.

 

by 우리집아찌 [2018.06.27 09:52:27]

MY-SQL은 잘모르긴한데..

재귀쿼리로 한방에 깔끔하게 될거같은데요.


by 꿈을향해 [2018.06.27 09:55:37]

재귀쿼리가 18년에 나온 5.8 version부터 지원되서요 ㅠ.. 


by 우리집아찌 [2018.06.27 10:15:58]

헉...


by 마농 [2018.06.27 13:08:18]
SELECT pr.*
     , c1.ctg_no
     , c1.ctg_nm
     , c1.ctg_lvl
     , CASE c1.ctg_lvl WHEN 1 THEN c1.ctg_nm
                       WHEN 2 THEN c2.ctg_nm
                       WHEN 3 THEN c3.ctg_nm
                       WHEN 4 THEN c4.ctg_nm
                        END ctg_nm_1
     , CASE c1.ctg_lvl WHEN 2 THEN c1.ctg_nm
                       WHEN 3 THEN c2.ctg_nm
                       WHEN 4 THEN c3.ctg_nm
                        END ctg_nm_2
     , CASE c1.ctg_lvl WHEN 3 THEN c1.ctg_nm
                       WHEN 4 THEN c2.ctg_nm
                        END ctg_nm_3
     , CASE c1.ctg_lvl WHEN 4 THEN c1.ctg_nm
                        END ctg_nm_4
     , CONCAT_WS(',', c4.ctg_no, c3.ctg_no, c2.ctg_no, c1.ctg_no) ctg_no_arr
     , CONCAT_WS(',', c4.ctg_nm, c3.ctg_nm, c2.ctg_nm, c1.ctg_nm) ctg_nm_arr
  FROM product pr
  LEFT OUTER JOIN product_ctg prc
    ON prc.goods_no = pr.goods_no
   AND prc.dlgt_ctg_yn = 'Y'
   AND IFNULL(prc.del_yn, 'N') = 'N'
  LEFT OUTER JOIN ctg c1 ON prc.ctg_no   = c1.ctg_no
  LEFT OUTER JOIN ctg c2 ON c1.up_ctg_no = c2.ctg_no
  LEFT OUTER JOIN ctg c3 ON c2.up_ctg_no = c3.ctg_no
  LEFT OUTER JOIN ctg c4 ON c3.up_ctg_no = c4.ctg_no
;

 


by 꿈을향해 [2018.06.27 15:07:23]

감사합니다!!. 아 왜 이 합치는 방법이 생각이 안났을까요 ㅠ.. 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입