mysql select 속도 문제입니다... 0 1 749

by 개리끼리 [MySQL] [2017.11.07 10:52:40]


구루.PNG (19,351Bytes)

현재 A C 가 다대다 관계 테이블입니다.

그래서 B라는 연결테이블을 만들었습니다.

이렇게 해서 A(5만건) B(6만건) C(1000건) 을 조인해야 하는 상황입니다.

위 3테이블을 조인할시 0.7초 정도 걸리구요. 

저걸 또 group by 시켜야 합니다. C테이블에 있는 한 컬럼 기준으로요

여기서 1초가 늘어납니다.

그리고 저걸 order by 시키고 rownum 부여하면서 쿼리가 3초 까지 늘어납니다.

제가 궁금한건 저 쿼리가 원래 3초정도 걸리는게 맞는가 입니다. 

저 쿼리가 웹에서 돌리는거라 페이지 넘기는데 3초이상 걸려버리니 너무 답답해서 1초 정도로 줄이고 싶은데 괜한 짓 하고 있는건가 싶어서요.

제가 해본건

1.select * 대신 컬럼명 일일이 다 써주기

2.join 순서 바꿔보기. inner join, left outer join 으로 바꿔보기 (이 중 제일 속도가 빠른걸로 해놨습니다.)

3.rownum 없애보기( 이거 없애보니 0.5초 정도 주는데요. 페이징 처리때문에 뺄 수가 없습니다.)

4.explain 사용( using temporary, using filesort 이거 두개는 group by, group_concat 때문에 발생하는데요.

group by 절에서 order by null 쓰면 filesort는 없어진다던데 저는 group_concat 때문에 저게 발생하는거라 안없어지는것 같습니다.

using temporary는 그룹바이 조건에 들어가는 컬럼에 인덱스를 주라던데... 하나는 어차피 primary키구 나머지 x,y컬럼은 제가 인덱스를 걸어줬습니다. x,y 컬럼을 group by 조건에 사용하지 않아도 using temporary는 없어지지 않습니다.)

5.group by절에서 order by 조건 같이 쓰지 말기. 

6. primary 인덱스를 타지 않는 테이블에 use index 강제지정 해보기 (이렇게 해봤자 인덱스를 타지 않습니다 ㅠ. explain 결과는 맨 밑에 있습니다.)

쿼리는

SELECT WELL_NM,
       PERM_NT_NO,
       X,
       Y,
       WMETER_NO,
       WELL_NO,
       WELL_CODE,
       JIBUN_JUSO,
       RNUM,
       FN_CODE_NM_RETURN('NKB001', VTN_CD) AS VTN_NM,
       CONCAT(LAST_VALUE(@RNUM))           AS TOTAL_CNT
FROM (SELECT WELL_NM,
             PERM_NT_NO,
             X,
             Y,
             WMETER_NO,
             VTN_CD,
             WELL_NO,
             WELL_CODE,
             JIBUN_JUSO,
             CONCAT(@RNUM := @RNUM + 1)   AS RNUM
      FROM (SELECT GROUP_CONCAT(AA.well_nm)        WELL_NM,
                   GROUP_CONCAT(AA.perm_nt_no)     PERM_NT_NO,
                   AA.X,
                   AA.Y,
                   AA.WMETER_NO,
                   AA.VTN_CD,
                   GROUP_CONCAT(AA.WELL_NO)        WELL_NO,
                   GROUP_CONCAT(AA.WELL_CODE)      WELL_CODE,
                   AA.JIBUN_JUSO
            FROM (SELECT A.X,
                         A.Y,
                         A.WMETER_NO,
                         A.VTN_CD,
                         A.JIBUN_JUSO,
                         C.WELL_NM,
                         C.PERM_NT_NO,
                         C.WELL_NO,
                         C.WELL_CODE,
                         C.WNAME_NO
                  FROM ((nongkiban.tb_wmeter        a
                    JOIN nongkiban.tb_wmeter_bridge b)
                   JOIN nongkiban.tb_well c)
                  WHERE     1 = 1
                        AND a.WMETER_NO = b.WMETER_NO AND b.WELL_NO = c.WELL_NO
                        AND A.DELETE_YN = 'N'
                        AND C.DELETE_YN = 'N') AA
            GROUP BY AA.WMETER_NO, AA.X, AA.Y
            ORDER BY NULL) TT,
           (SELECT @rnum := 0) RN
      WHERE 1 = 1
      ORDER BY IF(ascii(substring(WELL_NM, 1)) < 128, 9, 1) ASC,
               WELL_NM ASC) Z
WHERE RNUM > 10 AND RNUM <= 20;

이거구요. explain 결과는 밑에 있습니다.
이상한게 explain의 C테이블 결과를 보면 keys가 null 인데요.

조인할 때 select 컬럼중에 C테이블의 WELL_NO(primary키)만 조회하면 keys가 primary가 나오는데요. 다른 컬럼 WELL_NM 이런걸 조회하면 primary key를 사용안해버리네요. 

그치만 어차피 조인단계에서는 0.7초밖에 안걸리니 그냥 넘어갔습니다.

 

 

by 마농 [2017.11.08 21:58:22]

@rnum 대신 limit 기능을 사용해 보세요.

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