테이블 컬럼의 각 데이터 타입을 결정할 때는 아래의 사항을 유의해야 한다. 저장되는 값의 성격에 맞는 최적의 타입을 선정 가변 길이 컬럼은 최적의 길이를 지정 조인 조건으로 사용되는 컬럼은 똑같은 데이터 타입으로 선정 컬럼의 데이터 타입을 결정할 때 실제 저장되는 값의 특성을 고려하기 보다는 저장되는 값의 최대 길이를 기준으로 컬럼의 길이를 선택하는 것이 일반적이다. 하지만 컬럼의 크기가 너무 무분별하게 커진다면 디스크 공간을 많이 차지할 것이고 해당 컬럼이 인덱스라면 검색 효율도 떨어질 것이다. ☁️ ENUM 과 SET ENUM 과 SET을 사용하면 문자열 값을 내부적인 작엽을 통해 숫자 값으로 매핑하여 관리한다. 레코드의 타입이나 상태와 같은 코드 형태의 컬럼(ex. 상품 유형 코드 E(전자), A(..
Database/Real MySQL
테이블 컬럼의 각 데이터 타입을 결정할 때는 아래의 사항을 유의해야 한다. 저장되는 값의 성격에 맞는 최적의 타입을 선정 가변 길이 컬럼은 최적의 길이를 지정 조인 조건으로 사용되는 컬럼은 똑같은 데이터 타입으로 선정 컬럼의 데이터 타입을 결정할 때 실제 저장되는 값의 특성을 고려하기 보다는 저장되는 값의 최대 길이를 기준으로 컬럼의 길이를 선택하는 것이 일반적이다. 하지만 컬럼의 크기가 너무 무분별하게 커진다면 디스크 공간을 많이 차지할 것이고 해당 컬럼이 인덱스라면 검색 효율도 떨어질 것이다. ☁️ 문자열 (CHAR, VARCHAR) 두 타입 모두 문자열을 저장한다는 공통점을 가진다. CHAR 타입은 고정길이이며, VARCHAR 타입은 가변길이로 관리된다. CHAR(1), VARCHAR(1) 은 모두..
☁️ 파티션 파티션 기능은 논리적인 하나의 테이블을 물리적으로 여러 개의 테이블로 분리해서 관리하는 기능이다. 주로 대용량의 테이블을 물리적으로 여러 개의 소규모 테이블로 분산하는 목적으로 사용한다. 또한 파티션을 분리하면 필요한 파티션에만 접근할 수 있다는 장점을 취할 수 있다. 대용량 테이블을 분산하여 저장한다면 조회 쿼리의 성능이 좋아지게 된다. 하지만 잘못된 쿼리를 사용하는 경우 오히려 쿼리의 성능이 나빠질 수 있다. 파티션 사용 시 유의해야 할 사항을 알아보자. 파티션을 사용하는 이유 테이블의 데이터가 많다고 해서 무조건 파티션을 적용하는 것은 옳지 않다. 테이블의 크기가 커져 인덱스가 메모리보다 커지는 경우 혹은 데이터 특성상 주기적인 삭제작업이 필요한 경우 등에 파티션을 사용하면 좋다. 인덱..
💡 해당 포스팅은 참고용으로 MySQL 사용 편리성을 위해 쿼리나 명령어, Real MySQL의 쿼리 사용 팁들을 단순 정리한다. ☁️ INSERT 온라인 트랜잭션 서비스에서 INSERT 문장은 대부분 1건 또는 소량의 레코드를 추가하기에 성능에 대해 고려할 부분이 많지 않다. 한 번의 많은 INSERT 문이 실행되는 경우 쿼리 문장 보다는 테이블 구조가 성능에 영향을 미치는 경우가 대다수이다. 하지만 많은 경우 INSERT의 성능과 SELECT의 성능을 동시에 빠르게 만들 수 있는 테이블 구조는 없다. 그래서 INSERT와 SELECT 성능을 어느 정도 타협하면서 테이블 구조를 설계해야 한다 - 중에서 유용한 기능 INSERT IGNORE: INSERT 실행 시 테이블의 유니크 한 컬럼의 값이 중복되는..
인덱스 레인지 스캔은 인덱스를 탐색하는(Index Seek) 단계와 인덱스를 스캔하는(Index Scan) 과정으로 구분할 수 있다. 탐색 단계는 B-Tree를 통해 특정 인덱스 혹은 범위를 탐색하는 작업이고, 스캔 단계는 리프노드를 순차적으로 읽는 작업이다. 일반적으로 인덱스를 통해 가져오는 레코드는 소량이다. 따라서 스캔 작업 보다는 탐색 작업이 상대적으로 부하가 크다. ☁️ 드라이빙 테이블과 드리븐 테이블 두 개 이상의 테이블을 JOIN하는 과정에서 드라이빙 테이블과 드리븐 테이블이 구분된다. 보통 드라이빙 테이블을 읽을 때는 인덱스 탐색 작업을 한 번만 수행한 뒤 스캔작업만 수행하면 되지만 드리븐 테이블은 탐색과 스캔 작업을 드라이빙 테이블에서 읽은 레코드 수만큼 진행한다.따라서 드라이빙 테이블과..
☁️ 인덱스 사용의 기본적인 유의사항 기본적으로 인덱스를 사용하려면 인덱스된 컬럼의 값(인덱스 키값) 자체를 변환하지 않고 사용해야 한다. 해당 조건은 타입이 동일해야 한다는 조건을 포함한다. 자동 타입 변경으로 인해 인덱스를 사용하지 못하는 경우도 유의해야 한다. 예를 들어 아래와 같은 쿼리는 인덱스를 사용하지 못한다. -- employees.salary가 단일 컬럼 인덱스로 선언되었다고 가정 SELECT * FROM employees WHERE salary*10=12000; -- 아래 처럼 변경하면 인덱스를 사용할 수 있다. SELECT * FROM employees WHERE salary=12000/10; 만약 특정 컬럼을 변환한 값에 의한 검색이 빈번하게 발생하는 경우 가상 컬럼을 통해 인덱스를 ..
쿼리 튜닝을 진행하며 얻은 팁과 정리를 계속해서 추가할 예정이다. 실행 계획 정리 | Notion 쿼리 튜닝을 진행하며 얻은 팁과 정리를 계속해서 추가할 예정이다. hyunsb.notion.site 참고하면 좋은 글 [SQL튜닝] MySQL 쿼리 튜닝, 쿼리 실행계획, Explain 실행계획을 분석해서 SQL 성능튜닝을 해보자(feat.MySQL)
☁️ 클러스터링 인덱스 데이터베이스를 조회할 때, 주로 비슷한 값을 통시에 조회하는 경우가 많다고 한다. 이를 착안하여 비슷한 값(보통 프라이머리 키 기준)으로 묶어서 저장하는 것을 클러스터링 인덱스라고 한다. 클러스터링 인덱스는 다른 세컨더리 인덱스와는 다르게 인덱스의 값으로 레코드의 물리적인 주소를 가지고 있다. 레코드는 클러스터링 키 값에 의해 저장위치가 결정되며, 특정 레코드의 클러스터링 키의 데이터가 변경된다면 해당 레코드의 물리적인 위치까지 변경되는 코스트 높은 작업이 수행될 것이다. 이처럼 InnoDB에서 레코드는 클러스터링 인덱스에 상당히 의존적이기에 프라이머리 키를 신중하게 결정해야 한다. InnoDB에서는 각 테이블에 클러스터링 인덱스가 무조건 생성된다. 클러스터링 인덱스는 키 값으로 ..
☁️ 인덱스 (index) 인덱스는 책의 맨 끝에 있는 찾아보기라고 많이 설명된다. 특정 데이터를 이 찾아보기(인덱스)를 통해 데이터의 주소로 바로 이동할 수 것이다. 인덱스는 인덱스의 칼럼과 해당 레코드가 저장된 주소를 키와 값 쌍으로 찾아보기 쉽게 정렬하여 저장한다. (InnoDB는 레코드 주소가 아닌 PK를 주소처럼 사용) select 문장의 경우 인덱스를 통해 특정 레코드를 검색하는 것이 인덱스 없이 전체 테이블에서 레코드를 검색하는 방식보다 훨씬 빠를 것이다. 하지만 insert, update, delete 문장은 어떨까? 인덱스는 정렬되어 저장된다고 앞서 말했다. 레코드의 변경이 생기는 insert, update, delete 문장에 의해 인덱스와 연관이 있는 레코드에 변경이 생기는 경우 인덱..