πŸ“Œ ν…Œμ΄λΈ” 생성 및 관리

이번 λ‹¨κ³„μ—μ„œλŠ” DDL(Data Definition Language, 데이터 μ •μ˜μ–΄)에 λŒ€ν•΄ μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€.

DDL은 λ°μ΄ν„°λ² μ΄μŠ€ ꡬ쑰(ν…Œμ΄λΈ”, 인덱슀, λ·° λ“±)λ₯Ό μ •μ˜ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” λͺ…λ Ήμ–΄μž…λ‹ˆλ‹€.

DDL의 λŒ€ν‘œμ μΈ λͺ…λ Ήμ–΄λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.


3-1. ν…Œμ΄λΈ” 생성 (CREATE TABLE)

데이터λ₯Ό μ €μž₯ν•˜λ €λ©΄ λ¨Όμ € ν…Œμ΄λΈ”(Table)을 λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

βœ… 기본적인 ν…Œμ΄λΈ” 생성

CREATE TABLE employees (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    age INT CHECK (age >= 18),
    department VARCHAR(50),
    salary DECIMAL(10,2) DEFAULT 0.00,
    hire_date DATE NOT NULL
    CONSTRAINT chk_age CHECK (age >= 18) -- CHECK μ œμ•½ 쑰건 (MariaDB 10.2+μ΄μƒμ—μ„œ 지원)
);

μ„€λͺ…

πŸ“Œ AUTO_INCREMENTκ°€ 적용된 PRIMARY KEY

βœ… PRIMARY KEY

βœ… AUTO_INCREMENT

βœ… μ‹€λ¬΄μ—μ„œ 많이 μ‚¬μš©λ˜λŠ” νŒ¨ν„΄

CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,  -- μ‚¬μš©μž ID μžλ™ 증가
    username VARCHAR(50) NOT NULL UNIQUE,  -- 쀑볡 λΆˆκ°€
    email VARCHAR(100) NOT NULL UNIQUE,  -- 쀑볡 λΆˆκ°€
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP  -- ν˜„μž¬ μ‹œκ°„ μžλ™ μž…λ ₯
);

πŸ“Œ μ‚¬μš©μž 정보λ₯Ό μ €μž₯ν•˜λŠ” ν…Œμ΄λΈ”μ—μ„œ user_idλ₯Ό AUTO_INCREMENT PRIMARY KEY둜 μ„€μ •ν•˜μ—¬ μžλ™ 증가

πŸ“Œ μΆ”κ°€μ μœΌλ‘œ UNIQUE μ œμ•½ 쑰건을 μ μš©ν•˜μ—¬ μ€‘λ³΅λœ μ‚¬μš©μžλͺ…이 μž…λ ₯λ˜μ§€ μ•Šλ„λ‘ μ„€μ •


3-2. μ œμ•½ 쑰건(Constraints)

μ œμ•½ 쑰건은 데이터 무결성을 보μž₯ν•˜λŠ” μ€‘μš”ν•œ μš”μ†Œμž…λ‹ˆλ‹€.

μ£Όμš” μ œμ•½ 쑰건은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

μ œμ•½ 쑰건 μ„€λͺ…
PRIMARY KEY ν…Œμ΄λΈ”μ˜ κΈ°λ³Έ ν‚€, κ³ μœ ν•œ κ°’ μœ μ§€
FOREIGN KEY λ‹€λ₯Έ ν…Œμ΄λΈ”κ³Ό 관계λ₯Ό λ§ΊλŠ” μ™Έλž˜ ν‚€
UNIQUE 쀑볡 값을 ν—ˆμš©ν•˜μ§€ μ•ŠλŠ” 컬럼
NOT NULL NULL 값을 ν—ˆμš©ν•˜μ§€ μ•ŠμŒ
CHECK νŠΉμ • 쑰건을 λ§Œμ‘±ν•΄μ•Ό μ €μž₯ κ°€λŠ₯
DEFAULT 값이 없을 경우 κΈ°λ³Έκ°’ μ„€μ •

βœ… μ œμ•½ 쑰건을 μ μš©ν•œ ν…Œμ΄λΈ” 생성

CREATE TABLE departments (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) UNIQUE NOT NULL
);
CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    department_id INT,
    FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE SET NULL
);

μ„€λͺ…

🚨 ON DELETE μ˜΅μ…˜ μ„€λͺ… 보강

βœ… μΆ”κ°€λœ μ„€λͺ… 및 예제

CREATE TABLE employees (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    department_id INT,
    FOREIGN KEY (department_id) REFERENCES departments(id)
    ON DELETE SET NULL -- μƒμœ„ ν…Œμ΄λΈ”μ˜ 값이 μ‚­μ œλ˜λ©΄ NULL둜 λ³€κ²½
    ON UPDATE CASCADE  -- μƒμœ„ ν…Œμ΄λΈ” 값이 λ³€κ²½λ˜λ©΄ μžλ™ λ³€κ²½
);

πŸ“Œ λ‹€λ₯Έ ON DELETE μ˜΅μ…˜ μ„€λͺ… μΆ”κ°€

μ˜΅μ…˜ μ„€λͺ…
ON DELETE CASCADE λΆ€λͺ¨ 데이터 μ‚­μ œ μ‹œ μžμ‹ 데이터도 μ‚­μ œ
ON DELETE SET NULL λΆ€λͺ¨ 데이터 μ‚­μ œ μ‹œ μžμ‹ μ»¬λŸΌμ„ NULL둜 λ³€κ²½
ON DELETE RESTRICT λΆ€λͺ¨ 데이터 μ‚­μ œλ₯Ό μ œν•œ (였λ₯˜ λ°œμƒ)
ON DELETE NO ACTION RESTRICT와 동일 (SQL ν‘œμ€€ μœ μ§€)

πŸ“Œ μ™Έλž˜ ν‚€λ₯Ό μ •μ˜ν•  λ•Œ ON DELETE 및 ON UPDATE μ˜΅μ…˜μ„ λͺ…ν™•νžˆ 이해


3-3. ν…Œμ΄λΈ” λ³€κ²½ (ALTER TABLE)

κΈ°μ‘΄ ν…Œμ΄λΈ”μ„ λ³€κ²½ν•˜λ €λ©΄ ALTER TABLE을 μ‚¬μš©ν•©λ‹ˆλ‹€.

βœ… 컬럼 μΆ”κ°€

ALTER TABLE employees ADD COLUMN email VARCHAR(100);

βœ… 컬럼 μ‚­μ œ

ALTER TABLE employees DROP COLUMN email;

βœ… 컬럼 데이터 νƒ€μž… λ³€κ²½

ALTER TABLE employees MODIFY COLUMN salary FLOAT;

βœ… κΈ°λ³Έκ°’ λ³€κ²½

ALTER TABLE employees ALTER COLUMN salary SET DEFAULT 50000;

3-4. ν…Œμ΄λΈ” μ‚­μ œ (DROP TABLE)

ν…Œμ΄λΈ”μ„ μ™„μ „νžˆ μ‚­μ œν•˜λ €λ©΄ DROP TABLE을 μ‚¬μš©ν•©λ‹ˆλ‹€.

⚠ 주의: DROP TABLE을 μ‹€ν–‰ν•˜λ©΄ ν…Œμ΄λΈ”κ³Ό 데이터가 μ™„μ „νžˆ μ‚­μ œλ©λ‹ˆλ‹€.

βœ… ν…Œμ΄λΈ” μ‚­μ œ

DROP TABLE employees;

3-5. ν…Œμ΄λΈ” 데이터 μ΄ˆκΈ°ν™” (TRUNCATE)

TRUNCATEλŠ” ν…Œμ΄λΈ”μ˜ λͺ¨λ“  데이터λ₯Ό μ‚­μ œν•˜μ§€λ§Œ ν…Œμ΄λΈ” κ΅¬μ‘°λŠ” μœ μ§€ν•©λ‹ˆλ‹€.

βœ… λͺ¨λ“  데이터 μ‚­μ œ (μ΄ˆκΈ°ν™”)

TRUNCATE TABLE employees;

⚠ DELETE FROM employees; 와 λ‹€λ₯΄κ²Œ TRUNCATEλŠ” 둀백이 λΆˆκ°€λŠ₯ν•©λ‹ˆλ‹€.


3-6. λ°μ΄ν„°λ² μ΄μŠ€ 관리

λ°μ΄ν„°λ² μ΄μŠ€ 자체λ₯Ό 생성, μˆ˜μ •, μ‚­μ œν•˜λŠ” 방법도 μ€‘μš”ν•©λ‹ˆλ‹€.

βœ… λ°μ΄ν„°λ² μ΄μŠ€ 생성

CREATE DATABASE company;

βœ… λ°μ΄ν„°λ² μ΄μŠ€ 확인

SHOW DATABASES;

βœ… νŠΉμ • λ°μ΄ν„°λ² μ΄μŠ€ μ‚¬μš©

USE company;

βœ… λ°μ΄ν„°λ² μ΄μŠ€ μ‚­μ œ

DROP DATABASE company;

제λͺ© μ—†μŒ

3-7. ν…Œμ΄λΈ” 데이터 μ΄ˆκΈ°ν™” (TRUNCATE)

TRUNCATEλŠ” ν…Œμ΄λΈ”μ˜ λͺ¨λ“  데이터λ₯Ό μ‚­μ œν•˜μ§€λ§Œ ν…Œμ΄λΈ” κ΅¬μ‘°λŠ” μœ μ§€ν•©λ‹ˆλ‹€.

βœ… λͺ¨λ“  데이터 μ‚­μ œ (μ΄ˆκΈ°ν™”)

-- μ™Έλž˜ ν‚€κ°€ μ„€μ •λœ 경우, TRUNCATE μ‹€ν–‰ λΆˆκ°€ (였λ₯˜ λ°œμƒ κ°€λŠ₯)
TRUNCATE TABLE employees;

πŸ“Œ ν•΄κ²° 방법: FOREIGN_KEY_CHECKSλ₯Ό λΉ„ν™œμ„±ν™” ν›„ μ‹€ν–‰

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE employees;
SET FOREIGN_KEY_CHECKS = 1;

πŸ“Œ FOREIGN_KEY_CHECKSλ₯Ό 0으둜 μ„€μ •ν•˜λ©΄ μ™Έλž˜ ν‚€ 무결성 검사λ₯Ό μΌμ‹œμ μœΌλ‘œ ν•΄μ œν•˜μ—¬ TRUNCATE μ‹€ν–‰ κ°€λŠ₯.

TRUNCATE vs DELETE 차이점

차이점 DELETE TRUNCATE
μ‹€ν–‰ 속도 느림 (각 행을 κ°œλ³„ μ‚­μ œ) 빠름 (ν…Œμ΄λΈ” 전체 μ΄ˆκΈ°ν™”)
νŠΈλžœμž­μ…˜ λ‘€λ°± βœ… κ°€λŠ₯ (TRANSACTION λ‚΄μ—μ„œ) ❌ λΆˆκ°€λŠ₯ (μ¦‰μ‹œ 반영)
AUTO_INCREMENT μ΄ˆκΈ°ν™” ❌ μœ μ§€λ¨ βœ… μ΄ˆκΈ°ν™”λ¨
μ™Έλž˜ ν‚€ μ œν•œ (FK) βœ… μ œν•œ μ—†μŒ ❌ FK μ„€μ • μ‹œ μ‹€ν–‰ λΆˆκ°€ (우회 ν•„μš”)

πŸ“Œ λŒ€λΆ€λΆ„μ˜ 경우 TRUNCATEκ°€ 더 λΉ λ₯΄μ§€λ§Œ, μ™Έλž˜ ν‚€ μ œμ•½ 쑰건이 μžˆλŠ” 경우 싀행이 μ œν•œλ  수 있음.


3-8. 인덱슀(Index)와 μ„±λŠ₯ μ΅œμ ν™”

μΈλ±μŠ€λŠ” 검색 속도λ₯Ό ν–₯μƒμ‹œν‚€κΈ° μœ„ν•΄ ν…Œμ΄λΈ”μ˜ νŠΉμ • μ»¬λŸΌμ— λŒ€ν•΄ μƒμ„±λ©λ‹ˆλ‹€.

βœ… κΈ°λ³Έ 인덱슀 생성

-- κΈ°λ³Έ 인덱슀 생성 (검색 속도 ν–₯상)
CREATE INDEX idx_department ON employees(department_id);

βœ… UNIQUE 인덱슀 생성

-- κΈ°λ³Έ 인덱슀 생성 (검색 속도 ν–₯상)
CREATE INDEX idx_department ON employees(department_id);

πŸ“Œ idx_email 인덱슀λ₯Ό μƒμ„±ν•˜λ©΄ email μ»¬λŸΌμ—μ„œ 쀑볡 κ°’ μž…λ ₯을 λ°©μ§€ν•  수 있음.

βœ… PRIMARY KEY와 UNIQUE INDEX 차이점

ꡬ뢄 PRIMARY KEY UNIQUE INDEX
쀑볡 ν—ˆμš© ❌ (μœ μΌν•΄μ•Ό 함) βœ… (쀑볡 κ°€λŠ₯, NULL κ°’ ν—ˆμš©)
NULL ν—ˆμš© ❌ (NULL λΆˆκ°€) βœ… (NULL κ°€λŠ₯)
ν•œ ν…Œμ΄λΈ” λ‚΄ 개수 1개만 κ°€λŠ₯ μ—¬λŸ¬ 개 κ°€λŠ₯

πŸ“Œ PRIMARY KEYλŠ” ν…Œμ΄λΈ”λ‹Ή ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•  수 있으며, NULL 값을 ν—ˆμš©ν•˜μ§€ μ•ŠμŒ.

πŸ“Œ UNIQUE INDEXλŠ” μ—¬λŸ¬ 개 생성 κ°€λŠ₯ν•˜λ©°, NULL 값을 κ°€μ§ˆ 수 있음.

βœ… FULLTEXT INDEX μΆ”κ°€

-- 전체 ν…μŠ€νŠΈ 검색 인덱슀 생성 (InnoDB 지원 κ°€λŠ₯)
CREATE FULLTEXT INDEX idx_description ON products(description);

πŸ“Œ FULLTEXT INDEXλ₯Ό μ‚¬μš©ν•˜λ©΄ MATCH()와 AGAINST()λ₯Ό ν™œμš©ν•œ 고속 검색 κ°€λŠ₯.

πŸ“Œ LIKE '%검색어%' 보닀 μ„±λŠ₯이 μš°μˆ˜ν•œ 검색을 μˆ˜ν–‰ν•  수 있음.

SELECT * FROM products WHERE MATCH(description) AGAINST('fast query');

βœ… 인덱슀 μ‚­μ œ

DROP INDEX idx_department ON employees;

βœ… 전체 인덱슀 확인

SHOW INDEX FROM employees;

3-9. νŒŒν‹°μ…”λ‹ (Partitioning)

νŒŒν‹°μ…”λ‹μ€ λŒ€μš©λŸ‰ 데이터λ₯Ό μ—¬λŸ¬ 개의 μž‘μ€ νŒŒν‹°μ…˜μœΌλ‘œ λΆ„ν• ν•˜μ—¬ κ΄€λ¦¬ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

MariaDBλŠ” RANGE, LIST, HASH λ“±μ˜ νŒŒν‹°μ…”λ‹μ„ μ§€μ›ν•©λ‹ˆλ‹€.

βœ… RANGE νŒŒν‹°μ…”λ‹ 예제

-- RANGE νŒŒν‹°μ…”λ‹ (연도별 데이터 λΆ„ν• )
CREATE TABLE sales (
    id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10,2),
    PRIMARY KEY (id, sale_date)
) PARTITION BY RANGE(YEAR(sale_date)) (
    PARTITION p1 VALUES LESS THAN (2022),
    PARTITION p2 VALUES LESS THAN (2023),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

πŸ“Œ 각 μ—°λ„λ³„λ‘œ 데이터λ₯Ό λΆ„ν• ν•˜μ—¬ μ €μž₯ν•˜μ—¬ νŠΉμ • 연도 쑰회 μ‹œ 속도가 ν–₯상됨.

βœ… LIST νŒŒν‹°μ…”λ‹

-- LIST νŒŒν‹°μ…”λ‹ (μ§€μ •λœ κ°’ 기반 λΆ„ν• )
CREATE TABLE employees (
    id INT NOT NULL,
    name VARCHAR(100),
    department VARCHAR(50),
    PRIMARY KEY (id, department)
) PARTITION BY LIST COLUMNS(department) (
    PARTITION p1 VALUES IN ('HR', 'Finance'),
    PARTITION p2 VALUES IN ('IT', 'Marketing')
);

πŸ“Œ LIST νŒŒν‹°μ…”λ‹μ€ νŠΉμ • 컬럼 값에 따라 데이터λ₯Ό λ‚˜λˆ„λŠ” λ°©μ‹μœΌλ‘œ, λ²”μœ„λ³΄λ‹€ λͺ…ν™•ν•œ 그룹으둜 λΆ„λ₯˜ν•  λ•Œ 유용.

βœ… HASH νŒŒν‹°μ…”λ‹

-- HASH νŒŒν‹°μ…”λ‹ (κ· λ“± λΆ„λ°°)
CREATE TABLE logs (
    id INT NOT NULL,
    log_message TEXT,
    PRIMARY KEY (id)
) PARTITION BY HASH(id) PARTITIONS 4;

πŸ“Œ HASH νŒŒν‹°μ…”λ‹μ€ νŠΉμ • κ°’μ˜ ν•΄μ‹œ 값을 κ³„μ‚°ν•˜μ—¬ κ· λ“±ν•˜κ²Œ 데이터λ₯Ό 배뢄함.

πŸ“Œ νŠΉμ • 컬럼 값이 νŠΉμ • λ²”μœ„μ— νŽΈμ€‘λ˜μ§€ μ•Šλ„λ‘ κ³ λ₯΄κ²Œ μ €μž₯ν•˜λŠ” 데 유용.

βœ… νŒŒν‹°μ…˜ 확인

SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'sales';

πŸ“Œ ν˜„μž¬ λ°μ΄ν„°λ² μ΄μŠ€ λ‚΄ sales ν…Œμ΄λΈ”μ˜ νŒŒν‹°μ…˜ 정보λ₯Ό 확인 κ°€λŠ₯.

βœ… νŒŒν‹°μ…˜ 확인

SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'sales';

3-10. ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€(TableSpace) 관리

MariaDBλŠ” 데이터λ₯Ό 물리적으둜 μ €μž₯ν•˜λŠ” ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€λ₯Ό 관리할 수 μžˆμŠ΅λ‹ˆλ‹€.

βœ… InnoDB ν…Œμ΄λΈ”μ„ νŠΉμ • ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€μ— μ €μž₯

-- ν…Œμ΄λΈ”μ„ νŠΉμ • ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€μ— μ €μž₯ (InnoDB μ „μš©)
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100)
) ENGINE=InnoDB
TABLESPACE ts1;

πŸ“Œ ν…Œμ΄λΈ”μ„ ts1 ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€μ— μ €μž₯ν•  수 있음.

πŸ“Œ ν•˜μ§€λ§Œ, MariaDBμ—μ„œλŠ” λŒ€λΆ€λΆ„μ˜ 경우 κΈ°λ³Έ ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€(innodb_file_per_table=1)λ₯Ό μ‚¬μš©ν•˜λ©°, μ‚¬μš©μž μ§€μ • ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€λŠ” 잘 μ‚¬μš©λ˜μ§€ μ•ŠμŒ.

βœ… ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€ λͺ©λ‘ 쑰회

SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES;

πŸ“Œ MariaDB의 λͺ¨λ“  ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€ 정보λ₯Ό 확인할 수 있음.

βœ… ν…Œμ΄λΈ”μŠ€νŽ˜μ΄μŠ€ λͺ©λ‘ 쑰회

SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES;

βœ… 정리