[Daily morning study] PostgreSQL vs MySQL ๋น„๊ต

#daily morning study

Image


์™œ ๋‘˜์„ ๋น„๊ตํ•˜๋Š”๊ฐ€

์˜คํ”ˆ์†Œ์Šค RDBMS ์‹œ์žฅ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ด๋Š” ๋‘ DB๊ฐ€ MySQL๊ณผ PostgreSQL์ด๋‹ค. MySQL์€ ์›น ์„œ๋น„์Šค ์ดˆ์ฐฝ๊ธฐ๋ถ€ํ„ฐ LAMP ์Šคํƒ์˜ ํ•œ ์ถ•์„ ๋‹ด๋‹นํ–ˆ๊ณ , PostgreSQL(์ดํ•˜ Postgres)์€ โ€œ๊ฐ€์žฅ ๊ธฐ๋Šฅ์ด ํ’๋ถ€ํ•œ ์˜คํ”ˆ์†Œ์Šค DBโ€๋ฅผ ๋ชฉํ‘œ๋กœ ๋ฐœ์ „ํ•ด์™”๋‹ค. ๋ฌด์—‡์„ ์„ ํƒํ•˜๋А๋ƒ๋Š” ๋‹จ์ˆœํ•œ ์ทจํ–ฅ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ํŠธ๋žœ์žญ์…˜ ๋™์‹œ์„ฑ, ๋ฐ์ดํ„ฐ ํƒ€์ž… ์š”๊ตฌ์‚ฌํ•ญ, ํ™•์žฅ์„ฑ, ๋ผ์ด์„ ์Šค ๋“ฑ ์‹ค์งˆ์ ์ธ ์ฐจ์ด์—์„œ ๋น„๋กฏ๋œ๋‹ค.


์•„ํ‚คํ…์ฒ˜ ์ฐจ์ด

MySQL์˜ ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„ ๊ตฌ์กฐ

MySQL์€ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐ€๋Šฅํ•œ ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„ ๊ตฌ์กฐ๋ฅผ ๊ฐ–๋Š”๋‹ค. ์ฟผ๋ฆฌ ๋ ˆ์ด์–ด์™€ ์Šคํ† ๋ฆฌ์ง€ ๋ ˆ์ด์–ด๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด, ๊ฐ™์€ SQL๋กœ InnoDB, MyISAM, Memory, CSV ๋“ฑ ๋‹ค๋ฅธ ์—”์ง„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • InnoDB โ€” ๊ธฐ๋ณธ ์—”์ง„. ํŠธ๋žœ์žญ์…˜, ์™ธ๋ž˜ํ‚ค, Row-level locking ์ง€์›
  • MyISAM โ€” ํŠธ๋žœ์žญ์…˜ ์—†์Œ, Table-level locking. ์ฝ๊ธฐ ์ง‘์•ฝ์  ๋ ˆ๊ฑฐ์‹œ์— ์‚ฌ์šฉ
  • ํ˜„๋Œ€ MySQL์—์„œ๋Š” ๊ฑฐ์˜ InnoDB๋งŒ ์“ด๋‹ค๊ณ  ๋ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค

PostgreSQL์˜ ๋‹จ์ผ ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„

Postgres๋Š” ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„์ด ํ•˜๋‚˜๋‹ค. ๋Œ€์‹  ํ…Œ์ด๋ธ” ์•ก์„ธ์Šค ๋ฉ”์„œ๋“œ(Table Access Method) API๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€ ์—”์ง„์„ ๋ถ™์ผ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ(pg17 ์ดํ›„ ํ™•์žฅ ์˜ˆ์ •)๊ฐ€ ์žˆ์ง€๋งŒ ์‹ค์šฉ์ ์œผ๋กœ๋Š” ๊ธฐ๋ณธ heap ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋ณต์žก์„ฑ ๋Œ€์‹  ์‹ฌ์ธต์ ์ธ ๊ธฐ๋Šฅ ํ†ตํ•ฉ์— ์ง‘์ค‘ํ–ˆ๋‹ค.


MVCC ๊ตฌํ˜„ ๋ฐฉ์‹

๋‘ DB ๋ชจ๋‘ MVCC(Multi-Version Concurrency Control)๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ฐฉ์‹์ด ๋‹ค๋ฅด๋‹ค.

MySQL InnoDB์˜ MVCC

Undo ๋กœ๊ทธ ๊ธฐ๋ฐ˜. ํ–‰์„ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ์ด์ „ ๋ฒ„์ „์„ undo ๋กœ๊ทธ์— ๋ณด๊ด€ํ•˜๊ณ  ์›๋ณธ ํ–‰์„ ์ƒˆ ๊ฐ’์œผ๋กœ ๋ฎ์–ด์“ด๋‹ค. ์˜ค๋ž˜๋œ ๋ฒ„์ „์ด ํ•„์š”ํ•œ ํŠธ๋žœ์žญ์…˜์€ undo ๋กœ๊ทธ๋ฅผ ์—ญ์ถ”์ ํ•œ๋‹ค.

ํ–‰ ์—…๋ฐ์ดํŠธ ์ „: [ data=old | txn_id=100 | roll_pointer โ†’ undo_log ]
ํ–‰ ์—…๋ฐ์ดํŠธ ํ›„: [ data=new | txn_id=200 | roll_pointer โ†’ old_version ]
                                               โ†“
                                           undo_log: old_version ๋ณด๊ด€

์žฅ๊ธฐ ํŠธ๋žœ์žญ์…˜์ด ์žˆ์œผ๋ฉด undo ๋กœ๊ทธ๊ฐ€ ์Œ“์—ฌ undo tablespace ๋ถ€๋‹ด์ด ์ปค์ง„๋‹ค.

PostgreSQL์˜ MVCC

Postgres๋Š” ํ–‰ ์ž์ฒด์— ์—ฌ๋Ÿฌ ๋ฒ„์ „์„ ํ…Œ์ด๋ธ” ๋‚ด๋ถ€์— ์ €์žฅํ•œ๋‹ค (Heap tuple versioning). ์—…๋ฐ์ดํŠธํ•˜๋ฉด ์ƒˆ ํŠœํ”Œ์„ ํ…Œ์ด๋ธ”์— INSERTํ•˜๊ณ  ์ด์ „ ํŠœํ”Œ์˜ xmax๋ฅผ ์„ค์ •ํ•ด ์‚ญ์ œ ํ‘œ์‹œํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ์ „:  [ xmin=100, xmax=0,   data=old ]  โ† ์‚ด์•„์žˆ๋Š” ํŠœํ”Œ
์—…๋ฐ์ดํŠธ ํ›„:  [ xmin=100, xmax=200, data=old ]  โ† ์ฃฝ์€ ํŠœํ”Œ (xmax ์„ค์ •๋จ)
              [ xmin=200, xmax=0,   data=new ]  โ† ์ƒˆ ํŠœํ”Œ

์ฃฝ์€ ํŠœํ”Œ์€ VACUUM ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‚˜์ค‘์— ํšŒ์ˆ˜ํ•œ๋‹ค. VACUUM์ด ์ œ๋•Œ ๋Œ์ง€ ์•Š์œผ๋ฉด ํ…Œ์ด๋ธ” bloat์ด ์ƒ๊ธด๋‹ค.

ํ•ญ๋ชฉMySQL InnoDBPostgreSQL
๊ตฌ๋ฒ„์ „ ๋ณด๊ด€ ์œ„์น˜Undo ๋กœ๊ทธํ…Œ์ด๋ธ” ๋‚ด๋ถ€ (dead tuple)
์ •๋ฆฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜Purge threadVACUUM
์žฅ๊ธฐ ํŠธ๋žœ์žญ์…˜ ์˜ํ–ฅundo log ์ฆ๊ฐ€table bloat

ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€

๊ฒฉ๋ฆฌ ์ˆ˜์ค€MySQL InnoDBPostgreSQL
READ UNCOMMITTED์ง€์›์—†์Œ (READ COMMITTED๋กœ ์ฒ˜๋ฆฌ)
READ COMMITTED์ง€์›์ง€์›
REPEATABLE READ๊ธฐ๋ณธ๊ฐ’, Gap Lock์œผ๋กœ Phantom Read ๋ฐฉ์ง€์ง€์›
SERIALIZABLE์ง€์›์ง€์› (SSI ๊ตฌํ˜„)

Postgres์˜ SSI(Serializable Snapshot Isolation)๋Š” ์ž ๊ธˆ ์—†์ด ์ง๋ ฌํ™” ๊ฐ€๋Šฅ์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ๊ธฐ๋ฒ•์œผ๋กœ, ์ฝ๊ธฐ๊ฐ€ ๋งŽ์€ OLTP์—์„œ ์„ฑ๋Šฅ ์ด์ ์ด ์žˆ๋‹ค.

MySQL์˜ REPEATABLE READ์—์„œ Gap Lock์€ ํŠธ๋žœ์žญ์…˜ ๊ฐ„ ๊ต์ฐฉ(Deadlock)์„ ์œ ๋ฐœํ•˜๊ธฐ ์‰ฝ๋‹ค. ๊ณ ๋„๋กœ ๋™์‹œ์ ์ธ ์“ฐ๊ธฐ ์›Œํฌ๋กœ๋“œ์—์„œ ์ž ๊ธˆ ๊ฒฝํ•ฉ ๋ฌธ์ œ๊ฐ€ ์ž์ฃผ ๋ฐœ์ƒํ•œ๋‹ค.


๋ฐ์ดํ„ฐ ํƒ€์ž…๊ณผ ํ™•์žฅ์„ฑ

PostgreSQL์ด ์ œ๊ณตํ•˜๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด ํ›จ์”ฌ ํ’๋ถ€ํ•˜๋‹ค.

ํƒ€์ž…MySQLPostgreSQL
JSONJSON, JSON_TABLE (8.0+)JSON, JSONB (์ธ๋ฑ์‹ฑ ๊ฐ€๋Šฅ)
๋ฐฐ์—ด์—†์Œinteger[], text[] ๋“ฑ ๊ธฐ๋ณธ ์ง€์›
๋ฒ”์œ„์—†์Œint4range, tsrange ๋“ฑ
UUIDVARCHAR๋กœ ์ €์žฅ์ „์šฉ UUID ํƒ€์ž…
๊ธฐํ•˜/๊ณต๊ฐ„๊ธฐ๋ณธ GeometryPostGIS ํ™•์žฅ์œผ๋กœ ์ •๋ฐ€ GIS
์ „๋ฌธ ๊ฒ€์ƒ‰FULLTEXT ์ธ๋ฑ์Šคtsvector, tsquery, GIN ์ธ๋ฑ์Šค
์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…ENUM, SET ์ •๋„CREATE TYPE, ๋ณตํ•ฉ ํƒ€์ž…, ๋„๋ฉ”์ธ

Postgres์—์„œ JSONB๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท์œผ๋กœ ์ €์žฅ๋˜์–ด ํŒŒ์‹ฑ ์—†์ด ์ธ๋ฑ์‹ฑํ•  ์ˆ˜ ์žˆ๋‹ค. MongoDB ๋Œ€์‹  PostgreSQL๋กœ JSON ์ค‘์‹ฌ ์„œ๋น„์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ์‚ฌ๋ก€๊ฐ€ ๋งŽ์€ ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ์— ์žˆ๋‹ค.


์ธ๋ฑ์Šค ์ข…๋ฅ˜

PostgreSQL์€ ์ธ๋ฑ์Šค ์„ ํƒ์ง€๊ฐ€ ๋‹ค์–‘ํ•˜๋‹ค.

์ธ๋ฑ์Šค ํƒ€์ž…MySQLPostgreSQL
B-TreeOO
HashO (์ œํ•œ์ )O
GiSTXO (๊ธฐํ•˜, ๋ฒ”์œ„, ์ „๋ฌธ๊ฒ€์ƒ‰)
GINXO (๋ฐฐ์—ด, JSONB, ์ „๋ฌธ๊ฒ€์ƒ‰)
BRINXO (๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ •๋ ฌ๋œ ๋Œ€์šฉ๋Ÿ‰ ํ…Œ์ด๋ธ”)
๋ถ€๋ถ„ ์ธ๋ฑ์ŠคXO (WHERE ์กฐ๊ฑด๋ถ€ ์ธ๋ฑ์Šค)
ํ‘œํ˜„์‹ ์ธ๋ฑ์Šคํ•จ์ˆ˜ ์ธ๋ฑ์Šค(์ œํ•œ์ )O (lower(email) ๋“ฑ)

๋ถ€๋ถ„ ์ธ๋ฑ์Šค(Partial Index) ์˜ˆ์‹œ:

-- ํ™œ์„ฑ ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ์ธ๋ฑ์Šค๋งŒ ์ƒ์„ฑ
CREATE INDEX idx_active_users ON users (email)
WHERE is_active = TRUE;

๋น„ํ™œ์„ฑ ์‚ฌ์šฉ์ž๊ฐ€ ๋งŽ๋‹ค๋ฉด ์ธ๋ฑ์Šค ํฌ๊ธฐ๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.


๋ณต์ œ์™€ ๊ณ ๊ฐ€์šฉ์„ฑ

MySQL ๋ณต์ œ

  • Binary Log ๊ธฐ๋ฐ˜ ๋ณต์ œ: Statement, Row, Mixed ์„ธ ๊ฐ€์ง€ ํฌ๋งท
  • GTID(Global Transaction ID) ๋ณต์ œ: 5.6๋ถ€ํ„ฐ ๋„์ž…, ํŽ˜์ผ์˜ค๋ฒ„๊ฐ€ ์‰ฌ์›Œ์ง
  • Group Replication / InnoDB Cluster: MySQL 8.0์˜ ๊ณต์‹ HA ์†”๋ฃจ์…˜
  • ProxySQL ๊ฐ™์€ ๋ฏธ๋“ค์›จ์–ด๋กœ ์ฝ๊ธฐ/์“ฐ๊ธฐ ๋ถ„๋ฆฌ๋ฅผ ๋งŽ์ด ๊ตฌ์„ฑ

PostgreSQL ๋ณต์ œ

  • WAL ๊ธฐ๋ฐ˜ Streaming Replication: ๊ธฐ๋ณธ HA ๋ฐฉ์‹. primary_conninfo๋กœ ์Šคํƒ ๋ฐ”์ด ๊ตฌ์„ฑ
  • Logical Replication: ํŠน์ • ํ…Œ์ด๋ธ”/๋…ผ๋ฆฌ ๋ณ€๊ฒฝ์‚ฌํ•ญ๋งŒ ๋ณต์ œ. ์ด๊ธฐ์ข… ๋ฒ„์ „ ๊ฐ„ ๋ณต์ œ ๊ฐ€๋Šฅ
  • Patroni: ์—…๊ณ„ ํ‘œ์ค€ HA ๋„๊ตฌ. etcd/Consul/ZooKeeper๋กœ ๋ฆฌ๋” ์„ ์ถœ ๊ด€๋ฆฌ
# Patroni ๊ตฌ์„ฑ ์˜ˆ์‹œ (patroni.yml ์ผ๋ถ€)
restapi:
  listen: 0.0.0.0:8008
  connect_address: 10.0.0.1:8008

postgresql:
  listen: 0.0.0.0:5432
  data_dir: /var/lib/postgresql/14/main
  parameters:
    max_connections: 200
    wal_level: replica

์„ฑ๋Šฅ ํŠน์„ฑ

์ฝ๊ธฐ ์„ฑ๋Šฅ

๋‹จ์ˆœ PK ์กฐํšŒ๋‚˜ ์ธ๋ฑ์Šค ๋ฒ”์œ„ ์Šค์บ”์€ MySQL์ด ์•ฝ๊ฐ„ ๋น ๋ฅธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. InnoDB์˜ Clustered Index ๊ตฌ์กฐ(PK๊ฐ€ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์ €์žฅ)๊ฐ€ PK ๊ธฐ๋ฐ˜ ์กฐํšŒ์— ์ตœ์ ํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Postgres๋Š” ํ…Œ์ด๋ธ”๊ณผ ์ธ๋ฑ์Šค๊ฐ€ ๋ถ„๋ฆฌ๋œ Heap ๊ตฌ์กฐ๋‹ค. PK๋กœ ์กฐํšŒํ•ด๋„ ์ธ๋ฑ์Šค โ†’ heap ํ…Œ์ด๋ธ” ์ˆœ์œผ๋กœ ๋‘ ๋ฒˆ ์ ‘๊ทผ(Index Scan + Heap Fetch)ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ๋‹ค๋งŒ Index Only Scan์ด๋‚˜ Covering Index๋กœ ์ด๋ฅผ ํšŒํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

์“ฐ๊ธฐ ์„ฑ๋Šฅ

๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋‚˜ JOIN์ด ๋งŽ์€ OLAP์„ฑ ์ฟผ๋ฆฌ์—์„œ๋Š” Postgres์˜ ์ฟผ๋ฆฌ ํ”Œ๋ž˜๋„ˆ๊ฐ€ ๋” ์ •๊ตํ•œ ์‹คํ–‰ ๊ณ„ํš์„ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. Hash Join, Merge Join, ๋ณ‘๋ ฌ ์ฟผ๋ฆฌ ์‹คํ–‰์ด ๋” ํ’๋ถ€ํ•˜๊ฒŒ ์ง€์›๋œ๋‹ค.

VACUUM ์˜ค๋ฒ„ํ—ค๋“œ

Postgres์˜ VACUUM์€ dead tuple์„ ํšŒ์ˆ˜ํ•˜๋Š” ํ•„์ˆ˜ ์ž‘์—…์ด๋‹ค. Autovacuum ์„ค์ •์ด ์ž˜๋ชป๋˜๋ฉด ํ…Œ์ด๋ธ” bloat์ด ๋ฐœ์ƒํ•ด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋œ๋‹ค. write-heavy ํ™˜๊ฒฝ์—์„œ๋Š” VACUUM ํŠœ๋‹์ด ์ค‘์š”ํ•œ ์šด์˜ ํฌ์ธํŠธ๋‹ค.

-- ํ…Œ์ด๋ธ” bloat ํ™•์ธ
SELECT relname, n_dead_tup, n_live_tup, 
       round(n_dead_tup::numeric / nullif(n_live_tup,0) * 100, 2) AS dead_ratio
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;

์Šคํ† ์–ด๋“œ ํ”„๋กœ์‹œ์ € / ํ•จ์ˆ˜

Postgres๋Š” ์—ฌ๋Ÿฌ ์–ธ์–ด๋กœ ํ”„๋กœ์‹œ์ €๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ญ๋ชฉMySQLPostgreSQL
ํ”„๋กœ์‹œ์ € ์–ธ์–ดSQL, ์ œํ•œ์ PL/pgSQL, PL/Python, PL/Perl, PL/v8 ๋“ฑ
๋ฐ˜ํ™˜ ํƒ€์ž…๋‹จ์ผ ๊ฒฐ๊ณผ์…‹TABLE, SETOF, ๋ณตํ•ฉ ํƒ€์ž… ๋“ฑ
ํŠธ๋žœ์žญ์…˜ ์ œ์–ดํ”„๋กœ์‹œ์ € ๋‚ด BEGIN/COMMIT (8.0+)๋™์ผ

PL/pgSQL ์˜ˆ์‹œ:

CREATE OR REPLACE FUNCTION get_user_rank(p_user_id BIGINT)
RETURNS INT AS $$
DECLARE
  v_rank INT;
BEGIN
  SELECT rank INTO v_rank
  FROM (
    SELECT user_id, RANK() OVER (ORDER BY score DESC) AS rank
    FROM users
  ) ranked
  WHERE user_id = p_user_id;
  RETURN v_rank;
END;
$$ LANGUAGE plpgsql;

๋ผ์ด์„ ์Šค์™€ ์ƒํƒœ๊ณ„

ํ•ญ๋ชฉMySQLPostgreSQL
๋ผ์ด์„ ์ŠคGPL v2 (์˜คํ”ˆ์†Œ์Šค), ์ƒ์šฉ ๋ผ์ด์„ ์Šค ๋ณ„๋„PostgreSQL License (BSD ์œ ์‚ฌ, ๋งค์šฐ ์ž์œ ๋กœ์›€)
์†Œ์œ Oracle ์ธ์ˆ˜ (2010)์ปค๋ฎค๋‹ˆํ‹ฐ ์ฃผ๋„
ํด๋ผ์šฐ๋“œ ๊ด€๋ฆฌํ˜•AWS RDS/Aurora, GCP Cloud SQL, Azure DBRDS for PostgreSQL, Cloud SQL, Azure DB
ORM ์ง€์›๋งค์šฐ ๊ด‘๋ฒ”์œ„๊ด‘๋ฒ”์œ„ (์ ์  Postgres ์šฐ์„  ์ถ”์„ธ)

MySQL์€ Oracle ์ธ์ˆ˜ ์ดํ›„ ์ผ๋ถ€ ๊ฐœ๋ฐœ์ž๋“ค์ด MariaDB๋กœ ๋ถ„๊ธฐํ–ˆ๋‹ค. ๋ผ์ด์„ ์Šค ๋ฆฌ์Šคํฌ๋ฅผ ์šฐ๋ คํ•˜๋Š” ๊ธฐ์—…์€ Postgres๋ฅผ ์„ ํ˜ธํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๋‹ค.


์–ธ์ œ ๋ฌด์—‡์„ ์„ ํƒํ• ๊นŒ

MySQL์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ

  • ๋‹จ์ˆœ CRUD ์ค‘์‹ฌ์˜ ์ฝ๊ธฐ ์ง‘์•ฝ์  ์›น ์„œ๋น„์Šค
  • MySQL ์ƒํƒœ๊ณ„์— ์ต์ˆ™ํ•œ ํŒ€
  • ๊ธฐ์กด MySQL ์ธํ”„๋ผ์™€์˜ ์—ฐ๋™

PostgreSQL์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ

  • ๋ณต์žกํ•œ ์ฟผ๋ฆฌ, ๋ถ„์„, ์ง‘๊ณ„๊ฐ€ ๋งŽ์€ ์„œ๋น„์Šค
  • JSONB, ๋ฐฐ์—ด, ๋ฒ”์œ„ ํƒ€์ž… ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ
  • GIS, ์ „๋ฌธ ๊ฒ€์ƒ‰ ๋“ฑ ํ™•์žฅ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ
  • ์—„๊ฒฉํ•œ ์ง๋ ฌํ™” ๊ฒฉ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ธˆ์œต/ํ•€ํ…Œํฌ ๋„๋ฉ”์ธ
  • ์žฅ๊ธฐ์ ์œผ๋กœ ๋ผ์ด์„ ์Šค ์ž์œ ๋„๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ

์ •๋ฆฌ

ํ•ญ๋ชฉMySQLPostgreSQL
MVCC ๋ฐฉ์‹Undo ๋กœ๊ทธHeap tuple versioning + VACUUM
๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€REPEATABLE READREAD COMMITTED
๋ฐ์ดํ„ฐ ํƒ€์ž…๋ณดํ†ต๋งค์šฐ ํ’๋ถ€ (JSONB, ๋ฐฐ์—ด, GIS ๋“ฑ)
์ธ๋ฑ์Šค ์ข…๋ฅ˜B-Tree ์ค‘์‹ฌB-Tree, GIN, GiST, BRIN ๋“ฑ
๋‹จ์ˆœ ์ฝ๊ธฐ๋น ๋ฆ„ (Clustered PK)๋ณดํ†ต (Heap ๋ถ„๋ฆฌ)
๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ณดํ†ต์šฐ์ˆ˜ํ•œ ์ฟผ๋ฆฌ ํ”Œ๋ž˜๋„ˆ
ํ™•์žฅ์„ฑ์ œํ•œ์ ๋งค์šฐ ํ’๋ถ€ (Extension ์‹œ์Šคํ…œ)
๋ผ์ด์„ ์ŠคGPL / OracleBSD ์œ ์‚ฌ, ๋งค์šฐ ์ž์œ ๋กœ์›€

๋‘˜ ๋‹ค ์„ฑ์ˆ™ํ•œ ํ”„๋กœ๋•์…˜ DB์ง€๋งŒ, ๊ธฐ๋Šฅ์˜ ๊นŠ์ด์™€ ํ™•์žฅ์„ฑ ์ธก๋ฉด์—์„œ ํ˜„๋Œ€ ์„œ๋น„์Šค๋Š” ์ ์  PostgreSQL์„ ์„ ํƒํ•˜๋Š” ์ถ”์„ธ๋‹ค. MySQL์€ ๋‹จ์ˆœํ•œ ์›น ์„œ๋น„์Šค์—์„œ ์—ฌ์ „ํžˆ ์ถฉ๋ถ„ํ•œ ์„ ํƒ์ง€์ด๊ณ , ์šด์˜ ๋…ธํ•˜์šฐ๊ฐ€ ํ’๋ถ€ํ•œ ํŒ€์ด๋ผ๋ฉด ์†๋„ ๋ฉด์—์„œ ์ด์ ์„ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.