문자열 데이터를 다루다 보면 단순한 LIKE만으로는 처리하기 어려운 경우가 있다.예를 들어 다음과 같은 작업이다.문자열이 숫자로만 구성되어 있는지 검사이메일과 비슷한 형식인지 검사문자열에서 숫자만 제거하거나 추출쉼표로 구분된 문자열에서 특정 번째 값 추출특정 패턴이 문자열에 몇 번 등장하는지 계산Oracle에서는 이러한 작업을 위해 REGEXP_LIKE, REGEXP_REPLACE, REGEXP_SUBSTR, REGEXP_INSTR, REGEXP_COUNT와 같은 정규표현식 함수를 제공한다.1. 정규표현식 기본 패턴정규표현식은 일반 문자와 특별한 의미를 갖는 메타 문자를 조합해 문자열의 패턴을 표현한다.예를 들어 [0-9]+는 숫자가 1개 이상 연속되는 문자열을 의미하고,^[0-9]+$는 문자열 전체가 ..
실행 계획을 보다 보면 SORT AGGREGATE, SORT ORDER BY, SORT GROUP BY, SORT UNIQUE와 같은 Sort 오퍼레이션을 자주 볼 수 있다.모두 이름에 Sort가 들어가지만 역할은 서로 다르다. 어떤 오퍼레이션은 실제 정렬을 수행하고, 어떤 오퍼레이션은 이름과 달리 정렬을 수행하지 않는다.이번 글에서는 각 Sort 오퍼레이션이 언제 발생하는지와 내부 동작을 그림과 함께 정리해보자.1. SORT AGGREGATE전체 로우를 대상으로 하나의 집계 결과를 만들 때 발생한다.이름에 Sort가 포함되어 있지만 실제 정렬은 수행하지 않는다.SELECT SUM(sal), MAX(sal), MIN(sal)FROM emp;동작 흐름EMP │ ▼모든 Row 읽기 │ ..
SQL 튜닝을 하다 보면 IN 조건을 자주 사용한다.WHERE status IN ('PAID', 'READY', 'DONE')겉으로 보면 단순히 여러 값을 비교하는 조건처럼 보인다.하지만 실행계획 관점에서 보면 IN 조건은 생각보다 중요한 차이를 만든다.특히 Oracle에서는 INLIST ITERATOR라는 실행 방식으로 나타날 수 있고, 이 경우 IN 목록의 각 값을 기준으로 인덱스를 반복 탐색한다. 반대로 어떤 경우에는 IN 조건이 인덱스 탐색 범위를 만드는 데 사용되지 않고, 이미 읽은 데이터에 대해 값이 맞는지 확인하는 filter 조건으로 사용되기도 한다.이 글에서는 IN 조건이 인덱스에서 어떻게 동작하는지, 그리고 왜 항상 INLIST ITERATOR가 좋은 것은 아닌지 정리한다. 1. IN..
들어가며서비스를 개발하다 보면 거의 모든 데이터에 ID가 필요하다.예를 들어 다음과 같은 데이터들은 대부분 고유한 식별자를 가진다.회원 ID주문 ID게시글 ID댓글 ID결제 ID단일 서버와 단일 데이터베이스만 사용하는 환경에서는 ID 생성이 비교적 단순하다. 데이터베이스의 AUTO_INCREMENT나 SEQUENCE를 사용하면 된다.User Tableid | name---|------1 | Kim2 | Lee3 | Park하지만 시스템 규모가 커지면 상황이 달라진다.서버가 여러 대로 늘어나고, 데이터베이스가 샤딩되고, 여러 지역의 데이터센터에서 동시에 요청을 처리해야 한다면 단순히 숫자를 1씩 증가시키는 방식만으로는 충분하지 않을 수 있다.Server A ─┐Server B ─┼──> ID 생성Se..
어떤 값이 집합에 "있을 수도 있음 / 없음은 확실함"을 매우 빠르고 메모리 효율적으로 판단하기 위한 확률적 자료 구조이다.1. 목적존재 여부 검사를 빠르게 하기 위함정확성보다 속도와 메모리 효율을 우선대표적인 사용 목적캐시 Penetration 방지존재 가능한 키만 Bloom Filter에 미리 등록요청 키가 Bloom Filter에서 없음이면 Cache / DB 접근 자체를 차단존재하지 않는 ID에 대한 반복 DB 조회 방지 및 봇·악성 트래픽 방어중복 요청 차단이미 처리된 요청 ID를 Bloom Filter에 기록하여 요청이 다시 들어올 경우 "이미 처리됨"으로 간주멱등성 보조 수단 및 결제, 메세지 발송 중복 방지 (정확성이 중요한 경우 단독 사용은 부적합) 크롤러의 URL 중복 방문 방지방문한 ..
Redis는 클라이언트 요청을 이벤트 루프 기반으로 처리하고, Redis 자료구조를 직접 읽고 쓰는 명령 실행은 메인 쓰레드 중심으로 동작한다. 하지만 파일 닫기, AOF fsync, 메모리 해제 같은 일부 느린 작업은 백그라운드 쓰레드로 넘긴다.그래서 Redis를 정확히 이해하려면 다음 두 가지를 구분해야 한다.1. Redis 명령 실행 경로 - GET, SET, INCR, HSET 같은 명령 실행 - 메인 쓰레드 중심2. Redis 프로세스 전체 - 메인 쓰레드 외에도 백그라운드 쓰레드 존재 - 파일 닫기, AOF fsync, lazy free 등 처리1. Redis가 싱글 쓰레드라는 말의 의미Redis가 싱글 쓰레드라고 할 때 핵심은 데이터를 읽고 쓰는 명령 실행 경로가 기본적으로 하..
실행 계획을 보다 보면 range, ref, ALL 같은 접근 방식과 함께DBMS에 따라 인덱스 풀스캔에 가까운 동작이 등장한다.이름만 보면 비효율적으로 느껴질 수 있지만, 실제로는 상황에 따라 꽤 합리적인 선택이 된다.중요한 건 “인덱스를 일부만 읽는 스캔이 아니라, 인덱스 전체를 읽는 스캔” 이라는 점이다.1. 인덱스 풀스캔이 무엇이며, 어떻게 동작하는가인덱스 풀스캔은 말 그대로 인덱스의 처음부터 끝까지 전체를 읽는 방식이다.보통 인덱스는 특정 값을 빠르게 찾기 위해 사용한다고 배운다.예를 들어 where id = 10 같은 조건에서는 인덱스의 일부만 읽으면 된다.그런데 어떤 쿼리는 조건 검색보다도 정렬된 순서나 인덱스에 담긴 컬럼 자체가 더 중요하다.이럴 때 옵티마이저는 테이블 전체를 읽는 대신 인..
설치 1. github에서 tar.gz 파일 다운로드 (https://github.com/yahoo/CMAK) 2. 압축 해제 후 설치한 폴더 내에서 ./sbt clean dist 명령어 실행 Cannot use JVMCI compiler: No JVMCI compiler found 명령어 실행 시 위 에러가 발생한 경우, 링크 참고 3. target/universal 경로에 생성된 .zip 파일을 원하는 위치에 압축 해제 4. conf/application.conf 파일 수정 (로컬에 주키퍼를 띄웠기 때문에 아래와 같이 수정) 5. ./bin/cmak 명령어 실행 후, localhost:9000 접속 ! @7jn3njc8f - Internal server error, for (GET) [/assets..