database.sarang.net
UserID
Passwd
Database
DBMS
ㆍMySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
MySQL Q&A 30167 게시물 읽기
No. 30167
order by로 인한 속도문제입니다. 방법이 없을까요 ㅜㅜ
작성자
최진규(cjg1012)
작성일
2011-12-12 22:37ⓒ
2011-12-13 00:27ⓜ
조회수
10,882

 먼저 쿼리문을 보시면요..

 

SELECT 
    A.EMAIL, A.NICK_NAME, A.BIRTH_DATE, A.JENDER, A.INTRODUCE, 
    IFNULL(A.INTEREST_SCORE, 0) AS INTEREST_SCORE,
    ROUND( 6371 * ACOS( COS( RADIANS(37.62709565) ) * COS( RADIANS( A.LATITUDE ) ) * COS( RADIANS( A.LONGITUDE ) - RADIANS(127.0335156) ) + SIN( RADIANS(37.62709565) ) * SIN( RADIANS( A.LATITUDE ) ) ), 1) AS DISTANCE
    '' AS IMG,
     A.MAIN_PROFILE_FILE AS URL, (YEAR(CURDATE())-YEAR(DATE_FORMAT(A.BIRTH_DATE, '%Y%m%d')))+1 AS AGE
  FROM MT_MEMBER A
WHERE A.LATITUDE <> 0
  AND A.REPORT_COUNT < 4
  AND A.JENDER = 'M'
  AND A.BIRTH_DATE BETWEEN '19210101' AND '20111231'
  AND A.MAIN_PROFILE_FILE IS NOT NULL
  AND A.C2DM_POSSIBLE = 'Y'
  AND A.EMAIL NOT IN (SELECT BLOCK_EMAIL FROM MT_BLOCK_MEMBER D WHERE EMAIL = 'jin@jingyu.kr')
  AND A.EMAIL NOT IN (SELECT EMAIL FROM MT_BLOCK_MEMBER E WHERE BLOCK_EMAIL = 'jin@jingyu.kr')
  AND A.LAST_CONN_DATE > DATE_ADD( CURDATE(), INTERVAL -3 DAY )
  AND ROUND( 6371 * ACOS( COS( RADIANS(37.62709565) ) * COS( RADIANS( A.LATITUDE ) ) *
      COS( RADIANS( A.LONGITUDE ) - RADIANS(127.0335156) ) + SIN( RADIANS(37.62709565) ) *
      SIN( RADIANS( A.LATITUDE ) ) ), 1) >= CONVERT('0', UNSIGNED)
  AND ROUND( 6371 * ACOS( COS( RADIANS(37.62709565) ) * COS( RADIANS( A.LATITUDE ) ) *
      COS( RADIANS( A.LONGITUDE ) - RADIANS(127.0335156) ) + SIN( RADIANS(37.62709565) ) *
      SIN( RADIANS( A.LATITUDE ) ) ), 1) <= CONVERT('99999999', UNSIGNED)
ORDER BY DISTANCE
LIMIT 0 , 200;
 
보시면 그냥 단일테이블에서 조회 쿼리입니다. 서브쿼리도 들어갔지만 order by 만 빼면 전현 문제될게 없더군요..
그런데 문제는 조회요청자의 위도와경도를 가지고 거리를 구한다음에 거리순으로 보여야 하는데 문제가 있습니다.
기존에는 데이터가 적어 문제없었습니다. 15만이 넘으니 사용자 접속량에 따라  2~10+초가 걸리는군요..
이것저것 빼고 해보니 문제는 ORDER BY DISTANCE 구문이 문제입니다.
email이 키인데 order by email 하면 순식간입니다.
distance는 조회시 만들어진 alias칼럼이라 KEY가 아니니 느린건 당연한데 방법이 없을까요..ㅜㅜ 
참고로 innodb 입니다.
 
아래는 explain 결과 입니다.
 
 id  select_type         table  type             possible_keys                          key             key_len  ref         rows   Extra                        
1   PRIMARY             A      ref              PRIMARY,idx3_mt_member,idx1_mt_member  idx3_mt_member  1        const       62991  Using where; Using filesort  
3   DEPENDENT SUBQUERY  E      unique_subquery  PRIMARY                                PRIMARY         604      func,const  1      Using index; Using where     
2   DEPENDENT SUBQUERY  D      eq_ref           PRIMARY                                PRIMARY         604      const,func  1      Using where; Using index     
 

 

이 글에 대한 댓글이 총 5건 있습니다.

ORDER BY EMAIL인 경우와 ORDER BY DISTANCE인 경우 모두 동일한 실행 계획을 갖게 되는지가 우선 궁금합니다.

특히 LIMIT 없이 ORDER BY EMAIL과 ORDER BY DISTANCE의 수행 시간 차이도 궁금합니다.

혹시 DISTANCE 계산을 하면서 오래 걸리게 되는 것은 아닐까하는 의심이 들어서요.

우욱님이 2011-12-13 03:47에 작성한 댓글입니다. Edit

 저도 거리계산하면서 늦어지는줄 알았는데..아니예요..

계산공식 넣고 order by email 하면 0.05초 나옵니다.

계산공식 빼고 order by email해도 0.05초 정도 나오고요..

확실히 order by distance 가 문제 같습니다.

그래서 좀 고민해봤는데..

limit랑 order by 가 없으면 0.01~0.05정도 나오니..

순간적으로 tmp테이블(distance를 인덱스로 만들고)을 만들어 

insert into tmp

select ..위 쿼리 한다음에

tmp에서 order by distance 한다음에 가져오면 괜찮을까 하고 생각을 해봤는데..

한번요청에 tmp테이블 create하고 index만들고 insert하고 최종적으로 조회하는 단계인데

괜찮을까요?? 아님 더 좋은 방법이 없을까요?? ㅜㅜ

최진규(cjg1012)님이 2011-12-13 10:58에 작성한 댓글입니다.

 DISTANCE 를 구하는 것 자체가 각종 수학 함수를 활용하고 있으므로, 해당 부분을 간략화하는 것이 관건인것 같습니다.

 

무엇보다, 정확한 거리를 구하는 것이 목표가 아니라, 거리순으로 정렬만 하면 되는 것이므로, 대략적인 값으로 정렬하신 후에, 어플리케이션 레벨에서 정밀하게 측정해 재정렬하시거나, 서브쿼리를 사용해서 정확한 DISTANCE를 구한 후, 다시 정렬해주시면 될 것 같습니다.

 

단순히 위경도 차이의 절대값의 합으로 정렬하셔도 후보군을 구하는 데는 지장이 없을 것으로 보입니다. (추출하는 후보를 조금 더 뽑으면 되니까요 )

 

( 또한, WHERE 구문 마지막에 두 구문은, 전체 결과를 구한 다음에 서브 쿼리로 따로 빼시는 것이 좋겠습니다. )

박현우(lqez)님이 2011-12-16 00:55에 작성한 댓글입니다.
이 댓글은 2011-12-16 00:57에 마지막으로 수정되었습니다.

 ORDER BY email 이면 email이 키라고 하셨으므로 DB 입장에서는
email 순으로 진행하면서 where 조건에 맞는 애들 200개 뽑아서 계산을 하므로 200번만 계산하면 되는데,
ORDER BY distance라면 where 조건에 맞는 애들 다 뽑아서 아마 jender 등의 조건이 있는 것으로 보아 대략 전체의 30%정도 잡으면 5만번 계산을 하느라 늦는 것으로 생각되는데 질문하신 분은 반드시 "order by "가 문제라고 하시니 손 쓸 방법은 없어보입니다만...

우욱님이 2011-12-16 09:35에 작성한 댓글입니다.
이 댓글은 2011-12-16 09:35에 마지막으로 수정되었습니다. Edit

 

 

이건 느릴수밖에 없죠.. 위에서 where 조건에 맞는 건수가

 

10만건이면 10만건을 DISTANCE 에서 계산 하고 그중에

 

200건을 order by 해오는거랑

 

email 을 인덱스 이용해서 바로 200건 갖고와서 200건만 DITANCE 를 처리 하는거랑

 

속도 차이가 날수밖에 없죠..

 

지금같은 경우는 어플리 케이션 에서 이런 쿼리가 안돌게 수정 하시는방법 밖에 없을거 같네요..

 

아니면 sort 버퍼 사이즈 증가 tmp 증가 같은 튜닝도 해보시고 성능 테스트 해보세여~

민족님이 2011-12-21 09:52에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
30172[초보질문]mysql to oracle10g 데이터이관질문..ㅠㅠ [1]
나진산
2011-12-20
7498
30171박명회(park4019)님 보세요 [2]
강삼수
2011-12-19
7702
30170mysql.sock 파일좀 찾아주세요.. [10]
강삼수
2011-12-15
10346
30167order by로 인한 속도문제입니다. 방법이 없을까요 ㅜㅜ [5]
최진규
2011-12-12
10882
30165sqlstate=22018 에러발생좀 봐주세요^^ [1]
임종선
2011-12-11
12601
30164ms sql 데이터를 mysql 이관 시키려고 합니다..차근차근 설명좀 해주세요~ [4]
박순채
2011-12-11
14853
30163TDX for MYSQL에 관하여 [1]
정원백
2011-12-06
8396
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.020초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다