데이터베이스18 B+Tree, B-Tree 그림 B-Tree 인덱스의 클러스터링 인덱스PK, 데이터, 자식 노드 포인터로 이루어짐 B-Tree의 세컨더리 인덱스인덱스 컬럼, PK, 자식노드 포인터로 이루어짐리프노드에는 자식노드 포인터 없음 B+Tree의 클러스터링 인덱스.PK, 자식 노드 포인터로 이루어짐 데이터는 리프노드에만 있음리프노드에는 자식 노드 포인터 대신 데이터가 삽입 B+Tree의 세컨더리 인덱스루트노드와 브랜치 노드의 오른쪽 값은 자식 노드 포인터리프노드의 오른쪽 값은 PK 2026. 4. 9. GROUP BY 그룹바이도 오더바이처럼 쿼리의 스트리밍 처리가 불가능 함그룹바이에 사용된 조건은 인덱스를 사용해서 처리될 수 없으므로 HAVING절을 튜닝할 필요 없다. 그룹바이도 인덱스를 사용하는 경우와 못하는 경우로 나뉘는게 가능함1. 인덱스 사용 - 타이트 인덱스 스캔2. 인덱스 사용 - 루스 인덱스 스캔 : 실행계획에 Using index for group-by 표시3. 인덱스 불가 - 임시 테이블 : 실행계획에 Using temporary 표시 1. 타이트 인덱스 스캔인덱스를 읽으며 그룹핑 작업을 수행하고 그 결과로 조인을 처리함 조건1. 조인의 드라이빙 테이블에 속한 칼럼만 이용해 그룹핑2. 그룹 바이 칼럼에 인덱스 존재3. WHERE 조건절이 있지만 WHERE 조건절이 인덱스를 활용하지 못할 때 2. 루스 .. 2026. 3. 15. ORDER BY (정렬) 1. 정렬 서론크게 두가지로 나뉜다.1. 인덱스를 사용하는 방법2. Filesort를 별도로 사용 인덱스 장점 - 인덱스 이미 정렬되어있어서 엄청 빠름인덱스 단점 - 인덱스의 단점을 모두 공유파일소트 장점 - 인덱스를 별도로 안만드는것, 정렬해야할 레코드가 많지 않으면 메모리에서 처리되므로 충분히 빠름파일소트 단점 - 대상 레코드가 많아질 수록 느리다 모든 정렬이 인덱스를 이용하도록 하는건 사실상 어렵다.정렬 기준이 너무 많아 요건별로 인덱스를 생성하기 어려움그룹바이나 디스딩트의 결과를 처리UNION같은 임시 테이블의 결과를 정렬랜덤하게 결과 레코드를 가져올때 2. 소트 버퍼정렬을 수행하기위한 별도의 메모리 공간이다세션 메모리 영역에 해당함 공유 불가의 공간정렬이 필요한 공간때 할당되어 쿼리 실행 완.. 2026. 3. 15. 풀 테이블 스캔 vs 풀 인덱스 스캔 1. 풀 테이블 스캔- 레코드의 건수가 너무 작아서 인덱스를 통해 읽는 것 보다 풀 테이블 스캔이 더 빠를때- WHERE 절이나 ON절에 인덱스를 이용할 수 있는 적절한 조건이 없을 때- 인덱스 레인지 스캔을 사용할 수 있어도 옵티마이저가 판단한 조건 일치 레코드가 너무 많을 때- count(컬럼)같은 경우 인덱스가 설정되지 않으면 풀 테이블 스캔할 수 있다. 2. 풀 인덱스 스캔- count(*) 개수만 조회하면 되므로 테이블보단 인덱스가 싸다. 2026. 3. 15. MySQL의 쿼리 실행 구조 MySQL서버는 MySQL엔진과 스토리지엔진으로 나누어져있다. MySQL엔진은 쿼리 파서, 전처리기, 옵티마이저, 쿼리 실행기등을 가지고 있고 스토리지 엔진은 InnoDB, MyISAM등의 종류가 있다. 1. 쿼리 파서쿼리 파서는 사용자 요청으로 들어온 쿼리를 MySQL이 인식할수있는 최소 단위인 토큰으로 분리해 트리 형태의 구조로 만들어낸다. 쿼리의 문법 오류등은 이 과정에서 발견된다. 2. 전처리기파서 트리를 기반으로 쿼리 문장에 문제점이 있는지 확인한다. 테이블 이름, 칼럼 이름등이 실제로 존재하는지 접근할 수 있는지의 과정을 이 단계에서 수행한다. 3. 옵티마이저DBMS의 두뇌로 쿼리를 가장 저렴한 비용으로 탐색할 수 있는 경로를 찾아낸다. 4. 실행엔진실행엔진은 옵티마이저가 만든 계획대로 핸들.. 2026. 3. 8. 일대다 페이징 페치조인이 위험한 이유 public class Team { public Team(Long id, String name) { this.id = id; this.name = name; } @Id private Long id; private String name; @OneToMany(mappedBy = "team") private List members = new ArrayList();}여기 팀이 있다 팀은 일대다로 멤버와 연관되어 있다. public class Member { public Member (Long id, String username, Team team) { this.id = id; this.username = username.. 2026. 2. 27. 바인드 변수의 중요성 SQL을 실행하면 파싱하고 최적화한다 이때마다 연산은 불필요하기에 보통 DB안에는 라이브러리 캐시가 있다. 만약 SQL문을 SELECT * FROM CUSTOMER WHERE LOGIN_ID = '" + login_id + "'";로 작성한다면라이브러리 캐시에는 SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'a'SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'b'SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'c'SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'd'등등이 가득차있다. 그때마다 캐시를 생성하는 것이다 그런데 만약 SELECT *FROM CUSTOMER WHERE LOGIN_ID = ?; 로.. 2026. 2. 26. 스프링에서부터 레디스까지 동작 원리 레디스 클라이언트는 레터스를 사용한다고 가정레디스의 커넥션 풀을 사용한다고 가정파이프라인을 썼다고 가정 (이건 커넥션 풀에 유무에 따라 초기 커넥션을 얻을때 파이프라인의 행동이 달라서 그렇습니다. 커넥션 풀이 있으면 커넥션 획득 동작은 단일 명령일때와 같습니다.) 1. 스프링데이터레디스는 커넥션풀(아파치 커먼스 풀2)에서 커넥션을 가져와 레터스로 요청을 보낸다.2. 레터스는 내부적으로 Netty를 호출3. Netty는 커넥션이 이미 수립되어있으니 기존에 채널이 있을것이다. 그 채널로 레디스에 요청을 보낸다.4. 레디스는 RESP프로토콜을 쓴다. 역슬래시와 r, n으로 쓰이게 데이터를 직렬화시켜 대역폭과 파싱비용을 최소화하는 프로토콜이다. 네티의 핸들러에는 RESP 인코더 디코더가 있다. 데이터를 RESP.. 2026. 1. 29. 지연로딩 vs 즉시로딩 vs 패치조인 vs JPQL일반조인 vs 일반조인 1. 엔티티@Entity@Getter@NoArgsConstructor@AllArgsConstructor@Builderpublic class Post { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "post_id") private Long id; @Column(nullable = false) private String content;} @Entity@Getter@NoArgsConstructor@AllArgsConstructor@Builderpublic class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) .. 2026. 1. 12. 인덱스 스캔 선택도란?참고로 선택도란 인덱스 컬럼의 값이 얼마나 유일한지에 대한 지표다. 성별컬럼은 남자와 여자로 이루어져있기에 값이 2개 뿐이라 선택도가 매우 낮다. 따라서 인덱스 컬럼은 선택도가 높은 컬럼으로 지정하는게 좋다. 비용이란?비용이란 시스템의 성능, 안전성, 보안, 유지보수등에 지출되는 비용을 의미한다 DB에서 비용은 하드웨어, 소프트웨어, 인력, 보안, 유지보수 비용등의 요소가 포함되어있다. 수직적 탐색이란?B+tree에서 Root 노드에서 시작해 필요한 데이터가 있는 리프 노드까지 아래로 내려가는 탐색WHERE id = 100 같이 정확한 값을 찾을 때 id 인덱스 트리를 따라 100을 찾아간다. 수평적 탐색이란?수직적 탐색에서 찾은 첫 번째 리프노드에서 시작하여 인접한 리프 노드들을 좌우로 연결 .. 2026. 1. 10. 순차I/O와 랜덤I/O 순차I/O는 데이터를 연속적인 블록으로 순차적으로 읽거나 쓰는 작업이다.랜덤I/O는 데이터를 임의의 위치에서 읽거나 쓰는 작업이다. 순차I/O는 SSD에서 HDD보다 성능이 폭발적으로 상승하진않았지만. 랜덤 I/O는 SSD에서 성능이 크게 상승다.DB에서 일어나는 작업의 대부분은 랜덤 I/O기 때문에 RealMysql8.0에서는 SSD와 HDD의 초당 트랙잭션 처리 성능차이가 약 7배 라고 설명한다. 최근에 대부분 DBMS는 SSD를 채택한다. HDD에서 두 I/O의 공통점은 원판은 돌려서 읽어야 할 데이터가 저장된 위치까지 디스크 헤더를 이동시킨다는 것두 I/O의 성능차이는 디스크 헤더의 이동 횟수에서 발생한다. 디스크 헤더가 이동되는 시간을 seek time이라고 하는데 그 시간에 의해 좌우되는 것이.. 2026. 1. 10. 세션과 커넥션 요약1. 최초에 히카리데이터소스에서 풀엔트리크리에이터 생성 풀 엔트리크리에이터에서 콜() 호출2. 히카리풀에서 createPoolEntry() 호출 PollBase에서 newPollEntry() 호출 뉴커넥션 호출 히카리데이터소스에서 겟커넥션 호출 커넥션 반환 커넥션풀 만큼 커넥션을 만듬3. @Tramsctional 달린 메소드 시작 트랜잭션인터셉터 호출4. TransactionAspectSupport의 invokeWithinTransaction() 호출 createTransactionIfNecessary() 호출 5. 플랫폼트랜잭션매니저의 구현체인 AbstractPlatformTransactionManager에서 겟트랜잭션시작6AbstractPlatformTransactionManager을 상속받은 하.. 2026. 1. 9. 이전 1 2 다음