Database/SQL 42

MySQL - WHERE 절에서의 인덱스 사용 (+인덱스를 사용하지 않는 쿼리)

Index In Where clause SQL문 튜닝에 있어서 Where절은 중요합니다. SQL문은 Where절이 가장 먼저 실행되고 Where절을 어떻게 설계하냐에 따라 Index를 활용한 조회를 하지 않고, 무식한 Full Scan을 할 수도 있기 때문입니다. 개발자 분들이 흔히 놓칠 수 있는 인덱스를 안타는 Where절 예시와 튜닝에 대해 포스팅했습니다. LIKE '%_ ' 또는 LIKE '%_%' 문자열을 검색할 때 LIKE절을 많이 사용합니다. 그런데 인덱스를 타고 있지 않을 수도 있습니다. EXPLAIN SELECT * FROM employees WHERE first_name LIKE "David%" 이 경우에는 인덱스를 잘탑니다. 하지만 아래의 경우들에는 인덱스를 잘 타지 않습니다. EXPL..

Database/SQL 2022.03.20

MySQL - 쿼리 성능(실행 시간, CPU 사용량 등) 확인하는 방법 [Profiling]

MySQL Profiling MySQL에서 실행한 쿼리들이 각 수행 시간이 얼마가 걸렸는지 확인할 수 있는 기능으로 쿼리 프로파일링(Query Profiling)을 제공합니다. profiling 설정을 활성화하면 앞으로 실행되는 모든 쿼리문의 수행 시간을 기록합니다. profiling 속성은 적지 않은 부하를 생성하기 때문에, 기본값으로는 OFF로 되어있습니다. Profiling 옵션 확인 Profiling 옵션의 활성화 여부는 다음과 같이 확인합니다. SELECT @@profiling; 결과 값이 1이면 ON, 0이면 OFF 입니다. 활성화 쿼리 프로파일링을 다음과 같이 활성화합니다. SET profiling=1; 그리고 다시 SELECT @@profiling;으로 조회를 해보면 아래와 같이 활성화가 ..

Database/SQL 2022.03.20

SQL 튜닝 - SELECT 절과 WHERE 절에 동일한 함수가 사용될 때 [성능 비교]

1번? 여러번? SELECT 절에 있는 함수를 WHERE 절에도 사용하면서 그런 생각이 문득 들었습니다. "설마, 함수를 두 번 호출해서 계산하는건 아니겠지..? 그럼 낭비잖아!" SELECT emp_no, CONCAT(first_name, ' ', last_name) AS full_name FROM employees WHERE CONCAT(first_name, ' ', last_name) LIKE '%Robert%'; 찾아본 결과, 쿼리를 날리면 Oracle은 라이브러리 캐시, MySQL은 쿼리 캐시에 쿼리 결과를 캐싱해서 재사용한다고 합니다. (소프트 파싱) -> 하지만, 라이브러리 캐시, 쿼리 캐시는 1개의 완성된 쿼리 단위로 동작합니다. 즉, WHERE절에서 나온 결과를 SELECT절에서 재사용하..

Database/SQL 2022.03.17

MySQL - datetime("0000-00-00") 사용하면 안되는 이유! (+ 에러 임시 해결)

"0000-00-00 00:00:00" error? 이번 주 회사에서 예약 서비스를 개발하다가 발생한 문제입니다. 회사에서 mysql의 datatimes값으로 0000-00-00 00:00:00 등의 format을 많이 사용하고 있었습니다. 그런데 문제가 발생해서 이런 값 사용은 절대 지양했으면 좋겠다고 생각하게 되었는데, 이유를 말씀해드릴게요! 1. DB Error: Incorrect datetime value MySQL 8.0의 sql_mode은 기본값으로 아래 세팅들을 포함하고 있습니다. ONLY_FULL_GROUP_BY STRICT_TRANS_TABLES NO_ZERO_IN_DATE NO_ZERO_DATE ERROR_FOR_DIVISION_BY_ZERO NO_ENGINE_SUBSITUTION 저기..

Database/SQL 2022.02.20

SQL - 트랜잭션 범위 개선

트랜잭션 트랜잭션은 최소의 단위로 설정하는 것이 중요합니다. 아래 예제는 사용자가 게시판에 게시물을 작성한 후 저장 버튼을 클릭했을 때 서버의 동작을 순서대로 정리한 것입니다. 1) 처리 시작 => 데이터베이스 커넥션 생성 => 트랜잭션 시작 2) 사용자의 로그인 여부 확인 3) 사용자의 글쓰기 내용의 오류 여부 확인 4) 첨부로 업로드된 파일의 확인 및 저장 5) 사용자의 입력 내용을 DBMS에 저장 6) 첨부 파일 정보를 DBMS에 저장 7) 저장된 내용 또는 기타 정보를 DBMS에서 조회 8) 게시물 등록에 대한 알림 메일 전송 9) 알림 메일 발송 이력을 DBMS에 저장 => 트랜잭션 종료(COMMIT) => 데이터베이스 커넥션 반납 10) 처리 완료 개선 사항 1. 트랜잭션이 처리 시작과 동시에..

Database/SQL 2022.02.13

MySQL - 슬로우 쿼리 로그 설정 (자동으로 느린 쿼리 로그 남기기)

Slow Query Log 슬로우 쿼리 로그는 MySQL이 지원하는 느린 쿼리가 발생할 때마다 로그를 남겨주는 기능입니다. 슬로우 쿼리 로그는 on/off할 수 있고, 기준 시간 등을 설정할 수 있습니다. 설정 먼저 운영 중인 MySQL에 접속한 후, 아래의 SQL문을 수행합니다. show variables like 'slow_query_%'; 그러면 슬로우 쿼리 로그의 사용 여부와 로그의 경로가 나올겁니다. 저는 사용중이네요. 슬로우 쿼리 로그를 on 하거나 설정을 변경하려면 윈도우 환경이면 my.ini 리눅스면 my.cnf를 수정합니다. 윈도우이신 분은 C:\MySQL\MySQL Server 8.0 경로에 있습니다. 위 부분을 수정하시면 되고, slow-query-log는 1이 on, 0이 off입니..

Database/SQL 2022.02.06

Real MySQL - MySQL 기본 구조(+ 쿼리 실행 과정, 메모리 할당 구조, ...)

MySQL 서버 구조 MySQL은 아래의 그림과 같은 구조로 구성되어 있습니다. 각 시스템의 역할은 아래의 내용인 쿼리 실행 과정을 참고부탁드립니다. 쿼리 실행 과정(순서) 쿼리 실행은 아래 그림으로 설명할 수 있습니다. 각 시스템의 역할을 간략하게 설명하면 아래와 같습니다. Parser(파서) - 파서는 사용자의 요청으로 들어온 쿼리 문장을 토큰으로 분리해 트리 형태의 구조로 만들어 내는 작업을 합니다. 쿼리의 기본 문법 오류는 이 단계에서 발견되며 사용자에게 오류 메세지를 통보합니다. Pre-processor(전처리기) - 파서에서 만들어진 파서 트리를 기반으로 쿼리 문장에 구조적인 문제점이 있는지 확인 합니다. 각 토큰을 테이블 이름이나 칼럼 이름 또는 내장 함수와 같은 개체를 매핑해 해당 객체의 ..

Database/SQL 2022.02.05

MySQL - 인덱스 타는지 체크 방법 (+개선 방법, 인덱스를 타게 하는 방법)

MySQL 인덱스 타는지 확인하는 방법 mysql에서는 인덱스를 여러 개 걸었을 때 하나밖에 타지 않습니다. 그래서, 인덱스를 적절하게 걸어주지 않으면 데이터가 커졌을 때 트래픽이 튀거나 슬로우쿼리 등 문제가 될 확률이 거의 99%입니다. 인덱스를 타는 지 확인하는 방법은 MySQL의 Explain을 사용하는 것입니다. explain은 쿼리의 실행 계획을 반환해주므로 쿼리 튜닝, 성능 분석, 전략 수집 등의 기초가 됩니다 ! 사용 방법은 SELECT문 앞에 explain을 붙여주면 됩니다. explain select * from booking where resource_id=1 and start_time > NOW() order by rand(); 실행계획 분석 직접 쿼리문을 실행해보니 아래와 같은 결과..

Database/SQL 2022.01.01

데이터베이스 - 순서(정렬) 컬럼 두는 전략 비교

순서 컬럼? 일반적으로는 정렬을 id로 하지만, 특정 컬럼을 둬야 하는 경우가 생깁니다. 가령, 순서 수정이나 순서 변경 기능을 제공하는 백엔드에서 그렇죠. pk를 바꾸려면, 관련 테이블과 로그를 전부 수정해야 하기 때문이에요. 이 때는 순서 컬럼을 어떻게 두면 좋을까요? 방법 소개 stackoverflow를 통해, 존재하는 다양한 방법들을 살폈는데요. 대표적으로 4가지 방법이 있습니다. 1. 소수를 이용한 방법 2. bigint를 사용해서 bit hole을 두는 방법 3. next_id를 저장하는 방법 4. 기본적인 int를 저장하는 방법 비교 1. 소수를 이용한 방법의 경우 소수를 이용해서, 앞에 올 컬럼의 순서보다 0.01 정도씩 높여서 이동시키는 방법 적절하지만, 동작을 보장하지 않습니다. flo..

Database/SQL 2021.12.04

[Mysql] enum vs tinyint, boolean 차이점

MySQL enum? ERD 설계, 엔터티 설계, DTO 설계를 할 때 고민되는 부분이 있습니다. enum vs boolean, enum vs tinyint 어떤 차이가 있을까요? 비교 ERD를 많이 보신 분들이라면, enum('Y', 'N')을 사용하는 경우를 종종 볼 수 있습니다. 상태(State) 또는 코드(Code)에서도 enum("CANCEL", "STOP", "COMPLETE")등을 사용하기도 합니다. 하지만, 이는 그리 좋은 방법이 아닐 수 있습니다. 왜 Why? Enum은 DB 비표준이자, MySQL의 확장입니다. 여기서 문제가 발생할 수 있습니다. 다른 종류의 DBMS로 마이그레이션이 불가능합니다. 지정된 문자열이 아닌 다른 문자열이 들어왔을 때 빈 문자열이 저장될 수 있습니다. 값이 변..

Database/SQL 2021.11.24