포스트

2022-04-22-TIL

Today I Learned

B-Tree Index

대부분의 RDBMS 인덱스는 B-Tree 계열 자료구조다. 키가 정렬된 상태로 저장되고 트리 높이가 낮게 유지되므로, 일치 검색뿐 아니라 범위 검색(BETWEEN, >, LIKE 'abc%')과 정렬(ORDER BY)에도 쓸 수 있다. 데이터가 추가되거나 삭제되면 노드를 분할하거나 합쳐 균형을 유지하므로, 인덱스가 많을수록 쓰기 비용이 늘어난다. 복합 인덱스는 왼쪽 컬럼부터 정렬되어 있어서, 선두 컬럼 조건 없이 뒤 컬럼만으로 검색하면 인덱스를 효율적으로 쓰지 못한다.

  • https://12bme.tistory.com/138

B-tree and B+Tree

B+ tree는 B-tree의 변형으로, 내부 노드에는 탐색용 키만 두고 실제 레코드(또는 레코드 포인터)는 모두 리프 노드에 둔다. 리프 노드끼리는 연결되어 있다.

 B-treeB+tree
데이터 위치모든 노드리프 노드에만
내부 노드키와 데이터키만, 그래서 한 노드에 더 많은 키
범위 검색트리를 오르내리며 순회리프의 연결을 따라 순차 읽기

내부 노드에 키만 있으니 한 페이지에 더 많은 자식을 가리킬 수 있어 트리가 낮아지고, 범위 검색은 시작 리프를 찾은 뒤 옆으로 읽기만 하면 된다. 디스크 페이지 단위로 읽는 DB에 잘 맞아서 MySQL InnoDB의 인덱스도 B+tree 구조다.

  • https://en.wikipedia.org/wiki/B%2B_tree
  • https://sdesigner.tistory.com/79
  • https://zorba91.tistory.com/293

Indexing Boolean Field

boolean 컬럼처럼 값의 종류가 두세 개뿐인(카디널리티가 낮은) 컬럼은 단독 인덱스의 효과가 작다. 조건에 맞는 행이 테이블의 절반이라면, 옵티마이저는 인덱스를 거쳐 행을 하나씩 찾아가기보다 테이블 전체를 읽는 편이 낫다고 판단한다. 다만 값의 분포가 치우쳐 있어서 찾는 값이 아주 드물다면(예: 처리되지 않은 소수의 행) 인덱스가 도움이 될 수 있고, 다른 선택도 높은 컬럼과 묶은 복합 인덱스의 일부로 쓰는 경우도 많다.

  • https://stackoverflow.com/questions/10524651/is-there-any-performance-gain-in-indexing-a-boolean-field

DTO, VO, Entity

엔티티는 식별자로 구분되는 도메인 객체, VO는 값으로 비교되는 불변 객체, DTO는 계층 사이에 데이터를 옮기는 객체다. 링크된 테코블 글은 셋을 용도, 상태 변경 여부, 로직 포함 여부로 비교한다. DTO는 레이어 간 데이터 전송용으로 가변일 수도 불변일 수도 있고, getter/setter 외의 비즈니스 로직은 갖지 않는다. VO는 값을 표현하는 불변 객체로 setter가 없고, 모든 속성 값이 같으면 같은 객체로 본다. 엔티티는 DB 테이블에 매핑되어 ID로 구분되며, 비즈니스 로직을 가질 수 있다.

  • https://tecoble.techcourse.co.kr/post/2021-05-16-dto-vs-vo-vs-entity/
  • https://youngjinmo.github.io/2021/04/dto-vo-entity/
  • https://www.baeldung.com/java-dto-pattern
  • https://www.baeldung.com/java-pojo-javabeans-dto-vo

R-tree Index

R-tree는 1984년 Antonin Guttman이 제안한 공간 데이터용 인덱스다. 점, 선, 다각형 같은 공간 객체를 감싸는 최소 경계 사각형(MBR)으로 묶고, 가까운 사각형들을 다시 더 큰 사각형으로 묶어 트리를 만든다. “이 영역 안에 있는 가게”처럼 범위가 겹치는 객체를 찾을 때, 겹치지 않는 사각형 아래는 탐색하지 않아 빠르다. MySQL 문서에 따르면 InnoDB와 MyISAM에서 SPATIAL INDEX는 R-tree 인덱스를 만든다. 위치 기반 서비스에서 반경 검색을 할 때 쓰인다.

  • https://www.ibm.com/docs/en/informix-servers/14.10?topic=guide-r-tree-indexes
  • https://www.geeksforgeeks.org/introduction-to-r-tree/
  • https://dl.acm.org/doi/fullHtml/10.1145/3397506

Full Text Search Index

LIKE '%keyword%'는 B-Tree 인덱스를 쓰지 못하므로, 본문 검색에는 전문 검색 인덱스를 쓴다. MySQL 문서에 따르면 FULLTEXT 인덱스는 InnoDB와 MyISAM의 CHAR, VARCHAR, TEXT 컬럼에 만들 수 있고, MATCH ... AGAINST로 자연어 검색, 불린 검색, 쿼리 확장 검색을 할 수 있다. 공백으로 단어를 나누기 어려운 한국어, 중국어, 일본어를 위해 n-gram 파서도 내장되어 있다.

Elasticsearch와의 차이는 링크된 Stack Overflow 답변처럼 목적에 있다. MySQL 전문 검색은 DB 안에서 간단히 쓸 수 있지만 형태소 분석, 관련도 점수 조정, 오타 허용 같은 검색 품질 기능과 대용량 분산 처리에는 한계가 있다. Elasticsearch는 검색을 위한 전용 엔진이라 이런 기능이 풍부한 대신, DB와 데이터를 동기화하는 파이프라인을 따로 운영해야 한다.

  • https://enterone.tistory.com/229
  • https://stackoverflow.com/questions/41892179/elastic-search-full-text-vs-mysql-full-text#:~:text=The%20main%20difference%20ElasticSearch%20from,the%20database%2C%20as%20in%20MySQL.

Spring Batch vs DB Procedure

대량 데이터 처리를 DB 프로시저로 할지 Spring Batch 같은 애플리케이션 배치로 할지의 문제다. 프로시저는 데이터가 있는 DB 안에서 실행되어 네트워크 전송이 없고 빠르지만, 비즈니스 로직이 DB에 들어가 버전 관리, 테스트, 디버깅이 어렵고 특정 DB에 묶인다. Spring Batch는 청크 단위 처리, 재시작, 건너뛰기, 실행 이력 관리 같은 배치 기능을 제공하고 자바 코드로 테스트할 수 있지만, 데이터를 애플리케이션으로 읽어 와야 하므로 I/O 비용이 든다. 단순한 집계나 대량 갱신은 SQL로, 복잡한 로직과 외부 연동이 섞인 처리는 Spring Batch로 나누는 식의 절충이 흔하다.

  • https://prodo-developer.tistory.com/165

Natural vs Artificial Primary Keys

4월 4일 TIL에서 정리한 자연 키와 인조 키 비교와 같은 주제다. 링크된 글도 자연 키는 바뀔 수 있다는 위험을, 인조 키는 비즈니스상 중복을 따로 막아야 한다는 점을 짚는다.

  • https://sqlstudies.com/2016/08/29/natural-vs-artificial-primary-keys/

Redis Structure

Redis는 데이터를 메모리에 두는 키-값 저장소로, 값으로 String, List, Set, Sorted Set, Hash, Stream 같은 자료구조를 제공한다. 명령은 하나의 스레드에서 차례로 실행되므로 개별 명령은 원자적이다. 메모리에만 두면 재시작 시 데이터가 사라지므로, 주기적으로 스냅샷을 남기는 RDB나 쓰기 명령을 로그로 남기는 AOF로 디스크에 영속화할 수 있다. 고가용성은 복제와 Sentinel, 수평 확장은 Redis Cluster로 구성한다.

  • https://redis.io/docs/about/
  • https://redis.com/redis-enterprise/data-structures/
참고한 자료외부 출처 3

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다