항상 회고를 써야겠다는 생각을 가지고 있었지만 행동으로 옮기지는 않았었다. 스스로 회고할만한 경험이나 성장을 못했다고 생각했었기 때문이다. 돌이켜보면 아주 천천히, 조금씩은 성장하고 있었지만 그저 그런 핑계를 대며 그냥 안 썼던 것 같다. 한 해를 마무리하며 자신을 되돌아보는 시간을 가지는 건 아주 좋은 습관이라 생각한다. 좋은 습관을 내 것으로 만들기 위해 올해를 기점으로 꾸준히 회고를 써볼 생각이다. 2022년 회고에서는 내가 어떤 경험을 했고 어떤 생각을 했었는지 기록으로 남겨본다. 1. 이직 2020년 1월에 입사해서 2022년 1월까지, 총 2년간 근무했던 회사에서 퇴사하고 2022년 2월부터 새로운 회사로 출근하게 됐다. 이직 결심 신입으로 입사해서 2년 동안 일했던 회사에서 이직을 결심하게 ..
SELECT 절의 처리 순서 위 순서가 바뀌어서 실행되는 형태의 쿼리는 거의 없다. 쿼리에서 어느 절이 먼저 실행되는지 모르면 처리 내용이나 처리 결과를 예측할 수 없으므로 잘 알아두자. 다만, 실행 순서를 벗어나는 쿼리가 필요하다면 서브쿼리로 작성된 인라인 뷰를 사용하면 된다. 인라인 뷰(Inline View)란? 하나의 질의문 내에서만 생성되어 사용 되어지고 질의문 수행 종료 후에는 사라지는 뷰를 뜻한다. 일반적으로 FROM 절에서 서브쿼리를 하나의 테이블로 사용하는 형태를 말한다. 하지만 인라인 뷰가 사용되면 임시 테이블이 사용되기 때문에 주의해야 한다. WHERE 조건과 GROUP BY 절, ORDER BY 절의 인덱스 사용 인덱스를 사용하기 위한 기본 규칙 인덱스 컬럼 변형 없이 사용하기 WHE..
Extra 컬럼 실행 계획에서 성능과 관련된 중요한 내용이 Extra 컬럼에 자주 표시된다. 주로 내부적인 처리 알고리즘에 대해 깊이 있는 내용을 보여주는 경우가 많다. 이제 Extra 컬럼에 표시될 수 있는 문장을 하나씩 자세히 살펴보자. const row not found 실행 계획에서 const 접근 방법으로 테이블을 읽었지만 실제로 해당 테이블에 레코드가 1건도 존재하지 않으면 나타나는 문장이다. Deleting all rows 스토리지 엔진의 핸들러 차원에서 테이블의 모든 레코드를 삭제하는 기능을 제공하는 경우 해당 문구가 표시된다. WHERE 조건절이 없는 DELETE 문장의 실행 계획에서 자주 표시되며, 모든 레코드를 삭제하는 핸들러 API를 호출함으로써 처리됐다는 것을 의미한다. MySQL..
type 컬럼 쿼리의 실행 계획에서 type 이후의 컬럼은 테이블 레코드를 어떤 방식으로 읽었는지를 나타낸다. 일반적으로 쿼리 튜닝에서 인덱스를 효율적으로 사용하는지 확인하는 것이 중요하므로 type 컬럼은 반드시 체크해야 하는 중요한 정보다. 아래의 12개 접근 방법은 type 컬럼에 표시될 수 있는 값들 중 성능이 빠른 순서대로 나열한 것이다. system const eq_ref ref fulltext ref_or_null unique_subquery index_subquery range index_merge index ALL 마지막 ALL을 뺀 나머지는 모두 index를 사용한 접근 방법이며, index_merge를 제외한 나머지 접근 방법은 하나의 인덱스만 사용한다. 따라서 type 컬럼에도 라인..
실행 계획 분석 id 컬럼 SELECT 쿼리 별로 부여되는 식별자 값이다. 예를 들어 하나의 SELECT 문장에서 여러 개의 테이블을 조인하면 조인되는 테이블 개수만큼 실행 계획 레코드가 출력되지만 같은 id 값을 가지게 된다. 반면에 하나의 SELECT 문장에 여러 개의 단위 SELECT 쿼리가 포함되어 있는 경우 각기 다른 id 값을 가지게 된다. 한 가지 주의할 점은 실행 계획의 id 컬럼이 테이블의 접근 순서를 의미하지 않는다는 것이다. 명확한 테이블 접근 순서를 알고싶다면 TREE 형태의 포맷으로 실행 계획을 출력해 확인할 수 있다. select_type 컬럼 select_type은 단위 SELECT 쿼리가 어떤 타입의 쿼리인지 표시되는 컬럼이다. 해당 컬럼에 표시될 수 있는 값은 다음과 같다...
사용자의 쿼리를 최적으로 처리될 수 있게 하려면 쿼리의 실행 계획을 수립할 수 있어야 한다. 이에 가장 큰 영향을 미치는 정보는 바로 통계 정보다. 통계 정보 MySQL 5.7 버전까지 테이블과 인덱스에 대한 개략적인 정보를 가지고 실행 계획을 수립했다. 하지만 테이블 컬럼의 값들이 어떻게 분포돼 있는지에 대한 정보가 없기 때문에 실행 계획의 정확도가 떨어지는 경우가 많았다. 이러한 문제를 해결하기 위해 MySQL8.0부터는 데이터 분포도를 수집해 저장하는 히스토그램 정보가 도입됐다. 테이블 및 인덱스 통계 정보 비용 기반 최적화에서 가장 중요한 것은 통계 정보다. 통계 정보가 정확하지 않다면 엉뚱한 방향으로 쿼리를 실행할 수 있기 때문이다. 예를 들어, 1억 건의 레코드가 저장된 테이블의 통계 정보가 ..
트랜잭션이란? 트랜잭션은 어떤 작업의 완전성을 보장해주는 것을 의미한다. 논리적인 작업 단위를 완벽하게 처리하거나 모두 취소하여 작업의 일부만 적용되는 현상을 방지하는 기술이다. 즉, 데이터의 정합성을 보장하기 위한 기능이라고 볼 수 있다. 트랜잭션의 가장 쉬운 예로 계좌 송금 시스템을 떠올릴 수 있다. 계좌 송금 시스템의 논리적인 작업 단위는 다음과 같다. A가 B에게 계좌 송금 신청 A가 송금 가능한 상태인지 확인(신청한 송금 금액이 계좌에 들어있는지) A가 신청한 금액만큼 A의 계좌 금액 차감 B에게 금액 송금 B의 계좌에 송금된 금액이 가산 이러한 논리적 작업을 수행하는 도중 4번 과정에서(B에게 금액을 송금) 장애가 발생한다면 어떻게 될까? 당연히 송금은 취소되고 A의 계좌에서 차감됐던 금액도 ..
MySQL의 버전이 업그레이드되면서 옵티마이저의 쿼리 실행 계획 최적화 방법도 다양해지고 있다. 하지만 옵티마이저가 개발자나 DBA의 요구 조건을 100% 예측할 수는 없다. 따라서 옵티마이저가 부족한 실행 계획을 수립한 경우에는 우리가 옵티마이저에게 어떻게 실행계획을 수립해야 할지 알려줄 수 있는 방법이 필요하다. MySQL에서 사용 가능한 쿼리 힌트는 다음과 같이 2가지로 구분할 수 있다. 인덱스 힌트 옵티마이저 힌트 인덱스 힌트 인덱스 힌트는 예전 버전의 MySQL 서버에서 사용되어 오던 STRAIGHT_JOIN과 USE INDEX 같은 힌트를 의미한다. 이 기능들은 각 SQL문법에 영향을 받기 때문에 ANSI-SQL 표준 문법을 준수하지 못하며, 가능하면 MySQL 5.6 버전에 도입된 옵티마이저..
GROUP BY 처리 GROUP BY도 ORDER BY처럼 스트리밍된 처리를 할 수 없는 작업 중 하나다. GROUP BY 절에는 그루핑 결과에 필터링 역할을 수행하는 HAVING 절을 사용할 수 있는데, GROUP BY에 사용된 조건은 인덱스를 사용해 처리될 수 없어 HAVING 절을 튜닝하려고 인덱스를 생성하거나 다른 방법을 고민할 필요는 없다. GROUP BY 작업은 인덱스를 사용하는 경우와 그렇지 못한 경우로 나눌 수 있다. 인덱스를 이용하는 경우 인덱스를 차례대로 읽는 타이트 인덱스 스캔 인덱스를 건너뛰면서 읽는 루스 인덱스 스캔 인덱스를 사용하지 못하는 경우 임시 테이블 사용 인덱스 스캔을 이용하는 GROUP BY(타이트 인덱스 스캔) 드라이빙 테이블에 속한 컬럼만 이용해 그루핑할 때 이미 인..