1. Mysql 8.0 에서 사용자 함수 사용시 인덱스를 잘탈까요? 실행계획이 보이지않아서요
explain , explain analyze 시 확인이 안됩니다
Oracle 에선 개별 쿼리마다 인덱스를 타고 실행계획이 생성된다고하는데.. mysql 은 알방법이 없네요
2. 사용자 function 성능개선 방법이 있을까요?
1.2 만 건수 테이블의 pk컬럼을 값으로 페이징쿼리로
limit 로 10건 혹은 20건은 1초정도 걸리고 50건부터는 5초 이상 걸리는 쿼리입니다
한쿼리에 2개 function 20번 사용합니다
3. Mysql 8.0 사용자 function 과 count(1) over() 윈도우 함수를 같은 select 절에 사용시 성능이 엄청 느립니다 왜그럴까요?
함수수행쿼리 실행계획입니다
-> Limit: 20 row(s) (actual time=419352.233..419352.307 rows=20 loops=1)
-> Window aggregate with buffering: count(1) OVER () (actual time=419352.232..419352.304 rows=20 loops=1)
-> Nested loop inner join (cost=8927.16 rows=8027) (actual time=111.874..1240.618 rows=11365 loops=1)
-> Nested loop semijoin (cost=7827.13 rows=8027) (actual time=111.857..1214.503 rows=11365 loops=1)
-> Nested loop inner join (cost=6622.54 rows=8027) (actual time=111.748..621.480 rows=12361 loops=1)
-> Nested loop inner join (cost=5619.16 rows=8027) (actual time=111.698..333.299 rows=11574 loops=1)
-> Nested loop inner join (cost=4615.79 rows=8027) (actual time=111.667..175.703 rows=11575 loops=1)
-> Invalidate materialized tables (row from G) (cost=3612.41 rows=8027) (actual time=111.643..140.332 rows=11575 loops=1)
-> Sort: g.GOODS_CD (cost=3612.41 rows=8027) (actual time=111.642..138.315 rows=11575 loops=1)
-> Filter: ((g.SALE_SCN = '00') and (g.GOODS_CL_CD is not null) and (g.GOODS_CD is not null)) (cost=3612.41 rows=8027) (actual time=0.252..99.713 rows=11575 loops=1)
-> Index range scan on G using tp_goods_ix01, with index condition: ((g.RGST_DTIME >= <cache>(str_to_date('2021-01-01','%Y-%m-%d'))) and (g.RGST_DTIME < <cache>((str_to_date('2022-05-01','%Y-%m-%d') + interval 1 day)))) (cost=3612.41 rows=8027) (actual time=0.247..95.800 rows=11597 loops=1)
-> Single-row index lookup on M using PRIMARY (MD_CD=g.MD_CD) (cost=0.25 rows=1) (actual time=0.002..0.002 rows=1 loops=11575)
-> Index lookup on K using TP_GOODS_CL_ix01 (GOODS_CL_CD=g.GOODS_CL_CD), with index condition: (g.GOODS_CL_CD = k.GOODS_CL_CD) (cost=0.25 rows=1) (actual time=0.011..0.013 rows=1 loops=11575)
-> Index lookup on P using TP_GOODS_PRC_ix01 (GOODS_CD=g.GOODS_CD) (cost=0.25 rows=1) (actual time=0.020..0.024 rows=1 loops=11574)
-> Index lookup on Z using <auto_key0> (APLY_DTIME=p.APLY_DTIME, GOODS_CD=g.GOODS_CD) (actual time=0.002..0.002 rows=1 loops=12361)
-> Materialize (invalidate on row from G) (cost=0.38..0.38 rows=1) (actual time=0.047..0.047 rows=1 loops=12361)
-> Limit: 1 row(s) (cost=0.28 rows=1) (actual time=0.020..0.020 rows=1 loops=11365)
-> Sort: i.APLY_DTIME DESC, limit input to 1 row(s) per chunk (cost=0.28 rows=1) (actual time=0.020..0.020 rows=1 loops=11365)
-> Index lookup on I using TP_GOODS_PRC_ix01 (GOODS_CD=g.GOODS_CD), with index condition: (i.APLY_DTIME <= <cache>(now())) (actual time=0.011..0.012 rows=1 loops=11365)
-> Single-row index lookup on E using PRIMARY (ENTP_CD=g.ENTP_CD) (cost=0.37 rows=1) (actual time=0.002..0.002 rows=1 loops=11365)
-- 전체에 대해 조인이나 함수 사용 후 정렬 LIMIT 하지 말고 -- 정렬 LIMIT 부터 하고 난 후 일부만 가지고 조인이나 함수 사용하세요. SELECT ... FROM (SELECT goods_cd /* 상품코드 */ , goods_nm /* 상품명 */ , puchs_meth , cust_dscnt_yn , entp_cd /* 거래처코드 */ , md_cd /* md코드 */ , lrcl /* 대분류 */ , mdcl /* 중분류 */ , smcl /* 소분류 */ , dtcl /* 세분류 */ , taxt_yn , puchs_meth , goods_cl_cd , rgst_dtime , prc_dscnt_imposbl_yn , lmps_dscnt_imposbl_yn , set_goods_yn FROM tp_goods WHERE rgst_dtime >= STR_TO_DATE('2021-01-01', '%Y-%m-%d') AND rgst_dtime < DATE_ADD(STR_TO_DATE('2022-05-01','%Y-%m-%d'), INTERVAL 1 DAY) AND sale_scn = '00' ORDER BY goods_cd LIMIT 0, 20 ) g , tp_goods_prc p , tp_entp e , tp_md m , tp_goods_cl k WHERE ... ;