Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chapter 8.5 ~ 9.2 #5

Open
Tianea2160 opened this issue Oct 25, 2022 · 4 comments
Open

chapter 8.5 ~ 9.2 #5

Tianea2160 opened this issue Oct 25, 2022 · 4 comments

Comments

@Tianea2160
Copy link
Member

No description provided.

@Raemerrr
Copy link
Collaborator

MySQL 옵티마이저가 풀 테이블 스캔을 하는 경우는?
  • 테이블의 레코드 건수가 너무 작아서 인덱스를 통해 읽는 것보다 풀 테이블 스캔을 하는 편이 더 빠른 경우

    일반적으로 테이블이 페이지 1개로 구성된 경우

  • WHERE 절이나 ON 절에 인덱스를 이용할 수 있는 적절한 조건이 없는 경우
  • 인덱스 레인지 스캔을 사용할 수 있는 쿼리라고 하더라도 옵티마이저가 판단한 조건 일치 레코드 건수가 너무 많은 경우

    인덱스의 B-Tree를 샘플링해서 조사한 통계 정보 기준

아래의 쿼리는 항상 풀 테이블 스캔을 하는가?
mysql> SELECT COUNT(*) FROM employees; 

X

해당 쿼리는 아무런 조건 없이 employees 테이블의 레코드 건수를 조회하고 있으므로 당연히 풀 테이블 스캔을 할 것처럼 보인다.
하지만 실제 실행 계획은 풀 테이블 스캔보다는 풀 인덱스 스캔을 하게 될 가능성이 높다.

아래 DISTINCT 쿼리의 경우 first_name 컬럼만 유니크한 레코드를 조회하는가?
mysql> SELECT DISTINCT first_name, last_name FROM employees;

X

해당 쿼리는 (first_name, last_name) 조합 전체가 유니크한 레코드를 조회한다.

@doxxx93
Copy link
Member

doxxx93 commented Nov 11, 2022

싱글 패스와 투 패스의 비교
  • 싱글 패스: 소트 버퍼에 정렬 기준을 포함한 SELECT 대상이 되는 칼럼 전부를 담아서 정렬
  • 투 패스: 정렬 대상 칼럼과 프라이머리 키 값만 소트 버퍼에 담아서 정렬을 수행하고 정렬된 순서대로 다시 프라이머리 키로 테이블을 읽어서 SELECT할 컬럼을 가져온다.

싱글 패스의 경우 한 번의 쿼리만으로 결과를 확인할 수 있지만, 소트 버퍼의 크기가 더 필요하다.
투 패스 방식의 경우 테이블을 두번 읽어야 한다.

정렬할 땐 불필요한 칼럼을 SELECT 하지 않도록 한다.


풀 테이블 스캔과 리드 어헤드
  • 풀 테이블 스캔의 경우 디스크 I/O를 자주 하게 된다.

  • 이에 따른 MySQL - InnoDB에서의 해결 방안 : 리드 어헤드

    • InnoDB의 경우에 연속된 데이터 페이지가 읽히면 백그라운드 스레드에 의해 리드 어헤드 작업이 자동 실행된다.
    • 리드 어헤드 : 어떤 영역의 데이터가 앞으로 필요해지리라는 것을 예측해서 요청이 오기 전에 미리 디스크에서 읽어 InnoDB의 버퍼 풀에 가져다 두는 것

풀 테이블 스캔이 실행되면 처음 몇 개의 데이터 페이지는 포그라운드 스레드가 페이지 읽기를 실행하지만 특정 시점부터는 읽기 작업을 백그라운드 스레드로 넘겨 미리 디스크를 읽어 InnoDB 버퍼 풀에 가져다 둔다.

이렇게 되면 포그라운드 스레드는 미리 버퍼 풀에 준비된 데이터를 가져다 사용하기만 하면 되므로 쿼리가 빨리 처리되는 것!

→ 리드 어헤드는 풀 인덱스 스캔에서도 동일하게 사용되는데, 인덱스가 2~3개의 컬럼만으로 구성되기 때문에 테이블 자체보다는 용량이 작아서 훨씬 빠른 처리가 가능한 것임


드라이브 테이블과 드리븐 테이블

조인을 실행할 때 테이블의 순서는 쿼리의 성능에 매우 큰 영향을 미친다.
MySQL 옵티마이저는 여러 테이블이 조인되는 경우 가능하다면 일치하는 레코드 건수가 적은 순서대로 조인을 실행한다.


DISTINCT 처리
  • SELECT DISTINCT - SQLD에서도 나옴
  • GROUP BY랑 사실상 동일하다. 조합이 유니크한 결과를 가져온다.
  • 집합 함수와 함께 사용된 DISTINCT

@Tianea2160
Copy link
Member Author

Q. 함수기반 인덱스를 사용할 때에는 테이블을 생성할 때 사용한 표현식이 아니여도 함수 결과만 인덱스와 같다면 인덱스 스캔을 진행한다.(O, X)
Q. 인덱스 풀 스캔보다 테이블 풀스캔을 하는 것이 좋다고 옵티마이저가 결정짓는 기준을 설명하시오.
Q. unique 인덱스 스캔과 일반 인덱스 스캔의 차이점을 db에서 정보는 조회하는 입장에서 설명하시오

https://tianea.notion.site/MySQL-4-25adfc85591943748d05ee98ed71e083

@jojiapp
Copy link
Collaborator

jojiapp commented Nov 11, 2022

  • 프라이머리 키 auto-increment vs 테이블 대표 컬럼?
    검색이 상당히 자주 되기 때문에 업무적으로 해당 레코드를 대표할 수 있다면 그 컬럼을 프라이머리 키로 설정하는것이 좋음

  • 유니크 인덱스 vs 일반 세컨더리 인덱스 성능
    유니크 인덱스는 읽어야할 레코드가 1개면 끝이지만, 일반 세컨더리 인덱스는 더 많기 때문에 많이 소요
    하지만 인덱스 자체 성능은 동일하며 단지 읽어야할 레코드의 수에 따라 다른것이기 때문에 세컨더리 인덱스가 더 느리다고 표현하기에는 무리가 있음

  • 외래키를 잘 사용하지 않는 이유?
    자식 테이블의 레코드를 삭제 하지 않으면 부모 테이블의 레코드가 삭제되지 않는데, 이렇게 많은 외래키가 엮여있다면 엮여있는 모든 레코드가 락이 걸리게 되어 성능에 매우 안좋음

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants