SQL에서 DML(Data Manipulation Language)은 데이터 조작 언어를 의미하며, 데이터베이스에 저장된 데이터를 조회, 삽입, 수정, 삭제하는데 사용하는 SQL 명령어들의 집합이다. 즉, 테이블
구조가 아니라 데이블 안의 데이터를 다루는 명령어들이다.
SELECT: 테이블에서 데이터를 조회INSERT: 테이블에 새로운 데이터 삽입UPDATE: 테이블의 기존 데이터를 수정DELETE: 테이블의 기존 데이터를 삭제SELECT *
FROM users;
SELECT name
FROM users
WHERE age = 20; -- 이처럼 조건을 붙여 조회할 수도 있다.
-- users 테이블에 한 명의 데이터를 추가한다
INSERT INTO users (name, age)
VALUES ('김기현', 24);
UPDATE users
SET age = age + 1;
모든 유저의 나이를 1 더한다.
DELETE
FROM users
WHERE name = '김기현';
이름이 김기현인 유저를 삭제한다.
| 특징 | 설명 |
|---|---|
| 트랜잭션 가능 | DML문은 COMMIT / ROLEBACK으로 작업을 확정하거나 취소할 수 있다 |
| WHERE 절이 중요하다 | UPDATE나 DELETE에서 WHERE 절을 빼면 전체 데이터가 수정 또는 삭제될 수 있으므로 주의해야 한다. |
| 테이블 구조를 변경하지 않는다 | 테이블의 구조를 변경하는 것은 DDL이다. |
SELECT문이 SQL에서 가장 중요하다고 여겨진다. 그 이유는 다음과 같은 이유가 있다.
SELECT는 읽기 전용 작업의 핵심 도구이며, 데이터 기반 의사결정의 시작점이다.
SELECT는 단순 조회만 아니라 조건검색, 정렬, 집계, 그룹화, 조인, 서브쿼리, 윈도우 함수 등 다양한 기능을 제공한다.
SELECT t.name, COUNT(u.id) AS team_count
FROM team t
JOIN users u ON t.id = u.team_id
GROUP BY t.name
ORDER BY team_count DESC;
위처럼 여러 테이블을 연결하고, 통계를 내고, 정렬하는 복잡한 분석도 모두 SELECT에서 수행한다.
SELECT는 데이터를 변경하지 않기 때문에 실수로 데이터를 잃을 위험이 없다.DELETE, UPDATE는 잘못 사용하면 복구 불가능한 실수를 할 수 있다.SELECT로 조회된다.SELECT는 성능 저하를 일으키고, 애플리케이션에 영향을 준다.데이터베이스에 새로운 데이터를 추가할 때 사용되는 언어이며, 실무와 시스템 설계에서 INSERT문이 중요한 점은 단순히 데이터를 넣는 것 이상으로 다양한 측면에서 영향을 주기 때문이다.
INSERT이다.삽입이 없으면 그 이후의 작업도 없다는 점에서 매우 중요하다.
데이터 삽입 시 아래와 같은 제약조건들이 처름으로 검증된다.
NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY잘못된 데이터가 삽입되지 않도록 첫 관문 역할을 한다.
-- 만약 중복된 값이 있다면 에러가 발생한다.
INSERT INTO users (email)
VALUES ('rlarlgus0206@naver.com');
INSERT INTO login_logs (user_id, login_time)
VALUES (1, NOW());
시스템 초기화, 마이그래이션, 외부 데이터 수집 등에서 수십만 건의 대량 INSERT가 발생한다. 그리고 아래와 같은 부분에서 문제가 발생할 수 있다.
수만 건의 데이터를 한 번에 삽입할 때 CPU, 메모리, 디스크, I/O 부하가 급격히 올라간다.
예를 들어 100만 건을 삽입하면 DB 서버가 느려지거나 애플리케이션 타임 아웃 그리고 다른 쿼리들이 느려지는 문제가 발생할 수 있다.
이를 해결하게 위해 삽입을 batch로 나누거나 비동기 큐, 백그라운드 작업 처리 시스템을 도입해야 한다.
많은 INSERT를 하나의 트랜잭션으로 처리하면 중간에 실패시 롤백 비용이 크고, 장시간 트랜잭션은 락을 오래 점유해서 다른 작업을 방해한다.
따라서 적절한 단위로 나눠서 커밋하거나, 중간 실패 대비 부분 커밋/재시도 로직이 필요하다.
INSERT를 할 때마다 인덱스를 동시에 업데이트 해야하기 때문에 대량으로 삽입할 시 인덱스가 많으면 속도가 급감할 수 있다.
따라서 대량 삽입 전 인덱스를 일시 비활성화 하거나, 데이터 입력 후 인덱스를 다시 생성해야 한다.
FOREIGN KEY, UNIQUE, NOT NULL같은 제약조건이 대량 데이터에 동시에 검사되며 제약 조건 출돌로 삽입 실패 가능성이 올라간다. 이를 해결하려면 입력 전 데이터를 정제하거나, 임시
staging 테이블에 넣고 검증 후 본 테이블로 이동하는 작업이 필요하다.
DB마다 십입 시 로그 기록, 트리거 실행이 있는데 대량으로 삽입할 때 로그가 폭발적으로 늘어나고 이느 디스크 공간 부족으로 이어지며 마스터-슬레이브 구조의 데이터베이스 복제를 지연시킨다.
이를 해결하려면 트리거를 최소화하거나 외부 처리 시스템으로 옮겨야 하고, 심도있게 고민하고 취할 수 있는 방법은 트리거/로그를 비활성화 하는 것이다(어지간하면 할 일은 없을 것이다).
대량 삽입은 단순 쿼리 한 줄 문제가 아니라, 시스템 전체 구조를 고려한 설계가 필요하다.
기존에 저장된 데이터를 수정하는데 사용되는 DML이며, 실무와 시스템 설계 측면에서 UPDATE는 데이터 무결성, 시스템 신뢰성, 성능, 보안 등에 배우 중요한 영향을 준다.
UPDATE users SET last_login = NOW();시스테므이 상태가 정확하게 유지되기 위해 UPDATE는 중요한 도구이다.
WHERE 조건 없이 UPDATE를 사용하면 전체 데이터가 잘못 수정될 위험이 있다.
UPDATE users
SET name = '김기현'
데이터 보호 및 정확성 유지를 위해 UPDATE는 신중하게 조건절을 사용해야 한다.
UPDATE는 트랜잭션 내에서 자주 사용되며, 일관된 상태를 만들기 위해 꼭 필요하다.BEGIN;
UPDATE users SET age = age + 1 WHERE id = 1;
UPDATE users SET age = age - 1 WHERE id = 2;
COMMIT;
이런 방식으로 시스템은 절대 중간 상태를 남기지 않고 일관성을 보장한다.
많은 시스템 로직이 단순 조회 뿐만 아니라 상태 변경에 집중된다. 이때 상태 변화를 수행하는 주요 수단이 UPDATE이다.
UPDATE로 인해 시스템이 오작동할 수 있다.BEFORE UPDATE트리거로 변경 전 데이터를 백업한다.UPDATE는 단순한 값 수정 이상의 비용을 가질 수 있다. 따라서 성능이 중요한 시스템에서는 UPDATE도 반드시 쿼리 튜닝 대상이 된다.
단순한 값 변경 뿐만 아니라 계산이나 조건에 따라 값을 수정할 수도 있다.
UPDATE users
SET age = age * 2
WHERE name = '김기현';
계산, 조건 분기, 날짜 변경 등 복잡한 비즈니스 로직을 처리하는 데 필수적이다.
| 팁 | 설명 |
|---|---|
WHERE절 확인 | UPDATE에 적용하기 전에 SELECT로 먼저 조건을 검증한다. |
| 트랜잭션 사용 | 여러 건 변경 시 BEGIN ~ COMMIT 사용 |
| 백업 또는 이력 기록 | 중요한 컬럼은 변경 전 기록 남기기 |
| 인덱스 고려 | WHERE조건이나 SET컬럼에 인덱스가 있으면 성능 영향이 크다 |
| 트리거 확인 | 자동 실행되는 트리거나 제약 조건이 있는지 사전에 확인한다 |
데이터베이스에서 기존의 데이터를 삭제할 때 사용된다. 데이터 무결성, 보안, 시스템 안정성에 매우 깊이 연관되어 있으며, 실무에서 가장 조심스럽게 다뤄야하는 명령어 중 하나이다.
DELETE는 실제 데이터 행을 제거한다.실무에서는 DELETE명령을 바로 실행하기보다는 백업, 트랜잭션, 보안 점검 후 실행해야 한다.
DELETE FROM users; -- 끔찍한 결과를 초래할 것
DELETE에서 WHERE 절을 생략하면 테이블 전체가 삭제되며, 재앙을 불러올 것이다.ON DELETE CASCAGE 또는 ON DELETE SET NULL 등을 명확하게 명시해 영향을 제어해야 한다.| 설명 | 논리 삭제 | 물리 삭제 |
|---|---|---|
| 특징 | is_deleted = true같은 플래그만 설정한다 | 실제 행을 DELETE로 제거한다 |
| 장점 | 복구 가능하며 이력 관리가 쉽다 | 공간이 절약되며, 쿼리가 간단하다 |
| 단점 | DB 용량이 증가하고, 쿼리 복잡도가 증가한다 | 복구가 불가능하고, 감시/추적이 어렵다 |
이러한 전략 선택이 DELETE의 핵심 설계 포인트이다.
DELETE는 법적 책임을 완수하는 핵심 역할을 한다.DELETE FROM users WHERE id = 1 AND consent_to_date_storage = false;
잘못된 삭제는 법적 리스크로 이어질 수 있다.
DELETE는 테이블 락, 인덱스 업데이트, 복제 지연 등을 유발한다.DELETE가 undo log에 기록되어 롤백 가능하긴 하지만, 성능에 큰 부담을 줄 수 있다.DELETE를 조건을 나눠서 여러 번 실행하거나 TRUNCATE, PARTITION DROP등 더 효율적인 대안을 사용한다.중요 테이블에서 DELETE가 일어날 경우 아래와 같은 후처리를 해주면 좋다.
-- 트리거
CREATE TRIGGER log_delete
BEFORE DELETE ON users
FOR EACH ROW
INSERT INTO delete_logs(user_id, deleted_at) VALUES (OLD.id, NOW());