개발자상식 <백엔드 개발자> (8)[책리뷰 & Book review]
개발자상식 <백엔드 개발자> (8)
[책리뷰 & Book review]
인덱스를 추가하면 데이터베이스의 데이터 스키마는 변경되나?
인덱스를 추가하면 데이터베이스의 데이터 스키마는 변경되지 않습니다.
즉, 테이블의 구조나 데이터는 그대로 유지되며,
인덱스는 데이터를 더 빠르게 찾을 수 있도록 돕는 추가적인 데이터 구조입니다.
인덱스는 데이터베이스의 테이블에 있는 하나 이상의 열(column)에 대한 포인터를 유지합니다.
이것은 책의 색인과 매우 비슷합니다.
색인이 없는 책에서 특정 단어를 찾으려면, 책의 모든 페이지를 읽어야 할 것입니다.
이것은 매우 시간이 소요되는 작업입니다.
반면 색인이 있는 책에서는, 색인에서 단어를 찾아 해당 페이지로 바로 이동할 수 있습니다.
마찬가지로, 테이블에서 특정 데이터를 찾을 때, 인덱스가 없다면 데이터베이스는 테이블의 모든 행(row)을 검색해야 합니다. 이것은 전체 테이블 스캔(full table scan)이라고 하며, 매우 비효율적입니다.
반면 인덱스가 있다면, 데이터베이스는 인덱스를 사용해 특정 데이터를 더 빠르게 찾을 수 있습니다.
그러나 인덱스는 항상 성능을 향상하는 것은 아닙니다.
인덱스는 추가적인 저장 공간을 사용하며, 데이터가 변경될 때마다 인덱스도 함께 업데이트해야 합니다.
따라서 데이터가 자주 변경되는 테이블에는 인덱스를 추가하는 것이 반드시 좋은 것이 아닐 수 있습니다. 이런 이유로,
어떤 열에 인덱스를 추가할 것인지는 신중하게 결정해야 합니다.
색인과목차는 같은것인가?
책의 색인(index)과 목차(table of contents)는 조금 다른 개념입니다.
물론 둘 다 책의 내용을 빠르게 찾아갈 수 있도록 도와주는 역할을 하지만, 구체적인 용도와 형태가 다릅니다.
목차(Table of Contents): 책의 주요 장과 절을 나열하고, 각 부분의 시작 페이지를 표시합니다.
책을 읽을 때 전체적인 흐름을 파악하거나, 특정 장을 찾아갈 때 사용합니다.
색인(Index): 책의 뒷부분에 위치하며, 책에서 다루는 주요 키워드와 주제를 알파벳 순으로 나열합니다.
각 키워드 옆에는 해당 키워드가 어느 페이지에서 언급되었는지를 표시합니다.
책에서 특정 주제나 단어를 찾아볼 때 사용합니다.
데이터베이스의 인덱스는 이 색인과 비슷한 역할을 합니다.
특정 칼럼의 값에 빠르게 접근할 수 있도록 도와주는 역할을 하죠.
이를 통해 특정 값을 가진 데이터를 찾을 때 전체 데이터를 살펴보지 않고, 필요한 부분만 빠르게 찾아갈 수 있습니다.
컨트롤+F 키를 사용하여 웹페이지나 문서에서 특정 단어를 찾는 것과 유사한 원리를 데이터베이스에서 적용한 것이
인덱스입니다.
하지만 인덱스는 컨트롤+F보다 더 복잡합니다.
데이터베이스 인덱스는 특정 열의 데이터를 사전식 순서(또는 숫자의 경우 숫자 순서)로 정렬하고, 이 정렬된 데이터에 대한 포인터를 저장합니다. 이렇게 하면 데이터베이스는 특정 값을 찾을 때 전체 테이블을 스캔하지 않고, 인덱스를 통해 빠르게 해당 데이터를 찾을 수 있습니다.
즉, 인덱스는 데이터베이스에서 특정 값을 빠르게 찾는 방법을 제공하며, 이는 데이터베이스 성능을 크게 향상합니다. 하지만 인덱스는 저장 공간을 추가로 사용하고, 데이터가 변경될 때마다 업데이트해야 하므로, 신중하게 사용해야 합니다.
데이터베이스 인덱스를 이해하려면
전화번호부이다?
데이터베이스 인덱스를 이해하는 데 있어서 가장 좋은 예시는 전화번호부입니다.
전화번호부에서 이름을 찾을 때, 우리는 모든 페이지를 차례대로 읽지 않습니다. 대신, 이름이 알파벳순으로 정렬되어 있기 때문에 우리는 빠르게 원하는 이름을 찾을 수 있습니다.
이것이 바로 데이터베이스에서 인덱스가 하는 일입니다.
인덱스는 특정 열의 데이터를 정렬하고, 이 정렬된 데이터를 찾기 위한 '포인터'를 저장합니다.
예를 들어,
users 테이블에 first_name 열에 대한 인덱스를 만들어 봅시다.
sql
CREATE INDEX idx_first_name ON users (first_name);
이제 데이터베이스는 first_name 열의 데이터를 알파벳 순으로 정렬하고, 이 데이터를 찾기 위한 포인터를 저장합니다. 이 포인터는 실제 데이터가 저장된 테이블의 위치를 가리킵니다.
text
first_name pointer
---------- -------
Adam --> Adam's row in users table
Alex --> Alex's row in users table
Alice --> Alice's row in users table
...
Zoe --> Zoe's row in users table
이제 first_name이 'Alice'인 사용자를 찾아야 한다고 가정해 봅시다.
sql
SELECT * FROM users WHERE first_name = 'Alice';
데이터베이스는 이제 인덱스를 사용하여 'Alice'를 빠르게 찾을 수 있습니다.
인덱스에서 'Alice'를 찾은 후, 해당 포인터를 따라 실제 테이블의 'Alice' 행을 찾아갑니다.
이렇게 인덱스를 사용하면 데이터베이스는 전체 테이블을 스캔하지 않고도 원하는 데이터를 빠르게 찾을 수 있습니다.
이는 특히 큰 테이블에서 데이터를 조회할 때 매우 중요합니다.
데이터베이스 인덱스를 빠르게 찾는 방법은
단일 열 인덱스 생성
복합 열 인덱스 생성
전체 텍스트 인덱스 생성 이 있다.
단일 열 인덱스 생성
복합 열 인덱스 생성
전체 텍스트 인덱스 생성 이 있다.
데이터베이스에서 인덱스를 사용하는 몇 가지 일반적인 방법에 대해 설명하겠습니다.
먼저, SQL 코드와 설명을 제공하고, 이후에 해당 코드의 동작을 설명하는 텍스트 그림을 제공하겠습니다.
단일 열 인덱스 생성
sql
CREATE INDEX idx_first_name ON users (first_name);
이 코드는 users 테이블의 first_name 열에 인덱스를 생성합니다. 이는 first_name 열에서 특정 이름을 찾을 때 데이터베이스가 더 빠르게 데이터를 찾을 수 있도록 돕습니다.
텍스트 그림:
text
first_name pointer
---------- -------
Adam --> Adam's row in users table
Alex --> Alex's row in users table
Alice --> Alice's row in users table
...
Zoe --> Zoe's row in users table
복합 열 인덱스 생성
sql
CREATE INDEX idx_name ON users (first_name, last_name);
이 코드는 users 테이블의 first_name 열과 last_name 열에 대한 인덱스를 생성합니다. 이는 두열을 모두 사용하는 쿼리를 더 빠르게 만듭니다.
텍스트 그림:
text
first_name last_name pointer
---------- --------- -------
Adam Smith --> Adam Smith's row in users table
Alex Johnson --> Alex Johnson's row in users table
Alice Kim --> Alice Kim's row in users table
...
Zoe Park --> Zoe Park's row in users table
전체 텍스트 인덱스 생성
sql
CREATE FULLTEXT INDEX idx_text ON articles (title, body);
이 코드는 articles 테이블의 title 열과 body 열에 대한 전체 텍스트 인덱스를 생성합니다.
이는 텍스트 검색 쿼리를 더 빠르게 만듭니다.
텍스트 그림:
text
title body pointer
-------- ------ -------
Title1 Body text1 --> Article 1's row in articles table
Title2 Body text2 --> Article 2's row in articles table
...
TitleN Body textN --> Article N's row in articles table
여기서 제공된 예제는 가장 일반적인 인덱스 사용 방법을 보여줍니다.
실제로는 데이터베이스의 구조와 사용 패턴에 따라 인덱스를 사용하는 방법이 달라질 수 있습니다.
따라서 특정 상황에 가장 적합한 인덱스 전략을 결정하기 위해서는 해당 DBMS의 공식 문서와 여러 가지 DBMS 최적화 기법을 참고하는 것이 좋습니다.
데이터베이스에서 키-벨류(Key-Value)
데이터베이스에서 키-벨류(Key-Value)는 데이터 항목을 구분하고, 찾는 데 사용되는 고유한 식별자입니다.
자바에서는 이 개념이 주로 Map 인터페이스와 그 하위 클래스들에 의해 구현됩니다.
Map은 키-벨류 쌍을 저장하며, 키를 사용하여 특정 벨류를 검색할 수 있게 해 줍니다.
다음은 이를 사용하는 간단한 예제입니다:
java
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// HashMap 인스턴스 생성
Map<String, String> database = new HashMap<>();
// 데이터베이스에 키-벨류 쌍 추가
database.put("키1", "벨류1");
database.put("키2", "벨류2");
database.put("키3", "벨류3");
// 데이터베이스에서 키를 이용하여 벨류 검색
String value1 = database.get("키1");
System.out.println("키1의 벨류: " + value1);
// 데이터베이스에 있는 모든 키-벨류 쌍 출력
for (Map.Entry<String, String> entry : database.entrySet()) {
System.out.println("키: " + entry.getKey() + ", 벨류: " + entry.getValue());
}
}
}
이 예제에서는 HashMap을 사용하여 키-벨류 데이터베이스를 생성하고, 데이터를 추가하고, 검색하는 방법을 보여줍니다.
사용법:
Map <String, String> database = new HashMap <>(); : 새로운 HashMap을 생성합니다. HashMap은 Map 인터페이스의 구현 클래스로 키-벨류 쌍을 저장합니다.
database.put("키 1", "벨류 1"); : 키-벨류 쌍을 HashMap에 추가합니다.
String value1 = database.get("키 1"); : HashMap에서 키를 이용해 벨류를 검색합니다.
for (Map.Entry <String, String> entry : database.entrySet()) : HashMap에 있는 모든 키-벨류 쌍을 순회하고 출력합니다.
이렇게 자바에서는 Map 인터페이스를 통해 데이터베이스의 키-벨류 개념을 구현하고 활용할 수 있습니다.
형태의 표현은 제네릭
<T> 형태의 표현은 제네릭을 사용하기 위한 문법입니다.
여기서 T는 타입 변수를 의미하며, 이는 실제 타입으로 대체될 수 있습니다.
T 외에도 자바에서 자주 사용되는 타입 변수로 E, K, V, N, S 등이 있습니다. 이들은 각각 다음과 같은 의미를 가집니다:
E: Element의 약자로, 주로 컬렉션의 요소를 나타낼 때 사용됩니다.
K: Key의 약자로, 주로 Map의 키를 나타낼 때 사용됩니다.
V: Value의 약자로, 주로 Map의 값(value)을 나타낼 때 사용됩니다.
N: Number의 약자로, 주로 숫자를 나타낼 때 사용됩니다.
S, U, V 등: 두 번째, 세 번째, 네 번째 타입 변수를 나타낼 때 사용됩니다.
이렇게 제네릭을 사용하면 다양한 타입을 하나의 클래스나 메서드에서 처리할 수 있어 코드의 재사용성을 높일 수 있습니다.
다음은 Map <K, V>을 사용하는 예제입니다:
java
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
이 코드에서 Map <String, Integer>는 K에 String 타입을, V에 Integer 타입을 대입한 것입니다.
따라서 이 map은 키로 String 타입을, 값으로 Integer 타입을 사용하는 맵이 됩니다. 이처럼 제네릭을 사용하면 다양한 타입에 대응하는 클래스나 메서드를 쉽게 구현할 수 있습니다.
제네릭에서 사용되는 타입 변수는 다음과 같습니다:
<T>: 이것은 "Type"을 의미하며, 어떤 타입이든 될 수 있습니다.
제네릭 코드를 작성할 때 가장 일반적으로 사용되는 타입 변수입니다. 예제:
java
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
위의 Box <T> 클래스는 어떤 타입의 객체도 저장할 수 있습니다.
<E>: "Element"를 의미하며, 주로 컬렉션에서 요소의 타입을 나타낼 때 사용됩니다. 예제:
java
List<E> list = new ArrayList<>();
위의 List <E>에서 E는 리스트의 요소 타입을 나타냅니다.
<K>, <V>: "Key"와 "Value"를 의미하며, 주로 Map에서 키와 값의 타입을 나타낼 때 사용됩니다. 예제:
java
Map<K, V> map = new HashMap<>();
위의 Map <K, V>에서 K는 맵의 키 타입, V는 맵의 값 타입을 나타냅니다.
<N>: "Number"를 의미하며, 주로 숫자 타입을 나타낼 때 사용됩니다.
<S>, <U>, <V> 등: 두 번째, 세 번째, 네 번째 타입 변수를 나타낼 때 사용됩니다.
이런 식으로 제네릭을 사용하면 타입을 파라미터로 취급하여 다양한 타입에 대응하는 유연한 코드를 작성할 수 있습니다.
이는 코드의 재사용성을 높이고, 타입 안정성을 보장하여 런타임 에러를 방지하는 데 도움이 됩니다.
#개발자취업 #개발자기초 #개발자 #개발자분야 #개발자분류 #개발자종류 #it개발자 #서버개발자 #개발자성장 #신입개발자 #ios개발자 #개발자노트북 #개발자 되는 법 #개발 #앱개발 #웹개발 #개발분야 #it개발 #개발공부 #코딩상식 #개발공부 #개발초보
#개발자취업 #개발자면접 #개발자채용 #백엔드개발자 #백엔드개발자 #백엔드개발자취업 #백엔드개발 #프런트엔드개발자 #개발자상담 #백엔드 #개발자 #앱개발자 #웹개발자 #개발자팁 #앱개발자 #백엔드취업 #백엔드공부 #백엔드강의 #백엔드독학
#전산직면접 #면접 #면접팁 #면접관 #공공기관전산직면접 #공사면접 #면접질문 #면접할 말 #면접준비 #면접준비 #면접답변 #면접질문 #면접기출 #전화면접 #면접복장 #면접답변 #면접꿀팁 #모의면접 #면접후기 #롯데면접 #면접후기 #임원면접 #최종면접 #면접꿀팁