TIL

2021.09.23 기록장

Gisungcu 2021. 9. 23. 20:50

ToDo

  • 알고리즘 문제 풀기
  • 책 읽기
  •  

Done

  • 책 읽기

Weekly goal

  • 책 읽기

 

real mysql

 

285p.

innoDB에서의 풀 테이블 스캔은 디스크로부터 페이지를 하나씩 읽어오지 않는다. 이거는 myISAM에서 그러는 것이다.

innoDB에서는 특정 테이블의 연속된 데이터 페이지가 읽히면 백그라운드 스레드에 의해 리드 어헤드 작업이 일어난다.

 

리드 어헤드 : 어떤 영역의 데이터가 앞으로 필요해지리라는 것을 예측해서 미리 디스크에서 읽어 버퍼 풀에 가져다 두는 것.

 

즉 처음에는 포그라운드 스레드가 읽어오다가 나중에는 백그라운드 스레드가 읽어온다.

 

리드 어헤드는 풀 인덱스 스캔에서도 동일하게 작동한다.

 

289p.

mysql은 정렬을 위해 소트 버퍼라는 것을 사용한다.

이는 메모리의 일부 공간을 정렬을 위해 사용하는 것이다. 근데 소트 버퍼 보다 큰 데이터를 정렬해야 한다면?

이때는 디스크를 이용한다. 정렬은 소트 버퍼에서 하고 디스크에 임시로 저장해 둔다.

계속해서 디스크에 왔다 갔다 하면서 정렬해야 하는 양을 끝마친다. 이는 계속 IO 작업을 하는 것이며 이는 성능에 영향을 미친다.

 

294p.

정렬 방법에는 2가지가 있다. 소트 버퍼에 정렬에 사용될 칼럼만 불러올 투 패스 방법과 정렬에 사용되지는 않지만 select 해야 하는 애까지 소트 버퍼에 끌고 와서 정렬하는 싱글 패스 방식이다.

전자는 정렬 기준으로 소트 버퍼에서 정렬을 하고 다시 디스크로 가서 정렬된 기준으로 읽어서 클라이언트에게 반환한다. 후자는 데이터를 다 끌고 와서 정렬하고 바로 클라이언트에게 반환한다.

 

최신 db들은 싱글 패스를 사용하지만 꼭 투 패스를 사용하지 않는 것은 아니다.

예로

1. 레코드의 크기가 시스템 변수에 선언된 sort_data보다 큰 경우

2. BLOB이나 text 타입의 칼럼이 select 대상일 경우는 

투 패스를 사용한다.

 

 

*select시 *가 안 좋은 이유*

이는 정렬 버퍼를 몇 배나 비효율 적으로 쓰는 것이다. 

mysql은 대부분 싱글 패스 방식, 즉 모든 select 할 것을 소트 버퍼에 올려서 정렬하고 클라이언트에게 반환하는데

이때 불필요한 정보도 같이 올려 버리는 것이다.

 

296p.

여태 소트 버퍼를 사용해서 어떤 방식으로 정렬을 수행하는지 알았다면 

이제 정렬을 어떻게 하는지 더 깊게 보겠다.

1. 인덱스가 있다면 인덱스를 이용해서 정렬을 수행한다.

2. 조인에서 드라이빙 테이블만 정렬

3. 조인에서 조인 결과를 임시 테이블로 저장 후 정렬

 

1. 인덱스를 이용한 정렬.

이때는 조인 시나 where 절에서 처음 만나는 테이블의 칼럼에 대한 조건이 있다면 그 조건과 order by는 동일한 인덱스를 타야 한다.

인덱스를 통한 정렬은 따로 정렬을 수행하지 않는다. 이유는 

이미 인덱스는 정렬되어 있기 때문이다. 그렇다고 order by를 빼지는 말자. 나중에 예기치 못한 버그로 이어질 수 있다.

 

2. 조인에서 드라이빙 테이블만 정렬

조인을 하면 레코드는 수배로 불어난다. 그래서 조인하기 전에 미리 정렬을 수행하고 조인하는 것이다.

이를 위해서 드라이빙 테이블만을 이용해 order by 해야 한다.

 

3. 임시 테이블을 사용하여 정렬

이는 가장 느린 정렬방법으로 조인 시에 드라이빙 테이블이 아닌 반대편의 테이블의 칼럼을 이용해 정렬할 경우 발생한다.

 

이를 통해 정렬 시 인덱스를 우선적으로 이용하고 다른 칼럼을 이용해야 한다면 드라이빙 테이블이 누가 될 것인지를 

알고 명확하게 설정하는 것이 좋다.

 

 

300p.

정렬 처리 방법의 성능 비교

order by나 group by시에 limit를 걸어도 성능의 이점을 보지 못한다.

왜냐하면 데이터를 읽는 방식 때문이다.

기본적으로 위의 둘이 없는 방식은 스트리밍 방식이라고 부른다.

이는 디스크에서 읽자마자 바로 클라이언트에게 데이터를 전달하는 것이다. 

그래서 클라이언트가 데이터를 처음 받을 때 sql은 아직도 실행 중인 것이다.

그래서 이때 limit를 걸면 조금만 읽어서 내보낼 수 있으니 성능의 이점이 있다.

 

하지만 order by나 group by는 정렬을 해야 한다. 이를 위해서는 스토리지 엔진에서 읽어와서 소트 버퍼에 올리고 정렬을 해야 한다. 그래서 이미 다 올렸는데 limit 걸어봤자 성능의 이점이 없는 것이다. 이를 버퍼링 방식이라고 한다.

 

 

튜닝 방법. 

인덱스를 사용한 정렬이 좋고, 그렇지 못하다면 최소한 드라이빙 테이블로 정렬을 수행하자.