๐ PostgreSQL ๊ธฐ๋ณธ โ ง - ์ ์์ ์์ ์๋ง์ ํ ์ด๋ธ ๋์์ธ
๐ PostgreSQL ๊ธฐ๋ณธ โ
ง - ์ ์์ ์์ ์๋ง์ ํ
์ด๋ธ ๋์์ธ
๐
ใ์ค์ฉ SQLใ
์ ์ฝ๊ณ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
๋ค์ด๋ฐ ์ปจ๋ฒค์ ๋ฐ๋ฅด๊ธฐ
- ์นด๋ฉ ์ผ์ด์ค, ํ์ค์นผ ์ผ์ด์ค, ์ค๋ค์ดํฌ ์ผ์ด์ค ๋ฑ ์ด๋ค ๊ท์น์ ์ ํธํ๋ ์คํ์ผ์ ์ ํํ๊ณ ์ผ๊ด๋๊ฒ ์ ์ฉํ๋ ๊ฒ์ด ์ค์ํ๋ค.
- ๋ฌด์๋ณด๋ค ์ํ ์กฐ์ง์ ์คํ์ผ ๊ฐ์ด๋๋ ์ปจ๋ฒค์ ์ ๋ฐ๋ฅด๋ ๊ฒ์ด ๊ฐ์ฅ ์ค์ํ๋ค.
์ธ์ฉ ์๋ณ์๋ก ๋์๋ฌธ์ ํผํฉ ์ฌ์ฉํ๊ธฐ
1
2
3
CREATE TABLE "Customers" (
-- ...
)
PostgreSQL
์ ๋์๋ฌธ์์ ๊ด๊ณ ์์ด ์๋ณ์๋ฅผ ์๋ฌธ์๋ก ์ฒ๋ฆฌํ๋ค.- ๋ง์ฝ ๋์๋ฌธ์๋ฅผ ํผํฉํ์ฌ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด ํฐ๋ฐ์ดํ๋ก ๊ฐ์ธ์ผ ํ๋ค.
์ธ์ฉ ์๋ณ์์ ํจ์
- ์ธ์ฉ ์๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด ๊ณต๋ฐฑ์ ํฌํจํ์ฌ ์์ฝ์ด ๋ฑ ํ์ฉ๋์ง ์์๋ ๋ฌธ์๋ ํ์ฉํ๊ฒ ๋๋ค.
- ๊ทธ๋ฌ๋ ์ด ๋ฌธ์ ์๋ ํฐ ํจ์ ์ด ์กด์ฌํ๋ค.
- ๋ชจ๋ ์ฌ์ฉ์๋ ์ดํ์ ๋ชจ๋ ์ด ์ฐธ์กฐ์ ํฐ๋ฐ์ดํ๋ฅผ ์ ๊ณตํด์ผ ํ๋ค.
- ๊ฐ๋ น ํฐ๋ฐ์ดํ๋ฅผ ์๋ตํ๋ฉด ํ์ฉ๋์ง ์์๋ ๋ฌธ์์ ๋ํด
SQL
์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. - ๊ฐ์ฅ ์ ๋ขฐํ ์ ์๋ ๋ฐฉ๋ฒ์
_
๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ด์ ์ค๋ค์ดํฌ ์ผ์ด์ค๋ฅผ ์ ํํ๋ ๊ฒ์ด๋ค.
์ด๋ฆ ์ง์ ์๋ณ์ ๊ฐ์ด๋๋ผ์ธ
- ์ค๋ค์ดํฌ ์ผ์ด์ค ์ฌ์ฉ
- ์ด๋ฆ์ ์ดํดํ๊ธฐ ์ฝ๊ฒ ์ง๊ณ ์ํธ ๊ฐ์ ์ฝ์ด ์ฌ์ฉ ์ง์
- ํ
์ด๋ธ ์ด๋ฆ์ผ๋ก๋ ๋ณต์ํ ์ฌ์ฉ
CSV
ํ์ผ์ ์ด๋ฆ์ ๋ณด์กดํ๊ธฐ ์ํด ํด๋น ํ์ผ์ ํ ์ด๋ธ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์์ธ ์ํฉ์ผ๋ก ๊ฐ์ฃผํ๋ค.
- ๊ธธ์ด๋ฅผ ์ ๊ฒฝ ์ฐ๊ธฐ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ฐ๋ผ ์๋ณ์ ์ด๋ฆ์ ํ์ฉ๋๋ ๊ธธ์ด ์๊ฐ ๋ค๋ฅด๋ค.
- ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฌ์ฉ๋ ์ ์๋ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ ๋ ์งง์ ์๋ณ์ ์ด๋ฆ์ด ๊ถ์ฅ๋๋ค.
- ํ
์ด๋ธ์ ๋ณต์ฌํ ๋ ๋์ค์ ๊ด๋ฆฌํ๋๋ฐ ๋์๋๋ ์ด๋ฆ์ ์ฌ์ฉํ๊ธฐ
- ํ ๊ฐ์ง ๋ฐฉ๋ฒ์
YYYY_MM_DD
ํ์์ ๋ ์ง๋ฅผ ํ ์ด๋ธ ์ด๋ฆ์ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค. - ์ด ๋ฐฉ์์ ํ ์ด๋ธ ์ด๋ฆ์ด ๋ ์ง ์์๋ก ์ ๋ ฌ๋๊ธฐ ๋๋ฌธ์ ๊ถ์ฅ๋๋ค.
- ํ ๊ฐ์ง ๋ฐฉ๋ฒ์
์ ์ฝ ์กฐ๊ฑด์ผ๋ก ์ด ๊ฐ ์ ์ดํ๊ธฐ
- ์ ์ฝ ์กฐ๊ฑด์ ์ฌ์ฉํ๋ฉด ํ์ง์ด ์ข์ง ์์ ๋ฐ์ดํฐ๋ก ์ธํด ๋ถ์์ด ๋ถ์ ํํ๊ฑฐ๋ ๋ถ์์ ํ ๊ฐ๋น์ง ์ธ, ๊ฐ๋น์ง ์์ ํ์์ ํผํ ์ ์๋ค.
- ๋ค์์
SQL
์ ์ ์ฝ ์กฐ๊ฑด ์ ํ์ด๋ค.
CHECK
: ์ ๊ณต๋ ๋ถ์ธ ํํ์์ดtrue
๋ก ํ๊ฐ๋๋ ํ๋ง ํ์ฉUNIQUE
: ์ด ๋๋ ์ด ๊ทธ๋ฃน์ ๊ฐ์ด ํ ์ด๋ธ์ ๊ฐ ํ์์ ๊ณ ์ ํ์ง ํ์ธNOT NULL
: ์ด์NULL
๊ฐ์ ๋ฐฉ์ง
๊ธฐ๋ณธ ํค: ์์ฐ ํค vs
์ธ์กฐ ํค
- ๊ธฐ๋ณธ ํค๋
SQL
์ ์ฝ ์กฐ๊ฑด์ผ๋ก ํค๋ฅผ ๊ตฌ์ฑํ๋ ์ด์ ๋ค์ ๊ท์น ๋ ๊ฐ์ง๋ฅผ ์ ์ฉํ๋ค.
- ๊ฐ ๊ฐ์ ํ๋ง๋ค ๊ณ ์ ํด์ผ ํ๋ค.
- ์ด์ ๊ฐ์ด ๋๋ฝ๋ ๋ถ๋ถ์ด ์์ด์๋ ์ ๋๋ค.
๊ธฐ์กด ์ด์ ์์ฐ ํค๋ก ์ฌ์ฉํ๊ธฐ
- ์์ฐ ํค๋ ํ ์ด๋ธ์ ์๋ ์ด ์ค์์ ๊ธฐ๋ณธ ํค์ ๊ธฐ์ค์ ์ถฉ์กฑํ๋ ์ด ๋๋ ์ด์ ์กฐํฉ์ ์ฌ์ฉํ๋ค.
- ์ฆ ํด๋น ์ด์ ๊ฐ์ ๋ชจ๋ ํ์ ๋ํด ๊ณ ์ ํ๊ณ ๋น์ด์์ง ์์์ผ ํ๋ค.
- ์ด์ ๊ฐ์ ์ ์ฝ ์กฐ๊ฑด์ ์๋ฐํ์ง ์๋๋ค๋ฉด ์ผ๋ง๋ ์ง ๋ณ๊ฒฝํ ์ ์๋ค.
์ธ์กฐ ํค๋ฅผ ์ํ ์ด ์์ฑ
- ์ธ์กฐ ํค๋ ์์์ ๊ฐ์ ๋ถ์ฌํ๋ค.
- ํ ์ด๋ธ์ ์์ฐ ๊ธฐ๋ณธ ํค๋ฅผ ์์ฑํ ์ ์๋ ๋ฐ์ดํฐ๊ฐ ์์ ๋ ์ฌ์ฉํ๋ค.
- ์ผ๋ถ ๊ฐ๋ฐ์๋
UUID
๋ฅผ ์ ํธํ๋๋ฐ, ์ฉ๋ ๋ฉด์์bigint
์ ๋นํด ๋นํจ์จ์ ์ด๋ฏ๋ก ์ ์ํด์ผ ํ๋ค.
ํค ์ ํ ๋ณ ์ฅ๋จ์
์์ฐ ํค
- ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ํ ์ด๋ธ์ ์์ผ๋ฏ๋ก, ํค ์์ฑ์ ์ํ ์ด์ ์ถ๊ฐํ ํ์๊ฐ ์๋ค.
- ์์ฐ ํค ์์ฒด๋ก๋ ์๋ฏธ๊ฐ ์์ผ๋ฏ๋ก, ์ฟผ๋ฆฌ ์ ํ ์ด๋ธ์ ์กฐ์ธํ ํ์์ฑ์ด ์ค์ด๋ ๋ค.
- ๋ฐ์ดํฐ๊ฐ ํค ์๊ตฌ ์ฌํญ์ ์๋ฐํ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝ๋๋ฉด ํ ์ด๋ธ ์ค์ ์ ๋ณ๊ฒฝํด์ผ ํจ
์ธ์กฐ ํค
- ๊ทธ ์์ฒด๋ก ์๋ฏธ๊ฐ ์๊ณ , ํด๋น ๊ฐ์ด ํ ์ด๋ธ์ ๋ฐ์ดํฐ์ ๋ ๋ฆฝ์ ์ด๊ธฐ ๋๋ฌธ์ ๋์ค์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋๋ผ๋ ํค ๊ตฌ์กฐ์ ์ ํ์ ๋ฐ์ง ์๋๋ค.
- ํค ๊ฐ์ ๊ณ ์ ํด์ผ ํ๋ค.
- ์ธ์กฐ ํค์ ๋ํ ์ด์ ์ถ๊ฐํ๋ ค๋ฉด ๊ณต๊ฐ์ด ๋ ํ์ํ๋ค.
์ ๋ฆฌ
- ๊ฐ์ฅ ์ด์์ ์ธ ํ ์ด๋ธ์ด๋ผ๋ฉด, ํ ์ด๋ธ์ ๊ณ ์ ํ ์ฝ๋์ ๊ฐ์ด ์์ฐ ํค๋ก ์ฌ์ฉํ ์ ์๋ ์ด์ด ํ๋ ์ด์ ์์ด์ผ ํ๋ค.
- ๊ทธ๋ฌ๋ ํ์ค ์ธ๊ณ์๋ ๋ ํ๊ณ๊ฐ ์๊ณ , ํ ์ด๋ธ ๊ตฌ์กฐ๋ฅผ ์ฌ๊ณ ํ ์ ์๋ ๊ฒฝ์ฐ ์ธ์กฐ ํค๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
๋จ์ผ ์ด ๊ธฐ๋ณธ ํค ์์ฑ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- ์ด ์ ์ฝ ์กฐ๊ฑด
CREATE TABLE natural_key_example (
license_id text CONSTRAINT license_key PRIMARY KEY,
first_name text,
last_name text
);
-- ํ
์ด๋ธ ์ ์ฝ ์กฐ๊ฑด
CREATE TABLE natural_key_example (
license_id text,
first_name text,
last_name text,
CONSTRAINT license_key PRIMARY KEY (license_id)
);
- ์ด ์ ์ฝ ์กฐ๊ฑด์ ์ค์ ํ ๋๋
CONSTRAINT
ํค์๋๋ฅผ ์๋ตํด๋ ๊ฐ๋จํ๊ฒ ๊ธฐ๋ณธ ํค๋ฅผ ์ค์ ํ ์ ์๋ค. - ์ด ๊ฒฝ์ฐ
PostgreSQL
์ ์์ฒด์ ์ผ๋ก ํ ์ด๋ธ ์ด๋ฆ ๋ค์_pkey
๋ฅผ ๋ถ์ฌ ๊ธฐ๋ณธ ํค์ ์ด๋ฆ์ ์ง์ ํ๋ค. - ๋ง์ฝ ๋ ์ด์์ ์ด์ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ ํค๋ฅผ ๋ง๋ค๋ ค๋ฉด ํ ์ด๋ธ ์ ์ฝ ์กฐ๊ฑด ๊ตฌ๋ฌธ์ ์ฌ์ฉํด์ผ ํ๋ค.
๋ณตํฉ ๊ธฐ๋ณธ ํค ์์ฑ
1
2
3
4
5
6
CREATE TABLE natural_key_composite_example (
student_id text,
school_day date,
present boolean,
CONSTRAINT student_key PRIMARY KEY (student_id, school_day)
);
1
2
SQL Error [23505]: ERROR: duplicate key value violates unique constraint "student_key"
Detail: Key (student_id, school_day)=(775, 2022-01-23) already exists.
- ์ค๋ณต๋ ๋ณตํฉ ํค๊ฐ ํฌํจ๋ ํ์ ์ฝ์ ํ๋ฉด ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
์๋ ์ฆ๊ฐ ์ธ์กฐ ํค ์์ฑ
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE surrogate_key_example (
order_number bigint GENERATED ALWAYS AS IDENTITY,
product_name text,
order_time timestamp with time zone,
CONSTRAINT order_number_key PRIMARY KEY (order_number)
);
INSERT INTO surrogate_key_example (product_name, order_time)
VALUES ('Beachball Polish', '2020-03-15 09:21-07'),
('Wrinkle De-Atomizer', '2017-05-22 14:00-07'),
('Flux Capacitor', '1985-10-26 01:18:00-07');
SELECT * FROM surrogate_key_example;
- ์ ์ฝ๋๋
IDENTITY
๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌorder_number
๋ผ๋ ์๋ ์ฆ๊ฐbigint
ํ์ ์ด์ ์ ์ธํ ํ, ํด๋น ์ด์ ๊ธฐ๋ณธ ํค๋ก ์ค์ ํ๋ค.
order_number | product_name | order_time |
---|---|---|
1 | Beachball Polish | 2020-03-16 01:21:00.000 +0900 |
2 | Wrinkle De-Atomizer | 2017-05-23 06:00:00.000 +0900 |
3 | Flux Capacitor | 1985-10-26 17:18:00.000 +0900 |
- ํ
์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ ๋๋
order_number
์ด์๋ ๊ฐ์ ์ง์ ํ์ง ์์๋ ๊ด์ฐฎ๋ค. - ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์๋์ผ๋ก ๊ธฐ์กด
ID
๊ฐ ์ค ๊ฐ์ฅ ํฐ ๊ฐ์ผ๋ก ์๋์ผ๋ก ์์ฑํด์ค๋ค. GENERATED ALWAYS AS IDENTITY
ํค์๋๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์ค์ ์ ๋ฌด์ํ๊ณ ๊ฐ์ ์ต์ง๋ก ์ฝ์ ํ๋ ํ์๋ฅผ ๋ฐฉ์งํ๋ ๊ฒ์ด ์ค์ํ๋ค.
1
2
3
4
5
6
7
8
INSERT INTO surrogate_key_example
OVERRIDING SYSTEM VALUE
VALUES (4, 'Chicken Coop', '2021-09-03 10:33-07');
ALTER TABLE surrogate_key_example ALTER COLUMN order_number RESTART WITH 5;
INSERT INTO surrogate_key_example (product_name, order_time)
VALUES ('Aloe Plant', '2020-03-15 10:09-07');
OVERRIDING SYSTEM VALUE
ํค์๋๋ฅผ ํตํดIDENTITY
์๋ ์ฝ์ ์ ํ์ฉํ ์ ์๋ค.- ๊ฐ๋ น ์ค์๋ก ์ญ์ ๋ ํ์ ์ฝ์ ํ๋ ๊ฒฝ์ฐ ์๋ ์ ๋ ฅ์ ํ์ฉํ ์๋ ์๋ค.
- ์ฝ์
ํ์๋ ์ํ์ค๋ฅผ ์ฌ์์ํ๋๋ก ์ค์ ํ์ฌ ๋ค์
ID
๊ฐ์ ์ค์ ํ ์ ์๋ค. - ์์ฃผ ์ฒ๋ฆฌํ ์์ ์ ์๋์ง๋ง ํ์ํ ๋๊ฐ ์์ผ๋ ๊ธฐ์ตํด๋์ด์ผ ํ๋ค.
์ธ๋ ํค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CREATE TABLE licenses (
license_id text,
first_name text,
last_name text,
CONSTRAINT licenses_key PRIMARY KEY (license_id)
);
CREATE TABLE registrations (
registration_id text,
registration_date timestamp with time zone,
license_id text REFERENCES licenses (license_id),
CONSTRAINT registration_key PRIMARY KEY (registration_id, license_id)
);
INSERT INTO licenses (license_id, first_name, last_name)
VALUES ('T229901', 'Steve', 'Rothery');
INSERT INTO registrations (registration_id, registration_date, license_id)
VALUES ('A203391', '2022-03-17', 'T229901');
INSERT INTO registrations (registration_id, registration_date, license_id)
VALUES ('A75772', '2022-03-17', 'T000001');
- ์ธ๋ ํค ์ ์ฝ ์กฐ๊ฑด์ ์ค์ ํ๊ธฐ ๋๋ฌธ์,
registrations
ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ ๋๋license_id
๊ฐ์ดlicenses
ํ ์ด๋ธ์ ์กด์ฌํ๋ ๊ฐ์ธ์ง ํ์ธํ๋ค. - ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ ์ฝ๋ ์ค ์ธ ๋ฒ์งธ
INSERT
๊ตฌ๋ฌธ์ ๋ค์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํจ๋ค.
1
2
SQL Error [23503]: ERROR: insert or update on table "registrations" violates foreign key constraint "registrations_license_id_fkey"
Detail: Key (license_id)=(T000001) is not present in table "licenses".
- ์ ์ค๋ฅ ๋ฉ์์ง๋ ๋ฐ์ดํฐ๋ฅผ ๊นจ๋ํ๊ฒ ์ ์งํ๊ณ ์์์ ๋ํ๋ด๊ธฐ๋ ํ๋ ๋ฐ๋ฉด, ๋ค์๊ณผ ๊ฐ์ ๋ช ๊ฐ์ง ์ค์ง์ ์ธ ์๋ฏธ๋ฅผ ๋ํ๋ธ๋ค.
- ์ธ๋ ํค๋ ๋ฐ์ดํฐ ์ฝ์ ์์์ ์ํฅ์ ์ค๋ค.
- ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋๋ ๊ทธ ๋ฐ๋๋ก ์ ์ฉ๋๋ค.
- 2๋ฒ์ ๋ํ ๋ถ์ฐ ์ค๋ช
์ ํ์๋ฉด, ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๊ธฐ ์ํด ์ธ๋ ํค ์ ์ฝ ์กฐ๊ฑด์
registrations
ํ ์ด๋ธ์์ ๊ด๋ จ ํ์ ์ ๊ฑฐํ๊ธฐ ์ ์licenses
ํ ์ด๋ธ์ ํ์ ์ ๊ฑฐํ์ง ๋ชปํ๋๋ก ํ๋ค. - ์ด๋ฐ ๊ฒฝ์ฐ
CASCADE
ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
CASCADE
๋ก ๊ด๋ จ ํ ์๋ ์ญ์ ํ๊ธฐ
1
2
3
4
5
6
CREATE TABLE registrations (
registration_id text,
registration_date timestamp with time zone,
license_id text REFERENCES licenses (license_id) ON DELETE CASCADE,
CONSTRAINT registration_key PRIMARY KEY (registration_id, license_id)
);
- ํ
์ด๋ธ์ ์ ์ฝ๋์ ๊ฐ์ด ์์ฑํ ๊ฒฝ์ฐ
licenses
ํ ์ด๋ธ์ ํ์ ์ญ์ ํ ๊ฒฝ์ฐ ๊ด๋ จ ํ ์ด๋ธ์ ๋ชจ๋ ๊ด๋ จ ํ์ด ํจ๊ป ์ญ์ ๋๋ค. registrations
ํ ์ด๋ธ์ ๊ณ ๋ฆฝ๋ ๋ฐ์ดํฐ๊ฐ ๋จ์ง ์๋๋ก ํ์ฌ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ค.
CHECK
์ ์ฝ ์กฐ๊ฑด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE check_constraint_example (
user_id bigint GENERATED ALWAYS AS IDENTITY,
user_role text,
salary numeric(10,2),
CONSTRAINT user_id_key PRIMARY KEY (user_id),
CONSTRAINT check_role_in_list CHECK (user_role IN('Admin', 'Staff')),
CONSTRAINT check_salary_not_below_zero CHECK (salary >= 0)
);
-- ์๋ ๋ ๋ช
๋ น์ด๋ ์คํ์ ์คํจ
INSERT INTO check_constraint_example (user_role)
VALUES ('admin');
INSERT INTO check_constraint_example (salary)
VALUES (-10000);
CHECK
์ ์ฝ ์กฐ๊ฑด์ ์ด์ ์ถ๊ฐ๋ ๋ฐ์ดํฐ๊ฐ ๋ ผ๋ฆฌ์ ํ ์คํธ๋ก ์ง์ ํ ์์ ๊ธฐ์ค์ ์ถฉ์กฑํ๋์ง ์ฌ๋ถ๋ฅผ ํ๊ฐํ๋ค.- ๊ธฐ์ค์ด ์ถฉ์กฑํ์ง ์์ผ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ค.
๊ฐ๋ฐ์๋ ๊ฒ์ฌ ๋ก์ง์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋์ง, ์์ฉ ํ๋ก๊ทธ๋จ์ ์๋์ง, ๋๋ ๋ ๋ค์ ์ํ๋์ง ํ ๋ก ํ ์ ์๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฒ์ฌ์ ํ ๊ฐ์ง ์ฅ์ ์ ์์ฉ ํ๋ก๊ทธ๋จ์ด ๋ณ๊ฒฝ๋ ํ์๋, ๊ทธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ์๋ก์ด ์์ฉ ํ๋ก๊ทธ๋จ์ด๋ ์ฌ์ฉ์๊ฐ ์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ค๋ ์ ์ด๋ค.
UNIQUE
์ ์ฝ ์กฐ๊ฑด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE TABLE unique_constraint_example (
contact_id bigint GENERATED ALWAYS AS IDENTITY,
first_name text,
last_name text,
email text,
CONSTRAINT contact_id_key PRIMARY KEY (contact_id),
CONSTRAINT email_unique UNIQUE (email)
);
INSERT INTO unique_constraint_example (first_name, last_name, email)
VALUES ('Samantha', 'Lee', 'slee@example.org');
INSERT INTO unique_constraint_example (first_name, last_name, email)
VALUES ('Betty', 'Diaz', 'bdiaz@example.org');
INSERT INTO unique_constraint_example (first_name, last_name, email)
VALUES ('Sasha', 'Lee', 'slee@example.org');
- ๊ธฐ๋ณธ ํค์ ๋์ผํ๊ฒ ๋ณด์ผ ์๋ ์์ง๋ง,
UNIQUE
์ ์ฝ ์กฐ๊ฑด์NULL
๊ฐ์ ํ์ฉํ๋ค. - ๋์ผํ ์ด๋ฉ์ผ์ด ํฌํจ๋ ํ์ ์ฝ์ ํ๋ ค๊ณ ํ๋ฉด ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
1
2
SQL Error [23505]: ERROR: duplicate key value violates unique constraint "email_unique"
Detail: Key (email)=(slee@example.org) already exists.
NOT NULL
์ ์ฝ ์กฐ๊ฑด
1
2
3
4
5
6
7
8
9
10
CREATE TABLE not_null_example (
student_id bigint GENERATED ALWAYS AS IDENTITY,
first_name text NOT NULL,
last_name text NOT NULL,
CONSTRAINT student_id_key PRIMARY KEY (student_id)
);
-- ์๋ ๋ช
๋ น์ด๋ ์คํ์ ์คํจ
INSERT INTO not_null_example (first_name, last_name)
VALUES ('Sting', NULL);
์ ์ฝ ์กฐ๊ฑด์ ์ ๊ฑฐํ๊ฑฐ๋ ๋์ค์ ์ถ๊ฐํ๊ธฐ
1
2
3
4
5
6
7
8
9
-- ํค ์ญ์
ALTER TABLE not_null_example DROP CONSTRAINT student_id_key;
-- ๊ธฐ๋ณธ ํค ์ถ๊ฐ
ALTER TABLE not_null_example ADD CONSTRAINT student_id_key PRIMARY KEY (student_id);
-- ์ด ์์
ALTER TABLE not_null_example ALTER COLUMN first_name DROP NOT NULL; -- ์ญ์
ALTER TABLE not_null_example ALTER COLUMN first_name SET NOT NULL; -- ์ถ๊ฐ
- ๋์ ์ด ๋ฐ์ดํฐ๊ฐ ์ ์ฝ ์กฐ๊ฑด์ ์ ํ์ ๋ฐ๋ฅด๋ ๊ฒฝ์ฐ์๋ง ๊ธฐ์กด ํ ์ด๋ธ์ ์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์๋ค.
- ์๋ฅผ ๋ค์ด ๊ฐ์ด ์ค๋ณต๋๊ฑฐ๋ ๋น์ด ์๋ ์ด์๋ ๊ธฐ๋ณธ ํค ์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์๋ค.
์ธ๋ฑ์ค๋ก ์ฟผ๋ฆฌ ์๋ ํฅ์์ํค๊ธฐ
- ์ฑ ์ ๋ชฉ์ฐจ์ฒ๋ผ, ํ ์ด๋ธ์์๋ ํ๋ ์ด์์ ์ด์ ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ์ฌ ์ฟผ๋ฆฌ ์๋๋ฅผ ๋์ผ ์ ์๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ ์ํด ๊ฐ ํ์ ์ค์บํ๋ ๋์ ์ธ๋ฑ์ค๋ฅผ ๋ฐ๋ก ๊ฐ๊ธฐ๋ก ์ฌ์ฉํ๋ค.
- ์ด๋ ์ฌ์ํ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง
SQL
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฝค ์ค์ํ ์ฃผ์ ์ด๋ค.
B-Tree
: PostgreSQL
์ ๊ธฐ๋ณธ ์ธ๋ฑ์ค
- ์ด๋ฏธ ์๊ฒ ๋ชจ๋ฅด๊ฒ ์ฌ๋ฌ ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค์ด ๋ณด์๋ค.
- ๊ฐ๋ น ๊ธฐ๋ณธ ํค๋ฅผ ์ถ๊ฐํ๊ฑฐ๋,
UNIQUE
์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํ ๋๋ง๋ค ์ ์ฝ ์กฐ๊ฑด์ ํฌํจ๋ ์ด์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ค. PostgreSQL
์ ๊ธฐ๋ณธ ์ธ๋ฑ์ค ์ ํ์B-Tree
์ธ๋ฑ์ค์ด๋ค.- ๊ธฐ๋ณธ ํค๋ฅผ ์ถ๊ฐํ๊ฑฐ๋,
UNIQUE
์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํ ๋,CREATE INDEX
๋ฌธ์ ์คํํ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ๋๋ ์ ํ์ด๋ค. B-Tree
๋ ๊ท ํ ์กํ ํธ๋ฆฌ์ ์ฝ์๋ก, ๊ฐ ๊ฒ์ ์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ ๋๊น์ง ๋ถ๊ธฐ๋ฅผ ํตํด ํธ๋ฆฌ์ ๋งจ ์์์๋ถํฐ ์๋๋ก ๋ด๋ ค๋ค๋ณด๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์ฑํ๋ค.B-Tree
์ธ๋ฑ์ค๋ ๋ถ๋ฑํธ, ๋ฑํธ,BETWEEN
๊ณผ ๊ฐ์ ๋๋ฑ ๋ฐ ๋ฒ์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ ฌํ๊ณ ๊ฒ์ํ ์ ์๋ ๋ฐ์ดํฐ์ ์ ์ฉํ๋ค.WHERE chips LIKE 'Dorito%'
์ฒ๋ผ ๊ฒ์ ๋ฌธ์์ด์ ์์ ๋ถ๋ถ ํจํด์ ์์ผ๋ ์นด๋๊ฐ ์๋ ๊ฒฝ์ฐ์๋LIKE
์ ํจ๊ป ์๋ํ๋ค.PostgreSQL
์GIN
,GiST
๋ฅผ ๋น๋กฏํ ์ถ๊ฐ ์ธ๋ฑ์ค ์ ํ์ ํตํฉํ๋ค.- ๊ฐ๊ฐ์ ๊ณ ์ ํ ์ฉ๋๋ฅผ ๊ฐ๊ณ ์๋๋ฐ, ํ๋ฐ๋ถ ์ฅ์์ ๋ค๋ฃฐ ์์ ์ด๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE new_york_addresses (
longitude numeric(9,6),
latitude numeric(9,6),
street_number text,
street text,
unit text,
postcode text,
id integer CONSTRAINT new_york_key PRIMARY KEY
);
COPY new_york_addresses
FROM 'C:\YourDirectory\city_of_new_york.csv'
WITH (FORMAT CSV, HEADER);
- ์ธ๋ฑ์ค๋ฅผ ํ์ธํ๊ธฐ ์ํด ์ฐ์ ํ ์ด๋ธ์ ์์ฑํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ค.
EXPLAIN
์ผ๋ก ์ฟผ๋ฆฌ ์ฑ๋ฅ ๋ฒค์น๋งํนํ๊ธฐ
EXPLAIN
์PostgreSQL
์์๋ง ์ง์ํ๋ ๊ฒ์ ์๋์ง๋ง, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ณ๋ก ์ต์ ๋ฐ ์ถ๋ ฅ ํฌ๋งท์ด ๋ชจ๋ ๋ค๋ฅด๋ค.- ํด๋น ๋ช ๋ น์ ์ฌ์ฉํ๋ฉด ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ์ค์ผ๋ก ์ฟผ๋ฆฌ์ ๋ํ ์ค์บ ๊ณํ, ์ธ๋ฑ์ค ์ฌ์ฉ ์ฌ๋ถ ๋ฑ์ด ํฌํจ๋๋ค.
ANALYZE
ํค์๋๋ฅผ ์ถ๊ฐํ๋ฉดEXPLAIN
์ด ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ณ ์ค์ ์คํ ์๊ฐ์ ํ์ํ๋ค.
์ ์ด ์คํ ์๊ฐ ๊ธฐ๋กํ๊ธฐ
1
2
3
4
5
6
7
8
EXPLAIN ANALYZE SELECT * FROM new_york_addresses
WHERE street = 'BROADWAY';
EXPLAIN ANALYZE SELECT * FROM new_york_addresses
WHERE street = '52 STREET';
EXPLAIN ANALYZE SELECT * FROM new_york_addresses
WHERE street = 'ZWICKY AVENUE';
- ์ ๋ช ๋ น์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋๋ก ์ง์ํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ๋์ ์ฟผ๋ฆฌ ํ๋ก์ธ์ค ๋ฐ ์คํ์ ๊ฑธ๋ฆฐ ์๊ฐ์ ๋ํ ํต๊ณ๋ฅผ ํ์ํ๋ค.
1
2
3
4
5
6
7
8
Gather (cost=1000.00..15285.68 rows=3479 width=46) (actual time=19.869..436.569 rows=3336 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on new_york_addresses (cost=0.00..13937.78 rows=1450 width=46) (actual time=2.471..404.527 rows=1112 loops=3)
Filter: (street = 'BROADWAY'::text)
Rows Removed by Filter: 312346
Planning Time: 11.520 ms
Execution Time: 437.598 ms
- ์ฒซ ๋ฒ์งธ ์ฟผ๋ฆฌ์ ๋ํ ์คํ ๊ณํ์ผ๋ก, ๋ค์๊ณผ ๊ฐ์ด ํด์ํ ์ ์๋ค.
street = "BROADWAY"
์ธ ํ์ ์ฐพ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ํ ์ด๋ธ์ ์์ฐจ์ ์ค์บ์ ์ํํจ์ ๋ํ๋ธ๋ค.- ์ด๋ ์ ์ฒด ํ ์ด๋ธ ์ค์บ์ ๋์์ด์ด๋ค.
- ๊ฐ ํ์ด ๊ฒ์๋๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค๋
"BROADWAY"
์ ์ผ์นํ์ง ์๋ ํ์ ๊ฒฐ๊ณผ์์ ์ ๊ฑฐํ๋ค.
- ์คํ์ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์ ์ ์๋ค.
- ์ด๋ ํ๋์จ์ด ์ฑ๋ฅ ๋ฐ ๋ค์ํ ์์ธ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋ํ๋ ์ ์๋ค.
- ํ ์คํธ๋ฅผ ์ํด ์ฟผ๋ฆฌ๋ฅผ ๊ฐ์ ์ฌ๋ฌ ๋ฒ ์คํํ๊ณ , ๊ฐ๊ฐ ๊ฐ์ฅ ๋น ๋ฅธ ์๊ฐ์ ๊ธฐ๋กํด์ผ ํ๋ค.
- ์๋ฒ์์ ์คํ ์ค์ธ ๋ค๋ฅธ ํ๋ก์ธ์ค๋ ์์ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ ๋ฑ์ ์์ธ์ผ๋ก ๋์ผํ ์ฟผ๋ฆฌ์์๋ ์คํ ์๊ฐ์ ์คํํ ๋๋ง๋ค ์ฝ๊ฐ์ฉ ๋ค๋ฅด๋ค.
์ธ๋ฑ์ค ์ถ๊ฐํ๊ธฐ
1
CREATE INDEX street_idx ON new_york_addresses (street);
- ์ ๋ช ๋ น์ด๋ก ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๊ณ , ๋ค์ ์คํ ๊ณํ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
1
2
3
4
5
6
7
Bitmap Heap Scan on new_york_addresses (cost=43.39..6785.34 rows=3479 width=46) (actual time=0.768..3.071 rows=3336 loops=1)
Recheck Cond: (street = 'BROADWAY'::text)
Heap Blocks: exact=2152
-> Bitmap Index Scan on street_idx (cost=0.00..42.52 rows=3479 width=0) (actual time=0.376..0.377 rows=3336 loops=1)
Index Cond: (street = 'BROADWAY'::text)
Planning Time: 0.087 ms
Execution Time: 3.235 ms
- ๋ ๊ฐ์ง ํฐ ๋ณํ๊ฐ ์๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๊ฐ ํ์ ์์ฐจ ์ค์บํ๋ ๋์
street_idx
์์ ์ธ๋ฑ์ค ์ค์บ์ ์ฌ์ฉํ๊ณ ์์์ ๋ณด์ฌ์ค๋ค. - ์ฟผ๋ฆฌ ์๋๊ฐ ํ์ ํ ๋นจ๋ผ์ก๋ค.
- ๋ฐ๋ณต์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋ฐ์ดํฐ์์ ๋ต์ ์ฐพ๊ฑฐ๋, ์์ฒ ๋ช ์ ์ฌ์ฉ์๋ฅผ ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ ์ ๊ตฌ์ถํ ๋ ์๊ฐ์ ์ ์ฝํ ์ ์๋ค.
- ์ฌ๋ฌ ์ธ๋ฑ์ค ์ ํ์ ์ฑ๋ฅ์ ํ ์คํธํ๋ ๊ฒฝ์ฐ์ ๊ฐ์ด ํ ์ด๋ธ์์ ์ธ๋ฑ์ค๋ฅผ ์ ๊ฑฐํด์ผ ํ๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด ๋๋ค.
1
DROP INDEX street_idx;
์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ๋ ์๊ฐํ ์
- ์ธ๋ฑ์ค๊ฐ ์ฑ๋ฅ ํฅ์์ ํฐ ์ฅ์ ์ ๊ฐ๊ณ ์๋ค๋ ๊ฒ์ ํ์ธํ๋ค.
- ๊ทธ๋ ๋ค๋ฉด ํ ์ด๋ธ์ ๋ชจ๋ ์ด์ ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํด์ผ ํ ๊น?
- ๊ทธ๊ฒ์ ์๋๋ค.
- ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํฌ๊ธฐ๊ฐ ์ปค์ง๊ณ , ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ ๋ฐ ์ ์ง ๊ด๋ฆฌ ๋น์ฉ์ด ๋ ๋ค.
- ๋ค์์ ์ธ๋ฑ์ค๋ฅผ ์ธ์ ์ฌ์ฉํ๋ฉด ์ข์์ง ํ๋จํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ๊ธฐ์ค์ด๋ค.
- ์ฌ์ฉ ๊ฐ๋ฅํ ์ธ๋ฑ์ค ์ข
๋ฅ์ ํน์ ๋ฐ์ดํฐ ํ์
์์ ์ฌ์ฉํ ์ธ๋ฑ์ค์ ๋ํด ์์๋ณด๋ ค๋ฉด ์ฌ์ฉ ์ค์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ์์ ๋ํ ๋ฌธ์๋ฅผ ์ฝ์ด ๋ณด๋ผ.
- ์๋ฅผ ๋ค์ด
PostgreSQL
์๋B-Tree
์ธ์๋ ๋ค์ฏ ๊ฐ์ ์ธ๋ฑ์ค ์ ํ์ด ๋ ์กด์ฌํ๋ค.
- ์๋ฅผ ๋ค์ด
- ํ
์ด๋ธ ์กฐ์ธ์ ์ฌ์ฉํ ์ด์ ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข๋ค.
- ๊ธฐ๋ณธ ํค๋
PostgreSQL
์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ๋ฑ์ฑ๋์ง๋ง, ๊ด๋ จ ํ ์ด๋ธ์ ์ธ๋ ํค ์ด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ๋ฑ์ฑ๋์ง ์์ผ๋ฏ๋ก ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๊ธฐ ์ข์ ๋์์ด๋ค.
- ๊ธฐ๋ณธ ํค๋
- ์ธ๋ ํค์ ๋ํ ์ธ๋ฑ์ค๋ ์ฐ์ ์ญ์ (
CASCADING DELETE
) ๋์ ๊ฐ๋น์ผ ์์ฐจ ์ค์บ์ ํผํ๋ ๋ฐ ๋์์ด ๋๋ค. WHERE
์ ์ ์์ฃผ ์ฌ์ฉ๋๋ ์ด์ ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๋ฉด ์ฑ๋ฅ์ด ํฌ๊ฒ ํฅ์๋๋ค.EXPLAIN ANALYZE
ํค์๋๋ฅผ ํตํด ๋ค์ํ ๊ตฌ์ฑ์์ ์ฑ๋ฅ์ ํ ์คํธํ์.- ์ต์ ํ๋ ๊ณผ์ ์ด๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๊ธฐ๋ณธ ํค ๋๋ ๊ธฐํ ์ ์ฝ ์กฐ๊ฑด์ ๋ฐฑ์ ํ์ง ์๋๋ค๋ฉด, ์ธ๋ฑ์ค๋ฅผ ์ญ์ ํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์ฝ์ , ์ ๋ฐ์ดํธ, ์ญ์ ์๋๋ฅผ ๋์ผ ์ ์๋ค.
This post is licensed under CC BY 4.0 by the author.