내정보  |   고객지원

호스팅 사용법
호스팅 신청하기
도메인 연결하기
홈페이지 올리기
이메일 설정하기
서버 사용법
FTP사용법
메일사용법
텔넷/리눅스
MySQL사용법
MSSQL사용법
리눅스명령어 모음
시스템사용법
서버세팅
네트워크/보안
L4 매뉴얼
백업/미러링
호스팅용어 모음
프로그램 사용법
알리미사용법
제로보드설치방법
워드프레스설치방법
태터툴즈설치방법
그누보드설치방법
우편번호DB사용법
폼메일사용법
주문서사용법
예전 게시판/방명록
전자지불 서비스


HOME > 호스팅 > 사용안내 > MySQL사용법 > 조인
소개  기초문법  인덱스  조인  쿼리성능 
모델링  함수목록  PHP연동  DB백업  phpMyAdmin 사용법 

조인의 종류

    ① Nested Loops 조인
    Nested Loops 조인은 가장 전통적인 방법이면서도 가장 보편적으로 사용되는 조인방식이다. 이는 곧 Nested Loops 조인이 가장 중요한 조인방식임을 의미한다. Nested Loops 조인이 중요한 근본적인 이유는 먼저 액세스한 결과를 다음 액세스에 상수값을 제공하기 때문이다. 따라서 Nested Loops 조인은 완벽하게 이해를 하지 않으면 관계형 데이터베이스의 장점을 정확히 활용할 수 없으며 Join 시 부하의 원인이 된다.
- Nested Loops 조인의 작동원리 -

    Nested Loops 조인은 옆의 예제처럼 첫 번째 for의 첫 번째 값이 두 번째 for 문을 다 실행한 후 첫 번째 for문의 두 번째 값이 다음 for문을 도는 것과 같다.
  int total = 0;
  for (int i = 0; i != 100; ++i) {
     for (int j = 0; j != 100; ++j) {
        total += i + j;
     }
  }

    즉, 첫 번째 값이 Index A~Table B를 거쳐 운반단위(Array Size)에 적재되면 두 번째 값이 Index A에서 시작된다. 조인은 복수의 테이블이 하나로 합쳐지는 것이 아니라 하나의 테이블에서 조건에 맞는 특정 연결고리를 경유해 다른 테이블에 접근하기 위한 방법이다. 따라서 일반적으로 정렬을 하기 위해서 임시 테이블을 생성하는 경우는 있어도 조인을 하기 위해서 임시 테이블을 생성하지는 않는다.

    ② 아우터 조인(Outer Join)

    Null 값을 가진 행을 검색 대상에서 제외하는 것과 달리 아우터 조인은 Null 값을 가진 행도 검색 대상에 포함시킨다. MySQL의 left join이 아우터 조인에 해당된다.
  mysql > select * from a left join b on a.id = b.id;
 

조인 시 성능에 영향을 주는 요소

    ① 구동 테이블의 선택에 의한 성능 차이
    조인 시 연동되는 테이블은 데이터의 양 및 분포도가 서로 달라 구동 테이블에 따라 처리할 데이터의 양이 결정된다.
  ▶ 두 개 컬럼 모두가 같은 조건(Index가 둘 다 없거나, 둘 다 있는 경우)인 경
     우에는 from에서 가장 가까이에 정의된 테이블이 구동 테이블이 된다.
  ▶ 한쪽 컬럼에만 Index가 생성되어 있는 경우에는 from 절에 열거된 테이블의
     순서와 상관없이 Index가 없는 테이블이 구동 테이블이 된다.
  ▶ 유일 Index(Unique index)는 검색방법 중 대단히 좋은 성능을 보장해 주는
     Index 타입이기 때문에 유일 Index가 사용되는 테이블이 구동 테이블이 된다.
  ▶ 아우터 조인의 경우 비-아우터 테이블이 구동 테이블이 된다.

    ② 조인 순서에 의한 성능 차이
    여러 개의 테이블을 논리적으로 결합하는 경우 구동 테이블이 결정되고 나면 나머지 테이블들 중에 먼저 읽을 테이블과 나중에 읽을 테이블의 우선순위를 결정해야 한다. 구동 테이블이 결정되었다고 나머지 테이블들의 조인 순서를 고려하지 않는다면 성능 향상을 기대할 수 없다. 위 그림에서 Table A -> Table B -> Table C 순으로 조인을 걸면 액세스해야 하는 데이터의 양이 줄어 성능을 향상시킬 수 있다.
  pmysql-> select /*! straight_join */ *
           -> from a, b
           -> where a.id = b.id
           -> and a.name like '김%';

    ③ 테이블의 검색 양에 의한 성능 차이
    SQL문이 최적의 성능으로 실행되기 위해서는 여러 가지 조건들이 충족되어야겠지만 검색하려는 데이터를 테이블 전체 범위에서 검색한다면 성능 향상은 기대할 수 없다. 넓은 범위가 아닌 좁은 범위, 전체 테이블 스캔보다는 Index 부분 스캔으로 SQL문이 실행될 수 있도록 해야 한다.
    ④ Index의 사용 여부에 의한 성능 차이
    일반적으로 테이블에서 대한 Index를 생성한 후 SQL문을 실행하면 Index를 통해 데이터 검색이 발생한다고 생각한다. 하지만 개발자가 SQL문을 잘못 작성한다면 Index를 사용하지 못하고 테이블 전체 스캔으로 SQL문이 실행될 수 있어 좋은 성능을 기대할 수 없다.
 

조인의 연결고리

    조인이란 결국 집합을 연결고리(조인조건)를 통해 서로 연결하는 것이기 때문에 연결고리 상태가 조인에 커다란 영향을 미친다.
    ① 연결고리 정상
    조인 조건의 연결고리가 정상이라는 의미는 조건절에 기술되는 조인의 연결조건에 Index가 모두 존재하고 있는 상태를 말한다. 여기서 말하는 Index가 정상적인 상태라는 말의 정확한 의미는 연결을 시도할 때 SQL의 조건절에서 이미 주어진 상수값이나 앞서 액세스한 집합의 결과에서 제공받아 상수값이 된 것들을 이용해 대응되는 집합을 액세스할 때 Index에 문제가 없는 상태를 말한다.
    - 연결고리 정상일 경우 양방향 모두 논리적 랜덤 액세스의 총 횟수는 동일하다.
    - 1 : M 관계에서 M 쪽에 Optional로 정의 시 경우 M->1 로 갈 때 100%로 액세스 할 수 있지만 1->M으로 갈 경우 데이터가 없을 수 있어 불필요한 액세스가 발생할 수 있다.
    - 따라서 연결고리 정상의 경우 처리조건이 조인의 방향을 결정한다.
    ② 한쪽 연결고리 이상
    Index가 Table A는 없고 Table B에만 존재한다고 가정할 경우 조인방향에 따라 성능이 결정된다.
    ㉮ Table A -> Table B로 처리경로를 잡을 경우

       ㉯ Table B -> Table A로 처리경로를 잡을 경우
    Table B의 개수만큼 Table A를 전체 스캔(Full table scan)을 한다. 만약 Table B의 데이터가 100건이고 Table A가 100만 데이터가 있는 회원 테이블일 경우 Table A를 100번 전체 테이블 스캔을 한다. 따라서 이러한 연결고리 이상이 발생 시 Optimizer는 Index가 없는 Table A를 먼저 구동하여 ㉯와 같은 현상을 방지한다.
  mysql > select *
         -> from A, B
         -> where A.no = B.no
         -> and A.name like '김%';

    Table A의 no 컬럼의 데이터 타입이 int이고 Table B의 no 컬럼의 데이터 타입이 char이면 연결고리의 데이터 타입이 일치하지 않아 연결고리 이상이 발생한다.
    ③ 양쪽 연결고리 이상
    양쪽 연결고리 모두에 Index가 없다면 어느 방향으로 처리하든 연결고리 이상 상태가 되어 많은 수의 전체 테이블 스캔이 발생된다. 일반적으로 Optimizer는 연결고리의 상태에 영향을 받지 않는 소트머지(Sort merge)나 해시(Hash) 방식으로 실행계획을 수립하여 이런 문제점이 발생하는 것을 방지한다. 하지만 소트머지 및 해시를 지원하는 않는 DBMS의 경우 Nested Loops 조인을 수행한다.