ํ”„๋กœ์ ํŠธ/DB ์ž๋™ํ™”

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋‹ˆํ„ฐ๋ง ์ง€ํ‘œ ์ •๋ฆฌ (3) PostgreSQL

THE NICOLE 2026. 6. 19. 14:45

ํ•ต์‹ฌ ์š”์•ฝ

์ตœ๊ทผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ผ์ผ ์ ๊ฒ€์„ ์ž๋™ํ™”ํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๋งก๊ฒŒ ๋˜๋ฉด์„œ, DBA๊ฐ€ ๋งค์ผ ๋“ค์—ฌ๋‹ค๋ณด๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ์ง€ํ‘œ๋“ค์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ •๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๊ธ€์—์„œ MySQL, ๋‘ ๋ฒˆ์งธ ๊ธ€์—์„œ Oracle์„ ๋‹ค๋ค˜๋Š”๋ฐ, ์ด๋ฒˆ PostgreSQL์ด ์‹œ๋ฆฌ์ฆˆ์˜ ๋งˆ์ง€๋ง‰์ž…๋‹ˆ๋‹ค. PostgreSQL์€ ๊ฐ™์€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋ฉด์„œ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ์•ž์˜ ๋‘˜๊ณผ ๋˜ ๋‹ฌ๋ผ์„œ, ์ง€ํ‘œ ์ด๋ฆ„์—๋„ ๋‹ค๋ฅธ DB์—๋Š” ์—†๋Š” ๋‹จ์–ด๋“ค์ด ๋ณด์˜€์Šต๋‹ˆ๋‹ค. Dead Tuple, VACUUM, Age, autovacuum ๊ฐ™์€ ๋ง์ด ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฒˆ์—๋„ ํ•˜๋‚˜์”ฉ ์ •๋ฆฌํ•ด ๋‘๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” PostgreSQL(๋ฐ PostgreSQL on RDS)์—์„œ ์ž์ฃผ ๋ณด๋Š” ์ง€ํ‘œ๋“ค์„ โ‘  ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ โ‘ก ํ‰์†Œ ์–ด๋А ์ •๋„ ๊ฐ’์ด ์ •์ƒ์ธ์ง€(์‹ค์ œ ๊ด€์ธก ๋ฒ”์œ„·ํ‰๊ท ) โ‘ข ๊ฐ’์ด ํŠ€๋ฉด ๋ฌด์—‡์„ ์˜์‹ฌํ•ด์•ผ ํ•˜๋Š”์ง€ โ‘ฃ ํ•จ๊ป˜ ๋ณด๋ฉด ์ข‹์€ ์ง€ํ‘œ โ‘ค ์ง์ ‘ ํ™•์ธํ•˜๋Š” ์ฟผ๋ฆฌ๋กœ ๋ฌถ์–ด ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. PostgreSQL๋งŒ์˜ ๊ฐœ๋…(ํ”„๋กœ์„ธ์Šค ๊ธฐ๋ฐ˜ backend, MVCC, Dead Tuple, VACUUM·autovacuum, ํŠธ๋žœ์žญ์…˜ ID wraparound์™€ Age, shared_buffers, WAL)์€ ์ง€ํ‘œ๋ฅผ ๋ณด๊ธฐ ์ „์— ๋จผ์ € ํ•œ ๋ฒˆ ํ’€์–ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฐœ๋…๋“ค์ด ๊ทธ๋Œ€๋กœ ๋’ค์˜ ์ง€ํ‘œ๋กœ ์ด์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฐ ์ง€ํ‘œ๋งˆ๋‹ค ๊ทธ๊ฒƒ์„ ์‹ค์ œ๋กœ ์›€์ง์ด๊ฒŒ ๋งŒ๋“œ๋Š” ์ฟผ๋ฆฌ ํŒจํ„ด์„ "๋‚˜์œ ์˜ˆ → ๊ณ ์นœ ์˜ˆ" SQL๋กœ ๊ฐ€๋Šฅํ•œ ํ•œ ํ•จ๊ป˜ ์ ์—ˆ๊ณ , ์‹ค์ œ ์žฅ์• ๋กœ ์ด์–ด์ง€๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋„ ๋ถ™์˜€์Šต๋‹ˆ๋‹ค.

๋ณธ๋ฌธ์˜ "๊ด€์ธก๊ฐ’"์€ ์‹ค์ œ ์šด์˜ ์ธ์Šคํ„ด์Šค ํ•œ ๋Œ€์—์„œ 1๋ถ„ ๊ฐ„๊ฒฉ์œผ๋กœ ํ•œ ๋‹ฌ๊ฐ„ ์ˆ˜์ง‘ํ•œ ๊ฐ’์ž…๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๋‹ค๋ฅด๋ฏ€๋กœ ์ ˆ๋Œ€์ ์ธ ๊ธฐ์ค€์€ ์•„๋‹ˆ๊ณ , "๋ณดํ†ต ์ด ์ •๋„๊ตฌ๋‚˜"๋ฅผ ๊ฐ ์žก๋Š” ์šฉ๋„์ž…๋‹ˆ๋‹ค.


PostgreSQL์€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ธ๊ฐ€

์ง€ํ‘œ๋ฅผ ๋ณด๊ธฐ ์ „์—, PostgreSQL์ด MySQL·Oracle๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€๋ถ€ํ„ฐ ์งš๊ณ  ๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

  • PostgreSQL: ์˜คํ”ˆ์†Œ์Šค์ด๋ฉด์„œ ํ‘œ์ค€ ์ค€์ˆ˜์™€ ํ™•์žฅ์„ฑ์ด ๊ฐ•์ ์ž…๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ์ฟผ๋ฆฌ, ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…(JSON·๋ฐฐ์—ด·์ง€๋ฆฌ์ •๋ณด ๋“ฑ), ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ, ์‚ฌ์šฉ์ž ์ •์˜ ํ™•์žฅ(extension)์ด ํ•„์š”ํ•œ ๊ณณ์— ์ž˜ ๋งž์Šต๋‹ˆ๋‹ค. "๊ธฐ๋Šฅ์ด ๋งŽ๊ณ  ์ •์„์— ์ถฉ์‹คํ•œ ์˜คํ”ˆ์†Œ์Šค DB" ๋ผ๋Š” ํ‰์„ ์˜ค๋ž˜ ๋ฐ›์•„ ์™”์Šต๋‹ˆ๋‹ค.
  • MySQL: ์˜คํ”ˆ์†Œ์Šค์ด๊ณ  ๊ฐ€๋ณ๊ณ  ๋น ๋ฆ…๋‹ˆ๋‹ค. ์ฝ๊ธฐ๊ฐ€ ๋งŽ์€ ์›น ์„œ๋น„์Šค์—์„œ ์˜ค๋ž˜ ์‚ฌ๋ž‘๋ฐ›์•„ ์™”๊ณ , ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„(InnoDB ๋“ฑ)์„ ๊ฐˆ์•„ ๋ผ์šธ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ๊ตฌ์กฐ์  ํŠน์ง•์ž…๋‹ˆ๋‹ค.
  • Oracle: ์ƒ์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋Œ€ํ‘œ ๊ฒฉ์œผ๋กœ, ๋Œ€๊ธฐ์—…์˜ ํ•ต์‹ฌ ์—…๋ฌด ์‹œ์Šคํ…œ์— ๋งŽ์ด ์”๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ์ด ๊ฐ•๋ ฅํ•˜๊ณ  ์•ˆ์ •์ ์ธ ๋Œ€์‹  ๋ผ์ด์„ ์Šค ๋น„์šฉ์ด ๋น„์Œ‰๋‹ˆ๋‹ค.

์„ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋‘ CPU·๋ฉ”๋ชจ๋ฆฌ·์„ธ์…˜·I/O ๊ฐ™์€ ๊ณตํ†ต ์ง€ํ‘œ๋ฅผ ๋ณด์ง€๋งŒ, ๊ทธ ์œ„์— ๊ฐ์ž ๊ณ ์œ ํ•œ ์ง€ํ‘œ๊ฐ€ ์–นํž™๋‹ˆ๋‹ค. MySQL์€ InnoDB์—์„œ ๋‚˜์˜ค๋Š” ์ง€ํ‘œ(๋ฒ„ํผํ’€ ์ ์ค‘๋ฅ , Row Lock Waits)๊ฐ€ ๋งŽ์•˜๊ณ , Oracle์€ Redo·Undo·Library Cache·ํŒŒ์‹ฑ์—์„œ ๋‚˜์˜ค๋Š” ์ง€ํ‘œ๊ฐ€ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. PostgreSQL์€ MVCC·Dead Tuple·VACUUM·ํŠธ๋žœ์žญ์…˜ ID(Age) ์—์„œ ๋‚˜์˜ค๋Š” ์ง€ํ‘œ๊ฐ€ ๊ทธ DB๋งŒ์˜ ์ƒ‰๊น”์ž…๋‹ˆ๋‹ค. ์ด ๋‹จ์–ด๋“ค์ด ์ฒ˜์Œ์ด๋ฉด ์ง€ํ‘œ ์ด๋ฆ„์ด ์™ธ๊ณ„์–ด์ฒ˜๋Ÿผ ๋ณด์ด๋ฏ€๋กœ, ํ•ต์‹ฌ ๊ฐœ๋…์„ ๋จผ์ € ์‰ฝ๊ฒŒ ํ’€์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ฐœ๋…๋“ค์ด ๊ทธ๋Œ€๋กœ ๋’ค์˜ ์ง€ํ‘œ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

PostgreSQL์˜ ํ•ต์‹ฌ ๊ฐœ๋… ๋จผ์ € ํ’€๊ธฐ

  • ํ”„๋กœ์„ธ์Šค ๊ธฐ๋ฐ˜ backend: PostgreSQL์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ๋ณ„๋„์˜ ์šด์˜์ฒด์ œ ํ”„๋กœ์„ธ์Šค(backend process) ๋ฅผ ํ•˜๋‚˜์”ฉ ๋„์›๋‹ˆ๋‹ค. MySQL์ด ์—ฐ๊ฒฐ๋งˆ๋‹ค "์Šค๋ ˆ๋“œ" ๋ฅผ ๋„์šฐ๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, PostgreSQL์€ ์—ฐ๊ฒฐ๋งˆ๋‹ค "ํ”„๋กœ์„ธ์Šค" ๋ฅผ ๋„์›๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ PostgreSQL ์ง€ํ‘œ์—์„œ ์„ธ์…˜ ์ˆ˜๋ฅผ "Backend(๋ฐฑ์—”๋“œ)" ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ์ด 800๊ฐœ๋ฉด backend ํ”„๋กœ์„ธ์Šค๊ฐ€ 800๊ฐœ ๋–  ์žˆ๋Š” ์…ˆ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๋Š” ์Šค๋ ˆ๋“œ๋ณด๋‹ค ๋งŒ๋“œ๋Š” ๋น„์šฉ์ด ์ปค์„œ, PostgreSQL์—์„œ ์ปค๋„ฅ์…˜ ํ’€(๋˜๋Š” PgBouncer ๊ฐ™์€ ๋ณ„๋„ ํ’€๋Ÿฌ)์ด ํŠนํžˆ ์ค‘์š”ํ•œ ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ ์žˆ์Šต๋‹ˆ๋‹ค.
  • MVCC(๋‹ค์ค‘ ๋ฒ„์ „ ๋™์‹œ์„ฑ ์ œ์–ด): PostgreSQL์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ ์›๋ž˜ ํ–‰์„ ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฎ์–ด์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์ƒˆ ๋ฒ„์ „์˜ ํ–‰์„ ๋”ฐ๋กœ ๋งŒ๋“ค๊ณ , ์˜› ๋ฒ„์ „์€ "์ด์ œ ์•ˆ ์“ฐ๋Š” ํ–‰" ์œผ๋กœ ํ‘œ์‹œ๋งŒ ํ•ด ๋‘ก๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•œ ๋ฐ์ดํ„ฐ์˜ ์—ฌ๋Ÿฌ ๋ฒ„์ „์„ ๋™์‹œ์— ๋‘๋Š” ๋ฐฉ์‹์ด MVCC์ž…๋‹ˆ๋‹ค. ๋•๋ถ„์— ๋ˆ„๊ตฐ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊พธ๋Š” ์ค‘์—๋„ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์€ ๋ง‰ํžˆ์ง€ ์•Š๊ณ  ๋ฐ”๋€Œ๊ธฐ ์ „์˜ ๊นจ๋—ํ•œ ๋ฒ„์ „์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ฝ๊ธฐ๊ฐ€ ์“ฐ๊ธฐ๋ฅผ ๋ง‰์ง€ ์•Š์Œ). Oracle์ด ๋ณ€๊ฒฝ ์ „ ๊ฐ’์„ Undo๋ผ๋Š” ๋ณ„๋„ ๊ณต๊ฐ„์— ๋‘๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, PostgreSQL์€ ์˜› ๋ฒ„์ „์„ ํ…Œ์ด๋ธ” ์•ˆ์— ๊ทธ๋Œ€๋กœ ๋‚จ๊ฒจ ๋‘”๋‹ค๋Š” ์ ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
  • Dead Tuple(์ฃฝ์€ ํ–‰): ์œ„ MVCC ๋•Œ๋ฌธ์—, UPDATE๋‚˜ DELETE๋ฅผ ํ•˜๋ฉด ์˜› ๋ฒ„์ „์˜ ํ–‰์ด ํ…Œ์ด๋ธ” ์•ˆ์— "์ฃฝ์€ ํ–‰(dead tuple)" ์œผ๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค. UPDATE ํ•œ ๋ฒˆ์€ ์‹ค์ œ๋กœ๋Š” "์ƒˆ ๋ฒ„์ „ ์ถ”๊ฐ€ + ์˜› ๋ฒ„์ „์„ ์ฃฝ์€ ํ–‰์œผ๋กœ ํ‘œ์‹œ" ์ž…๋‹ˆ๋‹ค. ์ฃฝ์€ ํ–‰์€ ์•„๋ฌด๋„ ์•ˆ ๋ณด์ง€๋งŒ ๋””์Šคํฌ ๊ณต๊ฐ„์€ ๊ณ„์† ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ UPDATE·DELETE๊ฐ€ ๋งŽ์€ ํ…Œ์ด๋ธ”์€ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์ฃฝ์€ ํ–‰์ด ์Œ“์—ฌ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ณด๋‹ค ํ›จ์”ฌ ์ปค์ง€๋Š”๋ฐ, ์ด๊ฒƒ์„ "ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ(bloat)" ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ฒญ์†Œ๋ฅผ ์•ˆ ํ•œ ๋ฐฉ์— ๋นˆ ์ƒ์ž๊ฐ€ ์Œ“์ด๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.
  • VACUUM·autovacuum(์ฃฝ์€ ํ–‰ ์ฒญ์†Œ): ์Œ“์ธ ์ฃฝ์€ ํ–‰์„ ์ •๋ฆฌํ•ด ๊ทธ ๊ณต๊ฐ„์„ ๋‹ค์‹œ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ํšŒ์ˆ˜ํ•˜๋Š” ์ž‘์—…์ด VACUUM ์ž…๋‹ˆ๋‹ค. ์‚ฌ๋žŒ์ด ์ง์ ‘ VACUUM ๋ช…๋ น์„ ๋Œ๋ฆด ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋ณดํ†ต์€ PostgreSQL์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์•Œ์•„์„œ ๋Œ๋ฆฌ๋Š” autovacuum ์ด ์ด ์ผ์„ ํ•ฉ๋‹ˆ๋‹ค. autovacuum์ด ์ฃฝ์€ ํ–‰์„ ์ œ๋•Œ ์น˜์›Œ ์ฃผ๋ฉด ํ…Œ์ด๋ธ”์ด ๊นจ๋—ํ•˜๊ฒŒ ์œ ์ง€๋˜๊ณ , ๋ชป ๋”ฐ๋ผ๊ฐ€๋ฉด ์ฃฝ์€ ํ–‰์ด ์Œ“์—ฌ ํ…Œ์ด๋ธ”์ด ํŒฝ์ฐฝํ•˜๊ณ  ์ฟผ๋ฆฌ๊ฐ€ ๋А๋ ค์ง‘๋‹ˆ๋‹ค. ์ฒญ์†Œ๋ถ€๊ฐ€ ๋ถ€์ง€๋Ÿฐํ•˜๋ฉด ๋ฐฉ์ด ๊นจ๋—ํ•˜๊ณ , ๊ฒŒ์œผ๋ฅด๋ฉด ๋นˆ ์ƒ์ž๊ฐ€ ์Œ“์ด๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ํŠธ๋žœ์žญ์…˜ ID wraparound์™€ Age: PostgreSQL์€ ๋ชจ๋“  ํŠธ๋žœ์žญ์…˜์— ๋ฒˆํ˜ธ(ํŠธ๋žœ์žญ์…˜ ID, XID)๋ฅผ ๋งค๊น๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด ๋ฒˆํ˜ธ๋Š” ์•ฝ 21์–ต(32๋น„ํŠธ)์—์„œ ํ•œ ๋ฐ”ํ€ด ๋Œ์•„ ๋‹ค์‹œ 0์œผ๋กœ ๋Œ์•„์˜ค๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ wraparound(๋žฉ์–ด๋ผ์šด๋“œ) ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์•„์ฃผ ์˜ค๋ž˜๋œ ํ–‰์„ ์ ์ ˆํžˆ "freeze(๋™๊ฒฐ)" ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์€ ์ฑ„ ๋ฒˆํ˜ธ๊ฐ€ ํ•œ ๋ฐ”ํ€ด ๋Œ๋ฉด, ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฏธ๋ž˜๋กœ ๋ณด์ด๋Š” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ DB๊ฐ€ ์ƒˆ ์“ฐ๊ธฐ๋ฅผ ๊ฑฐ๋ถ€ํ•˜๊ณ  ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ PostgreSQL์€ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํŠธ๋žœ์žญ์…˜์ด ์ง€๊ธˆ์œผ๋กœ๋ถ€ํ„ฐ ์–ผ๋งˆ๋‚˜ ๋–จ์–ด์กŒ๋Š”์ง€๋ฅผ Age(๋‚˜์ด) ๋กœ ์ถ”์ ํ•˜๊ณ , ์ด ๋‚˜์ด๊ฐ€ ์œ„ํ—˜ ์ˆ˜์ค€์— ๊ฐ€๊นŒ์›Œ์ง€๋ฉด autovacuum์ด freeze ์ž‘์—…์„ ํ•ด์„œ ํ•œ ๋ฐ”ํ€ด ๋„๋Š” ์‚ฌ๊ณ ๋ฅผ ๋ง‰์Šต๋‹ˆ๋‹ค. ๋„์„œ๊ด€ ๋Œ€์ถœ์ฆ ๋ฒˆํ˜ธ๊ฐ€ ์–ธ์  ๊ฐ€ ๋‹ค์‹œ ์ฒ˜์Œ ๋ฒˆํ˜ธ๋กœ ๋Œ์•„์˜จ๋‹ค๋ฉด, ๋„ˆ๋ฌด ์˜ค๋ž˜๋œ ๊ธฐ๋ก์€ ๋ฏธ๋ฆฌ ์ •๋ฆฌํ•ด ๋‘ฌ์•ผ ์ƒˆ ๋ฒˆํ˜ธ์™€ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. ๋’ค์˜ Age Used Ratio·Current Age ์ง€ํ‘œ๊ฐ€ ๋ฐ”๋กœ ์ด ๋‚˜์ด๋ฅผ ๋ด…๋‹ˆ๋‹ค.
  • shared_buffers(๋ฒ„ํผ ์บ์‹œ): PostgreSQL์ด ์ž์ฃผ ์“ฐ๋Š” ๋ฐ์ดํ„ฐ·์ธ๋ฑ์Šค ๋ธ”๋ก์„ ์บ์‹ฑํ•ด ๋‘๋Š” ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค. MySQL์˜ ๋ฒ„ํผํ’€, Oracle์˜ ๋ฒ„ํผ ์บ์‹œ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋””์Šคํฌ์—์„œ ํ•œ ๋ฒˆ ์ฝ์–ด ์˜จ ๋ธ”๋ก์€ ์—ฌ๊ธฐ ์˜ฌ๋ ค ๋‘๊ณ , ๋‹ค์Œ์— ๊ฐ™์€ ๋ธ”๋ก์ด ํ•„์š”ํ•˜๋ฉด ๋””์Šคํฌ๊นŒ์ง€ ์•ˆ ๊ฐ€๊ณ  ์—ฌ๊ธฐ์„œ ๋ฐ”๋กœ ๊บผ๋ƒ…๋‹ˆ๋‹ค. ๋’ค์˜ Cache Hit Ratio·Blks Hit·Blks Read ์ง€ํ‘œ๊ฐ€ ์ด ์บ์‹œ์˜ ์ ์ค‘์„ ๋ด…๋‹ˆ๋‹ค.
  • WAL(๋ณ€๊ฒฝ ๋กœ๊ทธ): ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ๋งˆ๋‹ค "๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ๋ฐ”๊ฟจ๋Š”์ง€" ๋ฅผ ๋จผ์ € ์ ์–ด ๋‘๋Š” ๊ธฐ๋ก์ž…๋‹ˆ๋‹ค(Write-Ahead Log). ์žฅ์• ๋กœ DB๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ฃฝ์–ด๋„ ์ด ๊ธฐ๋ก์„ ๋‹ค์‹œ ์ ์šฉํ•ด ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค. Oracle์˜ Redo์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ๋งŽ์œผ๋ฉด WAL๋„ ๋งŽ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ๋ธ”๋ก(block): PostgreSQL์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์“ฐ๋Š” ์ตœ์†Œ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค(๋ณดํ†ต 8KB). ํ–‰ ํ•˜๋‚˜ํ•˜๋‚˜๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ํ–‰์ด ๋‹ด๊ธด ๋ธ”๋ก ๋‹จ์œ„๋กœ ๋””์Šคํฌ์™€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์˜ค๊ฐ‘๋‹ˆ๋‹ค. ๋’ค์˜ Blks Read·Blks Hit๊ฐ€ ์ด ๋ธ”๋ก ์ˆ˜๋ฅผ ์…‰๋‹ˆ๋‹ค.

์ด ๊ฐœ๋…๋“ค์„ ๋จธ๋ฆฌ์— ๋„ฃ๊ณ  ๋ณด๋ฉด, ๋’ค์— ๋‚˜์˜ค๋Š” 32๊ฐœ ์ง€ํ‘œ๊ฐ€ ๋”ฐ๋กœ ๋…ธ๋Š” ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ํ•˜๋‚˜์˜ ๊ทธ๋ฆผ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ํŠนํžˆ "UPDATE/DELETE → ์ฃฝ์€ ํ–‰ ๋ฐœ์ƒ → VACUUM์ด ์ฒญ์†Œ → ๋ชป ๋”ฐ๋ผ๊ฐ€๋ฉด ํŒฝ์ฐฝ·Age ์ƒ์Šน" ์ด๋ผ๋Š” ํ•œ ์ค„๊ธฐ๊ฐ€ PostgreSQL ์ง€ํ‘œ๋ฅผ ๊ด€ํ†ตํ•ฉ๋‹ˆ๋‹ค.


๋“ค์–ด๊ฐ€๊ธฐ ์ „์— — ์ง€ํ‘œ๋ฅผ ๋ณด๋Š” ๋‘ ๊ฐ€์ง€ ๊ด€์ 

์ง€ํ‘œ๋ฅผ ๋ณผ ๋•Œ๋Š” ๋ณดํ†ต ๋‘ ๊ฐ€์ง€ ๊ธฐ์ค€์„ ๊ฐ™์ด ์”๋‹ˆ๋‹ค.

์ฒซ์งธ๋Š” ์ ˆ๋Œ€ ์ž„๊ณ„๊ฐ’์ž…๋‹ˆ๋‹ค. "CPU ์‚ฌ์šฉ๋ฅ  90% ์ด์ƒ์ด๋ฉด ์œ„ํ—˜" ์ฒ˜๋Ÿผ ๋ฏธ๋ฆฌ ์ •ํ•œ ์„ ์„ ๋„˜์—ˆ๋Š”์ง€ ๋ด…๋‹ˆ๋‹ค. ๊ธฐ์ค€์ด ๋ช…ํ™•ํ•˜์ง€๋งŒ, DB๋งˆ๋‹ค ์ •์ƒ ๋ฒ”์œ„๊ฐ€ ๋‹ฌ๋ผ ์ž„๊ณ„๊ฐ’๋„ DB๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ์žก์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๊ฐ™์€ CPU ์‚ฌ์šฉ๋ฅ ์ด๋ผ๋„ PostgreSQL ์ธ์Šคํ„ด์Šค๋Š” ๊ฒฝ๊ณ  85% / ์œ„ํ—˜ 90%๋กœ, MySQL·Oracle(๊ฒฝ๊ณ  60% / ์œ„ํ—˜ 80%)๋ณด๋‹ค ๋†’๊ฒŒ ์žกํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค ํŠน์„ฑ์— ๋”ฐ๋ผ ํ‰์†Œ ๋ถ€ํ•˜ ์ˆ˜์ค€์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‘˜์งธ๋Š” ํ‰์†Œ ๋Œ€๋น„ ๋ณ€ํ™”์ž…๋‹ˆ๋‹ค. ์ž„๊ณ„๊ฐ’์„ ๋„˜์ง€ ์•Š์•˜๋”๋ผ๋„ "์–ด์ œ๊นŒ์ง€ ํ‰๊ท  10์ด๋˜ ๊ฐ’์ด ์˜ค๋Š˜ 40์œผ๋กœ ๋›ฐ์—ˆ๋‹ค" ๋ฉด ๋ฌด์–ธ๊ฐ€ ๋‹ฌ๋ผ์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋น„์œ ํ•˜์ž๋ฉด ์ ˆ๋Œ€ ์ž„๊ณ„๊ฐ’์€ ๊ฑด๊ฐ•๊ฒ€์ง„์˜ ์ •์ƒ ์ˆ˜์น˜ํ‘œ์ด๊ณ , ํ‰์†Œ ๋Œ€๋น„ ๋ณ€ํ™”๋Š” ํ‰์†Œ ๋‚ด ์ปจ๋””์…˜๊ณผ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ๋ด์•ผ ๋†“์น˜๋Š” ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. PostgreSQL์—๋Š” Tup Updated·Tup Deleted๋‚˜ Temp Bytes์ฒ˜๋Ÿผ ํ‰์†Œ์—” ์ž‘๋‹ค๊ฐ€ ๋ฐฐ์น˜ ๋•Œ ํฌ๊ฒŒ ํŠ€๋Š” ์ง€ํ‘œ๊ฐ€ ๋งŽ์•„์„œ, ํŠนํžˆ "ํ‰์†Œ ๋Œ€๋น„ ๋ณ€ํ™”" ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ•œ ๊ฐ€์ง€ ๋”, ์ง€ํ‘œ๋Š” ๊ฑฐ์˜ ํ˜ผ์ž ํŠ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ ์ง€ํ‘œ๋งˆ๋‹ค "ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ" ๋ฅผ ๋ถ™์˜€์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ๊ฐ’์ด ํŠ€์—ˆ์„ ๋•Œ ์˜†์˜ ์ง€ํ‘œ๊ฐ€ ๊ฐ™์ด ์˜ฌ๋ž๋Š”์ง€๋กœ ์›์ธ์˜ ๋ฐฉํ–ฅ์ด ๊ฐˆ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.


1. CPU · ๋ฉ”๋ชจ๋ฆฌ

์„œ๋ฒ„๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋ฐ”์œ์ง€๋ฅผ ๋ณด๋Š” ๊ธฐ๋ณธ ์˜์—ญ์ž…๋‹ˆ๋‹ค. ์‹๋‹น์— ๋น„์œ ํ•˜๋ฉด CPU๋Š” ์ฃผ๋ฐฉ์˜ ๋ฐ”์œ ์ •๋„, ๋ฉ”๋ชจ๋ฆฌ๋Š” ์กฐ๋ฆฌ๋Œ€์˜ ๋„“์ด์ž…๋‹ˆ๋‹ค. ์ฃผ๋ฌธ์ด ๋ชฐ๋ฆฌ๋ฉด ์ฃผ๋ฐฉ์ด ๋ฐ”๋น ์ง€๊ณ (CPU↑), ์žฌ๋ฃŒ๋ฅผ ๋ฏธ๋ฆฌ ๊บผ๋‚ด๋‘˜ ์กฐ๋ฆฌ๋Œ€๊ฐ€ ์ข์œผ๋ฉด ๊ทธ๋•Œ๊ทธ๋•Œ ์ฐฝ๊ณ ๋ฅผ ์˜ค๊ฐ€์•ผ ํ•ฉ๋‹ˆ๋‹ค(๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ → ๋””์Šคํฌ ์ ‘๊ทผ↑).

์ด ์˜์—ญ์— ์ฒ˜์Œ ๋ณด๋ฉด ๋ง‰ํžˆ๋Š” ๋‹จ์–ด๋ฅผ ๋จผ์ € ์งง๊ฒŒ ํ’€์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์Šค์™‘(swap): ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ชจ์ž๋ž„ ๋•Œ ์šด์˜์ฒด์ œ๊ฐ€ ๋””์Šคํฌ์˜ ์ผ๋ถ€๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์ฒ˜๋Ÿผ ๋นŒ๋ ค ์“ฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋น ๋ฅด๊ณ  ๋””์Šคํฌ๋Š” ํ›จ์”ฌ ๋А๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์—, ์Šค์™‘์ด ์‹œ์ž‘๋˜๋ฉด ๋ชจ๋“  ์ž‘์—…์ด ๊ฐ‘์ž๊ธฐ ๋А๋ ค์ง‘๋‹ˆ๋‹ค.
  • work_mem(์ž‘์—… ๋ฉ”๋ชจ๋ฆฌ): PostgreSQL์ด ์ •๋ ฌ(ORDER BY)·ํ•ด์‹œ ์กฐ์ธ·๊ทธ๋ฃนํ•‘(GROUP BY) ๊ฐ™์€ ์ž‘์—…์„ ํ•  ๋•Œ ์“ฐ๋Š” backend ํ•œ ๊ฐœ๋‹น ์ž‘์—… ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ๊ณต๊ฐ„ ์•ˆ์—์„œ ๋๋‚˜๋ฉด ๋น ๋ฅด์ง€๋งŒ, ์ฒ˜๋ฆฌํ•  ์–‘์ด ์ด ํ•œ๋„๋ฅผ ๋„˜์œผ๋ฉด ์ž„์‹œ ํŒŒ์ผ(temp file)์„ ๋””์Šคํฌ์— ๋งŒ๋“ค์–ด ์ฒ˜๋ฆฌํ•ด ๋А๋ ค์ง‘๋‹ˆ๋‹ค(๋’ค์˜ Temp Bytes·Temp Files๊ฐ€ ์ด๊ฒƒ์„ ๋ด…๋‹ˆ๋‹ค).

(OS) Cpu Usage (%)

์„œ๋ฒ„์˜ CPU ์‚ฌ์šฉ๋ฅ ์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋จผ์ € ๋ณด๋Š” ์ง€ํ‘œ์ด๊ณ  ์˜๋ฏธ๋„ ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. CPU๋Š” ๊ฒฐ๊ตญ ์ฟผ๋ฆฌ๋ฅผ ์‹ค์ œ๋กœ ๊ณ„์‚ฐํ•˜๋Š” ์ผ๊พผ์ด๋ผ, ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ(์ •๋ ฌ·์กฐ์ธ·์ง‘๊ณ„·ํ’€ ์Šค์บ”)์ด ๋งŽ์•„์งˆ์ˆ˜๋ก ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. PostgreSQL์—์„œ๋Š” autovacuum์ด ํฐ ํ…Œ์ด๋ธ”์„ ์ฒญ์†Œํ•  ๋•Œ๋„ CPU๋ฅผ ์–ด๋А ์ •๋„ ์”๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 18.0%, ๋ฒ”์œ„ ์•ฝ 8.3 ~ 52.4%. MySQL ์ธ์Šคํ„ด์Šค๋ณด๋‹ค ๋†’๊ฒŒ ๊น”๋ ค ์žˆ๊ณ , ์ˆœ๊ฐ„์ ์œผ๋กœ 50%๋Œ€๊นŒ์ง€ ์˜ค๋ฅด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ์ด ์ธ์Šคํ„ด์Šค์˜ ์ž„๊ณ„๋Š” ๊ฒฝ๊ณ  85% / ์œ„ํ—˜ 90%๋กœ ์žกํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค. 90%๋ฅผ ๋„˜์–ด ์ง€์†๋˜๋ฉด ์ฟผ๋ฆฌ ์‘๋‹ต์ด ๋А๋ ค์ง€๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ๋ฌด๊ฑฐ์šด ์ฟผ๋ฆฌ(ํ’€ ์Šค์บ”·์ •๋ ฌ·์กฐ์ธ), ๊ฐ‘์ž๊ธฐ ๋Š˜์–ด๋‚œ ํ™œ์„ฑ backend, ๋Œ€๋Ÿ‰ ๋ฐฐ์น˜, ํฐ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ autovacuum ๋™์ž‘. CPU๋งŒ ๋‹จ๋…์œผ๋กœ ํŠ€๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ฌผ๊ณ  ๋ณดํ†ต Active Backend๋‚˜ ์ฝ๊ธฐ๋Ÿ‰(Blks Read·Blks Hit)์ด ๊ฐ™์ด ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค.

PostgreSQL์—์„œ CPU๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š” ์ „ํ˜•์ ์ธ ์ฟผ๋ฆฌ๋Š” "ํ•  ์ผ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋– ์•ˆ๋Š”" ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ์กฐ๊ฑด, ํ•จ์ˆ˜๋กœ ๊ฐ์‹ผ ์ปฌ๋Ÿผ์ด ๋Œ€ํ‘œ์ ์ž…๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: created_at์— ์ธ๋ฑ์Šค๊ฐ€ ์žˆ์–ด๋„ ํ•จ์ˆ˜(date)๋กœ ๊ฐ์‹ธ๋ฉด ์ธ๋ฑ์Šค๊ฐ€ ๋ฌด๋ ฅํ™”๋œ๋‹ค
-- ํ’€ ์Šค์บ” + ํ•จ์ˆ˜ ์—ฐ์‚ฐ์ด ๊ฒน์ณ CPU๋ฅผ ํฌ๊ฒŒ ์“ด๋‹ค
SELECT * FROM orders
WHERE date(created_at) = DATE '2026-06-18';
-- ๊ณ ์นœ ์˜ˆ: ํ•จ์ˆ˜ ์—†์ด ๋ฒ”์œ„ ์กฐ๊ฑด์œผ๋กœ ๋ฐ”๊พธ๋ฉด ์ธ๋ฑ์Šค๋ฅผ ํƒ„๋‹ค
SELECT order_id, member_id, total_amount, created_at
FROM   orders
WHERE  created_at >= TIMESTAMP '2026-06-18 00:00:00'
  AND  created_at <  TIMESTAMP '2026-06-19 00:00:00';

์ง€๊ธˆ ๋ฌด์—‡์ด CPU๋ฅผ ์“ฐ๊ณ  ์žˆ๋Š”์ง€๋Š” ์‹คํ–‰ ์ค‘์ธ ์ฟผ๋ฆฌ๋ถ€ํ„ฐ ๋ด…๋‹ˆ๋‹ค.

-- ์ง€๊ธˆ active ์ƒํƒœ์ธ backend๊ฐ€ ์–ด๋–ค ์ฟผ๋ฆฌ๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ (์˜ค๋ž˜ ๊ฑธ๋ฆฐ ์ˆœ์„œ)
SELECT pid, usename, state,
       now() - query_start AS running_for,
       query
FROM   pg_stat_activity
WHERE  state = 'active'
  AND  backend_type = 'client backend'
ORDER  BY running_for DESC;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Blks Read·Blks Hit๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ํ’€ ์Šค์บ”/๋ฌด๊ฑฐ์šด ์ฝ๊ธฐ ์ฟผ๋ฆฌ๊ฐ€ CPU๋ฅผ ๋จน๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Active Backend๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ์ฟผ๋ฆฌ๊ฐ€ ๋นจ๋ฆฌ ๋๋‚˜์ง€ ๋ชปํ•˜๊ณ  ์Œ“์ด๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. Tup Updated·Tup Deleted๊ฐ€ ๊ฐ™์ด ๋›ฐ๋ฉด → ๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ ๋ฐฐ์น˜๊ฐ€ ๋Œ๋ฉฐ ์ฃฝ์€ ํ–‰์„ ๋งŒ๋“ค๊ณ  autovacuum๊นŒ์ง€ ์ผ์„ ์‹œ์ž‘ํ•œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์ •๋ ฌ·์ง‘๊ณ„·๋ฌธ์ž์—ด ๊ฐ€๊ณต์„ ์ „๋ถ€ DB ์ฟผ๋ฆฌ์— ๋ชฐ์•„๋„ฃ์œผ๋ฉด ๊ทธ ๊ณ„์‚ฐ ๋ถ€๋‹ด์ด ๊ทธ๋Œ€๋กœ CPU๋กœ ์˜ต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๊ณต์€ ์ฝ”๋“œ ์ชฝ์œผ๋กœ ์˜ฎ๊ธฐ๊ฑฐ๋‚˜, ์ž์ฃผ ์“ฐ๋Š” ์ง‘๊ณ„๋Š” ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•œ ์ง‘๊ณ„ ํ…Œ์ด๋ธ”์„ ๋‘๋ฉด ์™„ํ™”๋ฉ๋‹ˆ๋‹ค. ๋˜ ์ปฌ๋Ÿผ์„ ํ•จ์ˆ˜๋กœ ๊ฐ์‹ธ๋Š” ์กฐ๊ฑด(date(col) = ...)์€ ์ธ๋ฑ์Šค๋ฅผ ๋ฌด๋ ฅํ™”ํ•ด ํ’€ ์Šค์บ”์„ ์œ ๋ฐœํ•˜๋ฏ€๋กœ, ๋ฒ”์œ„ ์กฐ๊ฑด์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ž…๋‹ˆ๋‹ค.

(OS) Memory Percent (%)

์šด์˜์ฒด์ œ ๊ด€์ ์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ (%)์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 79.4%, ๋ฒ”์œ„ 78.2 ~ 82.3%๋กœ ํ‰ํƒ„ํ•˜๊ฒŒ ์œ ์ง€๋์Šต๋‹ˆ๋‹ค. MySQL(์•ฝ 54%)·Oracle(์•ฝ 56%) ์ธ์Šคํ„ด์Šค๋ณด๋‹ค ๋†’๊ฒŒ ๊น”๋ ค ์žˆ๋Š”๋ฐ, ์ด๋Š” ์ธ์Šคํ„ด์Šค ํฌ๊ธฐ·shared_buffers ์„ค์ •์— ๋”ฐ๋ฅธ ์ฐจ์ด์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ ˆ๋Œ€๊ฐ’๋ณด๋‹ค ์ถ”์„ธ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๊ฒฝ๊ณ  90%, ์œ„ํ—˜ 95%. ๋‹ค๋งŒ ๋‚จ์€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊พธ์ค€ํžˆ ์ค„์–ด๋“œ๋Š” ์ถ”์„ธ๊ฐ€ ๋” ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๊ฐˆ๋˜๋ฉด OS๊ฐ€ ์Šค์™‘(๋””์Šคํฌ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์ฒ˜๋Ÿผ ์“ฐ๋Š” ๊ฒƒ)์„ ์‹œ์ž‘ํ•˜๊ณ , ๊ทธ๋•Œ๋ถ€ํ„ฐ ์„ฑ๋Šฅ์ด ๊ธ‰๊ฒฉํžˆ ๋‚˜๋น ์ง‘๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: backend ํญ์ฆ(์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์”€), ํฐ ์ •๋ ฌ·ํ•ด์‹œ ์กฐ์ธ์œผ๋กœ work_mem ์‚ฌ์šฉ ์ฆ๊ฐ€, shared_buffers ์„ค์ • ๊ณผ๋‹ค.

PostgreSQL์€ ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋„์šฐ๋ฏ€๋กœ, backend๊ฐ€ ๋Š˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ๋„ ๊ทธ๋งŒํผ ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค. ๋˜ ์ •๋ ฌ·ํ•ด์‹œ ์ž‘์—…์ด work_mem์„ ๋„˜์œผ๋ฉด ๋””์Šคํฌ temp๋กœ ๋„˜์–ด๊ฐ€๋Š”๋ฐ, ์ด๊ฒƒ๋„ ํ•จ๊ป˜ ๋ด…๋‹ˆ๋‹ค.

-- ์ž„์‹œ ํŒŒ์ผ(temp) ์‚ฌ์šฉ๋Ÿ‰ — ์ •๋ ฌ/ํ•ด์‹œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋๋‚˜์ง€ ๋ชปํ•˜๊ณ  ๋””์Šคํฌ๋กœ ๋„˜์–ด๊ฐ€๋Š”์ง€
-- temp_files·temp_bytes๊ฐ€ ๋น ๋ฅด๊ฒŒ ๋Š˜๋ฉด work_mem์ด ๋ถ€์กฑํ•˜๋‹ค๋Š” ์‹ ํ˜ธ
SELECT datname, temp_files, temp_bytes
FROM   pg_stat_database
WHERE  datname = current_database();
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Numbackends๊ฐ€ ๊ฐ™์ด ์šฐ์ƒํ–ฅํ•˜๋ฉด → ์—ฐ๊ฒฐ(ํ”„๋กœ์„ธ์Šค) ๋ˆ„์ˆ˜๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ƒˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Temp Bytes·Temp Files๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ์ •๋ ฌ·ํ•ด์‹œ๊ฐ€ ๋””์Šคํฌ๋กœ ๋„˜์–ด๊ฐ€๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์••๋ฐ•ํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. ๋‚จ์€ ๋ฉ”๋ชจ๋ฆฌ(Free Memory)๊ฐ€ ์ค„๋ฉฐ Read IOPS๊ฐ€ ์˜ค๋ฅด๋ฉด → ์Šค์™‘์ด ์‹œ์ž‘๋์„ ์ˆ˜ ์žˆ์–ด ์ฆ‰์‹œ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — PostgreSQL์€ ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋„์šฐ๋ฏ€๋กœ ์ปค๋„ฅ์…˜ ํ’€์„ ๊ณผํ•˜๊ฒŒ ํฌ๊ฒŒ ์žก์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ•์ด MySQL๋ณด๋‹ค ์ง์ ‘์ ์œผ๋กœ ์ปค์ง‘๋‹ˆ๋‹ค. ํ’€ ํฌ๊ธฐ๋ฅผ ์ ์ •ํ•˜๊ฒŒ ์žก๊ณ , ํ•œ ๋ฒˆ์— ๊ฑฐ๋Œ€ํ•œ ๊ฒฐ๊ณผ์…‹์„ ์ •๋ ฌ·๊ทธ๋ฃนํ•‘ํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ค„์ด๋ฉฐ, ์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ์„ ๋Œ€์‹ ํ•˜๊ฒŒ ํ•˜๋ฉด work_mem์ด ๋””์Šคํฌ temp๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

Free Memory (Bytes)

์—ฌ์œ  ๋ฉ”๋ชจ๋ฆฌ(freeable memory)์ž…๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค์— ๋‚จ์•„ ์žˆ๋Š” ์“ธ ์ˆ˜ ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ฐ”์ดํŠธ๋กœ ๋ด…๋‹ˆ๋‹ค. (OS) Memory Percent์™€ ์ง์œผ๋กœ, ํ•œ์ชฝ์€ ๋น„์œจ์„, ํ•œ์ชฝ์€ ์ ˆ๋Œ€ ์—ฌ์œ ๋Ÿ‰์„ ๋ด…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 14.2GB, ๋ฒ”์œ„ ์•ฝ 12.2 ~ 15.0GB๋กœ ํ‰ํƒ„ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ์œ ๊ฐ€ ์•ˆ์ •์ ์œผ๋กœ ์œ ์ง€๋˜๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ ˆ๋Œ€๊ฐ’๋ณด๋‹ค ์—ฌ์œ  ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊พธ์ค€ํžˆ ์ค„์–ด๋“œ๋Š” ์ถ”์„ธ๊ฐ€ ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๊ฐˆ๋˜๋ฉด ์Šค์™‘์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด(์ค„๋ฉด) ์˜์‹ฌํ•  ๊ฒƒ: backend ๋ˆ„์ˆ˜(๋ฐ˜๋‚ฉ ์•ˆ ๋œ ์—ฐ๊ฒฐ์ด ์Œ“์ž„), ํฐ ์ •๋ ฌ·ํ•ด์‹œ ์ž‘์—…, shared_buffers·์บ์‹œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ์œ .
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: (OS) Memory Percent์™€ ๋ฐ˜๋Œ€๋กœ ์›€์ง์ž…๋‹ˆ๋‹ค(์—ฌ์œ ๊ฐ€ ์ค„๋ฉด ์‚ฌ์šฉ๋ฅ ์ด ์˜ค๋ฆ„). Numbackends๊ฐ€ ๊ฐ™์ด ์šฐ์ƒํ–ฅํ•˜๋ฉด → ์—ฐ๊ฒฐ ๋ˆ„์ˆ˜๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ƒˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Read IOPS๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ์Šค์™‘ ์‹œ์ž‘ ์‹ ํ˜ธ์ผ ์ˆ˜ ์žˆ์–ด ์ฆ‰์‹œ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ์—ฌ์œ  ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋Š˜ 14GB ์•ˆํŒŽ์œผ๋กœ ํ‰ํƒ„ํ•˜๋ฉด ํ•œ๋ˆˆ์— ์ •์ƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์ฒœ์ฒœํžˆ ์ƒˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—ฐ๊ฒฐ์„ ๋‹ซ์ง€ ์•Š์œผ๋ฉด backend ํ”„๋กœ์„ธ์Šค๊ฐ€ ์Œ“์ด๋ฉฐ ์—ฌ์œ  ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์‹œ๊ฐ„๋‹น ์ผ์ •ํ•˜๊ฒŒ ์ค„์–ด๋“œ๋Š” ์šฐํ•˜ํ–ฅ ๊ทธ๋ž˜ํ”„๊ฐ€ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ์–ด๋А ์ˆœ๊ฐ„ ์Šค์™‘์ด ์‹œ์ž‘๋˜๋ฉด ๋ชจ๋“  ์ฟผ๋ฆฌ๊ฐ€ ๋А๋ ค์ง€๋ฏ€๋กœ, ์ถ”์„ธ๊ฐ€ ๊บพ์ด๊ธฐ ์ „์— ์žก๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.


2. ์„ธ์…˜ · ์—ฐ๊ฒฐ

์ฒด๊ฐ์ƒ ๊ฐ€์žฅ ์ž์ฃผ ๋ณด๋Š” ์˜์—ญ์ž…๋‹ˆ๋‹ค. ํ•ต์‹ฌ์€ "์—ฐ๊ฒฐ" ๊ณผ "ํ™œ์„ฑ" ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์นดํŽ˜๋กœ ์น˜๋ฉด ๋งค์žฅ ์•ˆ ์†๋‹˜ ์ „์ฒด๊ฐ€ ์—ฐ๊ฒฐ(Numbackends)์ด๊ณ , ๊ทธ์ค‘ ์ง€๊ธˆ ๊ณ„์‚ฐ๋Œ€์—์„œ ์ฃผ๋ฌธ ์ค‘์ธ ์†๋‹˜์ด ํ™œ์„ฑ(Active Backend)์ž…๋‹ˆ๋‹ค. ๋งค์žฅ์— ์†๋‹˜์ด ๋งŽ์•„๋„ ๊ณ„์‚ฐ๋Œ€ ์•ž์€ ๋ณดํ†ต ํ•œ๋‘ ๋ช…์ธ ๊ฒƒ์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค.

์ด ์˜์—ญ์˜ ์šฉ์–ด ๋ช‡ ๊ฐœ๋ฅผ ๋จผ์ € ํ’€์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

  • backend(๋ฐฑ์—”๋“œ): PostgreSQL์ด ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ํ•˜๋‚˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๊ณ  ๋„์šฐ๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. MySQL์ด ์—ฐ๊ฒฐ๋งˆ๋‹ค ์Šค๋ ˆ๋“œ๋ฅผ ๋„์šฐ๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ PostgreSQL์€ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋„์šฐ๊ณ , ๊ทธ๊ฒƒ์„ backend๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•ด "์ง€๊ธˆ ๋ถ™์–ด ์žˆ๋Š” DB ์—ฐ๊ฒฐ ํ•œ ๊ฐœ" ์ž…๋‹ˆ๋‹ค.
  • ์ปค๋„ฅ์…˜ ํ’€(Connection Pool): ์—ฐ๊ฒฐ์„ ๋งค๋ฒˆ ์ƒˆ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค ๋Š๋Š” ๊ฒƒ์€ ๋น„์šฉ์ด ํฝ๋‹ˆ๋‹ค. ํŠนํžˆ PostgreSQL์€ ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋„์›Œ ๋” ๋น„์Œ‰๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—ฐ๊ฒฐ์„ ๋ฏธ๋ฆฌ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค์–ด ๋‘๊ณ  ๋นŒ๋ ค ์“ฐ๊ณ  ๋ฐ˜๋‚ฉํ•˜๊ฑฐ๋‚˜, PgBouncer ๊ฐ™์€ ๋ณ„๋„ ํ’€๋Ÿฌ๋ฅผ ์•ž์— ๋‘ก๋‹ˆ๋‹ค. ๊ณต๊ตฌ๋ฅผ ์“ธ ๋•Œ๋งˆ๋‹ค ์‚ฌ ์˜ค์ง€ ์•Š๊ณ  ๊ณต๊ตฌํ•จ์—์„œ ๊บผ๋‚ด ์“ฐ๊ณ  ๋‹ค์‹œ ๋„ฃ์–ด ๋‘๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋นŒ๋ฆฐ ์—ฐ๊ฒฐ์„ ๋ฐ˜๋‚ฉํ•˜์ง€ ์•Š์œผ๋ฉด "์—ฐ๊ฒฐ ๋ˆ„์ˆ˜" ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค.
  • idle ์—ฐ๊ฒฐ: ์—ฐ๊ฒฐ์€ ๋˜์–ด ์žˆ์ง€๋งŒ ์ง€๊ธˆ์€ ์•„๋ฌด ์ฟผ๋ฆฌ๋„ ๋Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ผ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ(state = 'idle')์ž…๋‹ˆ๋‹ค. ์ปค๋„ฅ์…˜ ํ’€์ด ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋‘” ์—ฐ๊ฒฐ๋“ค์€ ๋Œ€๋ถ€๋ถ„ ์ด idle ์ƒํƒœ๋กœ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฐ๊ฒฐ ์ˆ˜๊ฐ€ ์ˆ˜๋ฐฑ ๊ฐœ์—ฌ๋„ ์‹ค์ œ๋กœ ์ผํ•˜๋Š” ๊ฒƒ์€ ๋ช‡ ๊ฐœ๋ฟ์ธ ๊ฒฝ์šฐ๊ฐ€ ์ •์ƒ์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ํŠธ๋žœ์žญ์…˜์„ ์—ฐ ์ฑ„๋กœ ๋…ธ๋Š” idle in transaction ์ƒํƒœ๋Š” ๋ฝ๊ณผ ์ฃฝ์€ ํ–‰ ์ •๋ฆฌ๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ์–ด ์ฃผ์˜ํ•ด์„œ ๋ด…๋‹ˆ๋‹ค(๋’ค์—์„œ ๋‹ค์‹œ ๋‹ค๋ฃน๋‹ˆ๋‹ค).

Active Backend (๊ฐœ)

์ง€๊ธˆ ์‹ค์ œ๋กœ ์ผํ•˜๊ณ  ์žˆ๋Š”(active ์ƒํƒœ์ธ) backend ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ถ€ํ•˜๋ฅผ ๊ฐ€์žฅ ์ž˜ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 0.88, ๋ฒ”์œ„ 0 ~ 177. ๋’ค์— ๋‚˜์˜ค๋Š” Numbackends๊ฐ€ ์•ฝ 837์ธ๋ฐ ํ™œ์„ฑ์€ 1 ์•ˆํŒŽ์ž…๋‹ˆ๋‹ค. ์ฆ‰ ๋Œ€๋ถ€๋ถ„์˜ ์—ฐ๊ฒฐ์€ ๋†€๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , ์ด๊ฒƒ์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ˆœ๊ฐ„ ์ตœ๋Œ“๊ฐ’์ด 177๊นŒ์ง€ ํŠ„ ์ ์ด ์žˆ๋Š”๋ฐ, ์ด ์ˆœ๊ฐ„์ด ๋ฐ”๋กœ ํ™œ์„ฑ์ด ํ•œ๊บผ๋ฒˆ์— ๋ชฐ๋ฆฐ ์œ„ํ—˜ ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๊ฒฝ๊ณ  30, ์œ„ํ—˜ 40. ํ™œ์„ฑ์ด ๊ฐ‘์ž๊ธฐ ์ˆ˜์‹ญ ๊ฐœ๋กœ ๋›ฐ๋ฉด ์ฟผ๋ฆฌ๋“ค์ด ๋นจ๋ฆฌ ๋๋‚˜์ง€ ๋ชปํ•˜๊ณ  ์Œ“์ด๊ณ  ์žˆ๋‹ค๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค. ๊ด€์ธก ์ตœ๋Œ“๊ฐ’ 177์€ ์ž„๊ณ„๋ฅผ ํฌ๊ฒŒ ๋„˜๊ธด ๊ฐ’์ž…๋‹ˆ๋‹ค.
  • ์ฝ๋Š” ๋ฒ•: "์—ฐ๊ฒฐ(Numbackends)์€ ๊ทธ๋Œ€๋กœ์ธ๋ฐ ํ™œ์„ฑ๋งŒ ๋›ฐ์—ˆ๋‹ค" ๋ฉด ์ฟผ๋ฆฌ๊ฐ€ ๋А๋ ค์ง„ ๊ฒƒ์ด๊ณ , "์—ฐ๊ฒฐ๋„ ๊ฐ™์ด ๋›ฐ์—ˆ๋‹ค" ๋ฉด ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ตฌ๋ถ„์ด ์›์ธ ์ถ”์ ์˜ ์ถœ๋ฐœ์ ์ž…๋‹ˆ๋‹ค.

ํ™œ์„ฑ backend๊ฐ€ ๊ฐ‘์ž๊ธฐ ์˜ค๋ฅด๋Š” ํ”ํ•œ ์›์ธ์€, ์–ด๋–ค ๋ฌด๊ฑฐ์šด ์ฟผ๋ฆฌ๊ฐ€ ๋ฐฐํฌ๋˜์–ด ๊ทธ ์ฟผ๋ฆฌ๋ฅผ ๋Œ๋ฆฌ๋Š” backend๋“ค์ด ๋™์‹œ์— ์˜ค๋ž˜ ๋จธ๋ฌด๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

-- ์ง€๊ธˆ active ์ƒํƒœ์ธ backend๋ฅผ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ ์ˆœ์„œ๋กœ
SELECT pid, usename, state,
       now() - query_start AS running_for,
       wait_event_type, wait_event, query
FROM   pg_stat_activity
WHERE  state = 'active'
  AND  backend_type = 'client backend'
ORDER  BY running_for DESC;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: CPU·Blks Read๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๋А๋ฆฐ(ํ’€ ์Šค์บ”) ์ฟผ๋ฆฌ๊ฐ€ ์•ˆ ๋๋‚˜๊ณ  ์Œ“์ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Locks Waiting์ด ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๋ฝ ๋Œ€๊ธฐ๋กœ ํ™œ์„ฑ์ด ๋ง‰ํ˜€ ์Œ“์ธ ๊ฒƒ(์ฟผ๋ฆฌ ์ž์ฒด๋ณด๋‹ค ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ์›์ธ). Numbackends๊ฐ€ ๊ฐ™์ด ๋›ฐ๋ฉด → ํŠธ๋ž˜ํ”ฝ ๊ธ‰์ฆ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ํ™œ์„ฑ backend๋Š” ์ฟผ๋ฆฌ ํ•˜๋‚˜ํ•˜๋‚˜์˜ ์‘๋‹ต ์†๋„์— ์ง์ ‘ ์ขŒ์šฐ๋ฉ๋‹ˆ๋‹ค. ๋А๋ฆฐ ์ฟผ๋ฆฌ ํ•œ ์ข…๋ฅ˜๊ฐ€ ๋ฐฐํฌ๋˜๋ฉด ๊ทธ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” backend๋“ค์ด ๋™์‹œ์— ์˜ค๋ž˜ ๋จธ๋ฌผ๋Ÿฌ ํ™œ์„ฑ ์ˆ˜๊ฐ€ ํ•œ๊บผ๋ฒˆ์— ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ์‘๋‹ต ์‹œ๊ฐ„์„ ์งง๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ(์ธ๋ฑ์Šค·์ ์ • ๊ฒฐ๊ณผ ํฌ๊ธฐ)์ด ํ™œ์„ฑ ์ˆ˜๋ฅผ ๋‚ฎ๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ทผ๋ณธ ๋Œ€์ฑ…์ž…๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ํ‰์†Œ ํ™œ์„ฑ backend๊ฐ€ 1~2์˜€๋Š”๋ฐ ์–ด๋А ๋ฐฐํฌ ์งํ›„ ๊ฐ‘์ž๊ธฐ ์ˆ˜์‹ญ~177๋กœ ์น˜์†Ÿ์•˜๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. pg_stat_activity๋กœ ์žก์•„ ๋ณด๋‹ˆ ๊ฐ™์€ query๋ฅผ ๊ฐ€์ง„ backend๋“ค์ด ์ˆ˜์‹ญ ๊ฐœ์”ฉ ๋™์‹œ์— active๋กœ ๋–  ์žˆ๊ณ , ๊ทธ ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ํ’€ ์Šค์บ”์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํ•œ ์š”์ฒญ์ด ๋А๋ ค์ง€์ž ๋’ค๋”ฐ๋ผ ๋“ค์–ด์˜จ ์š”์ฒญ๋“ค์ด ๋๋‚˜์ง€ ๋ชปํ•˜๊ณ  ์Œ“์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋‹ˆ ํ™œ์„ฑ backend๊ฐ€ ๋‹ค์‹œ 1~2๋กœ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. ๊ด€์ธก ์ตœ๋Œ“๊ฐ’ 177์€ ์ด๋Ÿฐ "๋А๋ฆฐ ์ฟผ๋ฆฌ๊ฐ€ ๋™์‹œ์— ๋ชฐ๋ฆฐ" ์ˆœ๊ฐ„์˜ ํ”์ ์ž…๋‹ˆ๋‹ค.

Numbackends (๊ฐœ)

์ง€๊ธˆ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” ์ „์ฒด backend ์ˆ˜์ž…๋‹ˆ๋‹ค. ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•˜๋Š”(idle) backend๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. (delta๋กœ ํ‘œ๊ธฐ๋˜์ง€๋งŒ ์‹ค์งˆ์ ์œผ๋กœ ํ˜„์žฌ ์—ฐ๊ฒฐ ์ˆ˜๋ฅผ ๋ด…๋‹ˆ๋‹ค.)

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 837, ๋ฒ”์œ„ 726 ~ 1,385. ์ปค๋„ฅ์…˜ ํ’€์ด ํฐ ํ™˜๊ฒฝ์ด๋ผ ์ˆ˜๋ฐฑ ๊ฐœ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ฑ„ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ ์ˆ˜ ์ž์ฒด๋ณด๋‹ค "ํ‰์†Œ ์ˆ˜์ค€์—์„œ ๋ฒ—์–ด๋‚ฌ๋Š”๊ฐ€" ๊ฐ€ ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ์—ฐ๊ฒฐ ๋ˆ„์ˆ˜(๋ฐ˜๋‚ฉ ์•ˆ ๋œ ์—ฐ๊ฒฐ), ํ’€ ์„ค์ • ๋ณ€๊ฒฝ, ํŠธ๋ž˜ํ”ฝ ๊ธ‰์ฆ.
-- ์ƒํƒœ๋ณ„·์‚ฌ์šฉ์ž๋ณ„ ์—ฐ๊ฒฐ ์ˆ˜ (idle๊ฐ€ ํ•œ์ชฝ์œผ๋กœ ์Œ“์ด๋ฉด ๋ˆ„์ˆ˜ ๋‹จ์„œ)
SELECT usename, state, COUNT(*) AS cnt
FROM   pg_stat_activity
WHERE  backend_type = 'client backend'
GROUP  BY usename, state
ORDER  BY cnt DESC;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Active Backend๋Š” ๊ทธ๋Œ€๋กœ์ธ๋ฐ Numbackends๋งŒ ์šฐ์ƒํ–ฅํ•˜๋ฉด → ์ผ ์•ˆ ํ•˜๋Š” idle ์—ฐ๊ฒฐ์ด ์Œ“์ด๋Š” ๋ˆ„์ˆ˜์ž…๋‹ˆ๋‹ค. Connection Ratio๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → max_connections ํ•œ๋„์— ๊ฐ€๊นŒ์›Œ์ง€๋Š” ๊ฒƒ์ด๋ผ ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค. Free Memory๊ฐ€ ๊ฐ™์ด ์ค„๋ฉด → backend ํ”„๋กœ์„ธ์Šค๋งˆ๋‹ค ์“ฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ˆ„์ ๋˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ๋ฅผ ๋„ˆ๋ฌด ํฌ๊ฒŒ ์žก๊ฑฐ๋‚˜, ์˜ˆ์™ธ ๊ฒฝ๋กœ์—์„œ ์—ฐ๊ฒฐ์„ ๋ฐ˜๋‚ฉํ•˜์ง€ ์•Š์œผ๋ฉด(try-with-resources๋‚˜ finally ๋ˆ„๋ฝ) ์—ฐ๊ฒฐ์ด ๊ณ„์† ์Œ“์ž…๋‹ˆ๋‹ค. PostgreSQL์€ ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋„์›Œ ๋น„์šฉ์ด ํฌ๋ฏ€๋กœ, ํ’€ ํฌ๊ธฐ๋Š” max_connections์™€ ํ•จ๊ป˜ ์‹ ์ค‘ํžˆ ์„ค๊ณ„ํ•ด์•ผ ํ•˜๊ณ , ์—ฐ๊ฒฐ์ด ๋งŽ์ด ํ•„์š”ํ•˜๋ฉด PgBouncer ๊ฐ™์€ ํ’€๋Ÿฌ๋ฅผ ์•ž๋‹จ์— ๋‘๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.

Connection Ratio (%)

์—ฐ๊ฒฐ ์‚ฌ์šฉ๋ฅ ์ž…๋‹ˆ๋‹ค. ์‚ฐ์‹์€ numbackends / max_connections * 100, ์ฆ‰ "ํ—ˆ์šฉ๋œ ์ตœ๋Œ€ ์—ฐ๊ฒฐ ์ค‘ ๋ช‡ %๋ฅผ ์“ฐ๋‚˜" ์ž…๋‹ˆ๋‹ค. ์ฃผ์ฐจ์žฅ ๋งŒ์ฐจ์œจ๊ณผ ๊ฐ™์•„์„œ, 100%๋ฉด ์ƒˆ ์ฐจ(์—ฐ๊ฒฐ)๊ฐ€ ๋ชป ๋“ค์–ด์˜ต๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 16.8%, ๋ฒ”์œ„ 14.5 ~ 27.7%. ์ตœ๋Œ€ ์—ฐ๊ฒฐ ๋Œ€๋น„ ์—ฌ์œ ๊ฐ€ ๋งŽ์€ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๊ฒฝ๊ณ  85%, ์œ„ํ—˜ 90%. 100%์— ๋„๋‹ฌํ•˜๋ฉด ์ƒˆ ์—ฐ๊ฒฐ์ด ๊ฑฐ๋ถ€๋˜์–ด "too many clients already" ์—๋Ÿฌ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์žฅ์• ๋กœ ์ง๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ์—ฐ๊ฒฐ ๋ˆ„์ˆ˜, ํ’€ ํฌ๊ธฐ ๊ณผ๋‹ค ์„ค์ •, max_connections๊ฐ€ ๋„ˆ๋ฌด ์ž‘๊ฒŒ ์žกํž˜.

์—ฐ๊ฒฐ ๋ˆ„์ˆ˜๋Š” ๋Œ€๊ฐœ ์ฝ”๋“œ์—์„œ "๋นŒ๋ฆฐ ์—ฐ๊ฒฐ์„ ๋ฐ˜๋‚ฉํ•˜์ง€ ์•Š๋Š”" ๊ฒฝ๋กœ์—์„œ ์ƒ๊น๋‹ˆ๋‹ค.

-- (๊ฐœ๋…์šฉ ์˜์‚ฌ์ฝ”๋“œ) ๋‚˜์œ ์˜ˆ: ์˜ˆ์™ธ๊ฐ€ ๋‚˜๋ฉด ์—ฐ๊ฒฐ์„ ๋‹ซ์ง€ ๋ชปํ•˜๊ณ  ์ƒŒ๋‹ค
-- conn = pool.getConnection();
-- stmt.executeQuery(...);   // ์—ฌ๊ธฐ์„œ ์˜ˆ์™ธ๊ฐ€ ๋‚˜๋ฉด
-- conn.close();             // ์ด ์ค„์— ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•œ๋‹ค → ์—ฐ๊ฒฐ ๋ˆ„์ˆ˜
-- ๊ณ ์นœ ์˜ˆ: try-with-resources / finally ๋กœ ๋ฐ˜๋“œ์‹œ ๋ฐ˜๋‚ฉ
-- try (Connection conn = pool.getConnection()) {
--     ... ์ฟผ๋ฆฌ ...
-- }  // ๋ธ”๋ก์„ ๋ฒ—์–ด๋‚˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋‚˜๋„ conn์ด ์ž๋™ close ๋œ๋‹ค
-- ํ˜„์žฌ ์‚ฌ์šฉ๋ฅ  ์ง์ ‘ ๊ณ„์‚ฐ
SELECT
  (SELECT COUNT(*) FROM pg_stat_activity) AS connected,
  setting::int AS max_conn,
  ROUND((SELECT COUNT(*) FROM pg_stat_activity)::numeric
        / setting::int * 100, 2) AS usage_pct
FROM pg_settings
WHERE name = 'max_connections';
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Numbackends๊ฐ€ ํ•จ๊ป˜ ์šฐ์ƒํ–ฅํ•˜๋ฉด → ์—ฐ๊ฒฐ ๋ˆ„์ˆ˜๊ฐ€ ์‚ฌ์šฉ๋ฅ ์„ ๋ฐ€์–ด ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Active Backend๋Š” ๋‚ฎ์€๋ฐ ์‚ฌ์šฉ๋ฅ ๋งŒ ์˜ค๋ฅด๋ฉด → idle ์—ฐ๊ฒฐ์ด ์Œ“์—ฌ ํ•œ๋„๋ฅผ ์ž ์‹ํ•˜๋Š” ๊ฒƒ(๋ˆ„์ˆ˜ ๊ฐ€๋Šฅ์„ฑ)์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์‚ฌ์šฉ๋ฅ ์€ ๊ฒฐ๊ตญ ํ˜„์žฌ ์—ฐ๊ฒฐ / max_connections์ด๋ฏ€๋กœ, ์—ฐ๊ฒฐ ๋ฐ˜๋‚ฉ ๋ˆ„๋ฝ์ด ์žˆ์œผ๋ฉด ๋ถ„์ž๊ฐ€ ๊พธ์ค€ํžˆ ์šฐ์ƒํ–ฅํ•ฉ๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ์€ ๋นŒ๋ฆฌ๋ฉด ๋ฐ˜๋“œ์‹œ ๋ฐ˜๋‚ฉ๋˜๋Š” ๊ตฌ์กฐ(try-with-resources/finally)๋กœ ์“ฐ๊ณ , ํ’€๊ณผ max_connections๋ฅผ ํ•จ๊ป˜ ์„ค๊ณ„ํ•ด ์—ฌ์œ ๋ฅผ ๋‘ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋ฅ ์ด ์„œ์„œํžˆ ์šฐ์ƒํ–ฅํ•˜๋Š” ๊ทธ๋ž˜ํ”„ ์ž์ฒด๊ฐ€ ๋ˆ„์ˆ˜ ์ฝ”๋“œ์˜ ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ๊ฐ€์žฅ ํ”ํ•œ ์žฅ์•  ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—ฐ๊ฒฐ์„ ์“ฐ๊ณ  ๋ฐ˜๋‚ฉํ•˜์ง€ ์•Š์œผ๋ฉด ์—ฐ๊ฒฐ์ด ํ•˜๋‚˜์”ฉ ์ƒˆ์–ด ๋‚˜๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ๋ž˜ํ”„์ƒ Connection Ratio๊ฐ€ ์„œ์„œํžˆ ์šฐ์ƒํ–ฅํ•˜๋‹ค๊ฐ€, 100%์— ๋‹ฟ๋Š” ์ˆœ๊ฐ„ ์‹ ๊ทœ ์š”์ฒญ์ด ์ „๋ถ€ "too many clients already" ๋กœ ์‹คํŒจํ•˜๋ฉฐ ์„œ๋น„์Šค๊ฐ€ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. ์žฌ๊ธฐ๋™ํ•˜๋ฉด ์ผ์‹œ ๋ณต๊ตฌ๋˜์ง€๋งŒ ๋ˆ„์ˆ˜ ์ฝ”๋“œ๋ฅผ ๋ชป ์žก์œผ๋ฉด ๋ฉฐ์น  ๋’ค ๊ฐ™์€ ์‹œ์ ์— ๋˜ ํ„ฐ์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ "์œ„ํ—˜์„ ์„ ๋„˜์—ˆ๋‚˜" ๋ฟ ์•„๋‹ˆ๋ผ "๊พธ์ค€ํžˆ ์šฐ์ƒํ–ฅํ•˜๋Š”๊ฐ€" ๋ฅผ ๊ฐ™์ด ๋ด…๋‹ˆ๋‹ค.

Long Active Backend (๊ฐœ)

๋จผ์ € ์šฉ์–ด๋ถ€ํ„ฐ ํ’€์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. backend๋Š” PostgreSQL์ด ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ํ•˜๋‚˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๊ณ  ๋„์šฐ๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ backend๊ฐ€ ์ฟผ๋ฆฌ ํ•˜๋‚˜๋ฅผ 5์ดˆ๊ฐ€ ๋„˜๋„๋ก ๋๋‚ด์ง€ ๋ชปํ•˜๊ณ  ๋ถ™์žก๊ณ  ์žˆ์„ ๋•Œ, ์ด๊ฒƒ์„ "์žฅ๊ธฐ ์‹คํ–‰ backend" ๋กœ ์…‰๋‹ˆ๋‹ค.

๋ณดํ†ต์˜ ์ฟผ๋ฆฌ๋Š” ์ˆ˜ ๋ฐ€๋ฆฌ์ดˆ๋ฉด ๋๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ํ•œ ์ฟผ๋ฆฌ๊ฐ€ 5์ดˆ์”ฉ ๊ฑธ๋ฆฐ๋‹ค๋Š” ๊ฒƒ์€, ๊ทธ๋™์•ˆ ๊ทธ ์—ฐ๊ฒฐ์ด ๊ณ„์† ๋ฌถ์—ฌ ์žˆ๊ณ  CPU·๋ฉ”๋ชจ๋ฆฌ·๋””์Šคํฌ๋ฅผ ์žก์•„๋จน์œผ๋ฉฐ, ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ฟผ๋ฆฌ๊นŒ์ง€ ๋ง‰๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ณ„์‚ฐ๋Œ€์—์„œ ํ•œ ์†๋‹˜์ด 5์ดˆ ๋„˜๊ฒŒ ์•ˆ ๋๋‚˜๋ฉด ๋’ค์— ์ค„์ด ์ƒ๊ธฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 0.02(๋ฒ”์œ„ 0 ~ 2). 0์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๊ฒฝ๊ณ  1, ์œ„ํ—˜ 2. 1๊ฐœ๋งŒ ๋‚˜ํƒ€๋‚˜๋„ ๋“ค์—ฌ๋‹ค๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ์ƒํ™ฉ์—์„œ ์ƒ๊ธฐ๋‚˜ — ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ๋ฒ”์ธ์ธ๊ฐ€

๋Œ€๋ถ€๋ถ„์€ ์ธ๋ฑ์Šค๋ฅผ ์ œ๋Œ€๋กœ ํƒ€์ง€ ๋ชปํ•ด ํ…Œ์ด๋ธ”์„ ํ†ต์งธ๋กœ ํ›‘๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋Š” ์ฑ… ๋’ค์˜ ์ƒ‰์ธ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ƒ‰์ธ์ด ์žˆ์œผ๋ฉด ์›ํ•˜๋Š” ํ•ญ๋ชฉ์„ ๋ฐ”๋กœ ํŽด๊ณ , ์—†์œผ๋ฉด ์ฒซ ์žฅ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋„˜๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์ ์„ ๋• ๋๊นŒ์ง€ ๋„˜๊ฒจ๋„ ๊ธˆ๋ฐฉ์ด์ง€๋งŒ, ์ˆ˜๋ฐฑ๋งŒ ํ–‰์ด ๋˜๋ฉด 5์ดˆ, 10์ดˆ๋กœ ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค. ์‹ค๋ฌด์—์„œ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์œ ํ˜•์„ ์ฝ”๋“œ๋กœ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

(1) WHERE ์กฐ๊ฑด ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ

-- phone ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๊ฐ€ ์—†์œผ๋ฉด, ํšŒ์› 500๋งŒ ๋ช…์„ ์ „๋ถ€ ํ›‘๋Š”๋‹ค
SELECT * FROM members WHERE phone = '010-1234-5678';

(2) LIKE ์•ž์— ์™€์ผ๋“œ์นด๋“œ(%)๊ฐ€ ๋ถ™์€ ๊ฒฝ์šฐ

-- 'name%' ์€ ์ธ๋ฑ์Šค๋ฅผ ์“ธ ์ˆ˜ ์žˆ์ง€๋งŒ, '%...%' ๋Š” ์ธ๋ฑ์Šค๋ฅผ ๋ชป ์“ฐ๊ณ  ์ „์ฒด๋ฅผ ์Šค์บ”ํ•œ๋‹ค
SELECT * FROM products WHERE name LIKE '%์ผ€์ด์Šค%';

๋ถ€๋ถ„ ๊ฒ€์ƒ‰์ด ๊ผญ ํ•„์š”ํ•˜๋ฉด PostgreSQL์˜ ์ „๋ฌธ ๊ฒ€์ƒ‰(tsvector/GIN ์ธ๋ฑ์Šค)์ด๋‚˜ pg_trgm ํ™•์žฅ์œผ๋กœ ํ‘ธ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

(3) ์ปฌ๋Ÿผ์„ ํ•จ์ˆ˜๋กœ ๊ฐ์‹ผ ๊ฒฝ์šฐ

-- created_at์— ์ธ๋ฑ์Šค๊ฐ€ ์žˆ์–ด๋„, ํ•จ์ˆ˜๋กœ ๊ฐ์‹ธ๋ฉด ์ธ๋ฑ์Šค๊ฐ€ ๋ฌด๋ ฅํ™”๋œ๋‹ค
SELECT * FROM orders WHERE date(created_at) = '2026-06-18';

-- ์ด๋ ‡๊ฒŒ ๋ฒ”์œ„๋กœ ๋ฐ”๊พธ๋ฉด ์ธ๋ฑ์Šค๋ฅผ ํƒ„๋‹ค
SELECT * FROM orders
WHERE created_at >= TIMESTAMP '2026-06-18 00:00:00'
  AND created_at <  TIMESTAMP '2026-06-19 00:00:00';

(4) ๊นŠ์€ ํŽ˜์ด์ง•(OFFSET์ด ํฐ ๊ฒฝ์šฐ)

-- 100๋งŒ ๊ฑด์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  20๊ฑด์„ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด, 100๋งŒ ๊ฑด์„ ๋‹ค ์ฝ์–ด์•ผ ํ•œ๋‹ค
SELECT * FROM posts ORDER BY id OFFSET 1000000 LIMIT 20;

-- ๊ณ ์นœ ์˜ˆ: ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ณธ id ๊ธฐ์ค€์œผ๋กœ ์ž˜๋ผ ์ฝ๋Š”๋‹ค(keyset ํŽ˜์ด์ง•)
SELECT * FROM posts WHERE id > 1000000 ORDER BY id LIMIT 20;

(5) ๋Œ€๋Ÿ‰ UPDATE / DELETE

-- ์กฐ๊ฑด์— ๊ฑธ๋ฆฌ๋Š” ์ˆ˜๋ฐฑ๋งŒ ํ–‰์„ ํ•œ ๋ฒˆ์— ์ง€์šฐ๋ฉด, ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฌถ์ด๊ณ  ๋ฝ๋„ ์˜ค๋ž˜ ์žก์œผ๋ฉฐ
-- ์ฃฝ์€ ํ–‰(dead tuple)๋„ ํ•œ๊บผ๋ฒˆ์— ์Ÿ์•„์ง„๋‹ค
DELETE FROM access_logs WHERE created_at < '2025-01-01';

PostgreSQL์—์„œ๋Š” ๋Œ€๋Ÿ‰ DELETE/UPDATE๊ฐ€ ์ฃฝ์€ ํ–‰์„ ํ•œ๊บผ๋ฒˆ์— ๋งŒ๋“ค์–ด ์ดํ›„ autovacuum ๋ถ€๋‹ด๊นŒ์ง€ ํ‚ค์šฐ๋ฏ€๋กœ, ๋ช‡ ์ฒœ ๊ฑด์”ฉ ๋‚˜๋ˆ ์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ํŠนํžˆ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ™•์ธํ•˜๋‚˜

์žฅ๊ธฐ ์‹คํ–‰ backend๊ฐ€ ๋ณด์ด๋ฉด, ๋จผ์ € ์ง€๊ธˆ ๋ฌด์—‡์ด ์˜ค๋ž˜ ๋Œ๊ณ  ์žˆ๋Š”์ง€ ์ฐพ์Šต๋‹ˆ๋‹ค.

-- 5์ดˆ ๋„˜๊ฒŒ ์‹คํ–‰ ์ค‘์ธ ์ฟผ๋ฆฌ๋งŒ ๊ณจ๋ผ ๋ณธ๋‹ค
SELECT pid, usename, now() - query_start AS running_for,
       wait_event_type, wait_event, query
FROM   pg_stat_activity
WHERE  state = 'active'
  AND  now() - query_start > interval '5 seconds'
ORDER  BY running_for DESC;

๋ฒ”์ธ ์ฟผ๋ฆฌ๋ฅผ ์ฐพ์•˜์œผ๋ฉด EXPLAIN (ANALYZE, BUFFERS) ๋กœ ์‹คํ–‰ ๊ณ„ํš์„ ๋ด…๋‹ˆ๋‹ค. Seq Scan(์ˆœ์ฐจ ์Šค์บ”)์ด ํฐ ํ…Œ์ด๋ธ”์— ๊ฑธ๋ ค ์žˆ๊ฑฐ๋‚˜ ์ฝ์€ ๋ธ”๋ก ์ˆ˜๊ฐ€ ๋งค์šฐ ํฌ๋ฉด ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM members WHERE phone = '010-1234-5678';
-- ๊ฒฐ๊ณผ์— Seq Scan on members ... rows=5000000 ์ด ๋ณด์ด๋ฉด ํ’€ ์Šค์บ”, ์ธ๋ฑ์Šค ํ•„์š”
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: โ‘  ๋จผ์ € pg_stat_activity์˜ running_for๋กœ ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š”์ง€ ์ฐพ๊ณ  EXPLAIN์œผ๋กœ ์ˆœ์ฐจ ์Šค์บ”์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. โ‘ก CPU·Blks Read๊ฐ€ ๋™๋ฐ˜ ์ƒ์Šน์ด๋ฉด → ํ’€ ์Šค์บ”/๋ฌด๊ฑฐ์šด ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. โ‘ข Locks Waiting์ด ๋™๋ฐ˜์ด๋ฉด → ๋ฝ ๋Œ€๊ธฐ(์ฟผ๋ฆฌ ์ž์ฒด๋ณด๋‹ค ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ๋ง‰์€ ๊ฒƒ)์ž…๋‹ˆ๋‹ค. โ‘ฃ Active Backend๊ฐ€ ๊ฐ™์ด ์Œ“์ด๋ฉด → ๋А๋ฆฐ ์ฟผ๋ฆฌ๊ฐ€ ๋’ค๋ฅผ ๋ง‰๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์žฅ๊ธฐ ์‹คํ–‰ ์ฟผ๋ฆฌ๋Š” ๋Œ€๋ถ€๋ถ„ ORM์ด๋‚˜ ์ง์ ‘ ์ž‘์„ฑํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ๋ฐ์„œ ๋‚˜์˜ต๋‹ˆ๋‹ค. ์กฐํšŒ ์กฐ๊ฑด ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๊ฐ€ ์—†๊ฑฐ๋‚˜, ํ•จ์ˆ˜๋กœ ์ปฌ๋Ÿผ์„ ๊ฐ์‹ธ๊ฑฐ๋‚˜, ๊นŠ์€ OFFSET ํŽ˜์ด์ง•์„ ์“ฐ๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์Œ“์ผ์ˆ˜๋ก ์–ด๋А ๋‚  ๊ฐ‘์ž๊ธฐ ๋А๋ ค์ง‘๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์งค ๋•Œ ์กฐํšŒ ์กฐ๊ฑด๊ณผ ์ •๋ ฌ ์ปฌ๋Ÿผ์˜ ์ธ๋ฑ์Šค ์„ค๊ณ„๋ฅผ ๋จผ์ € ์ฑ™๊ธฐ๊ณ , ๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ์€ ํ•œ ๋ฒˆ์— ํ•˜์ง€ ๋ง๊ณ  ๋‚˜๋ˆ ์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ์ถœ์‹œ ์ดˆ๊ธฐ์—๋Š” ๋ชจ๋“  ํ™”๋ฉด์ด ๋นจ๋ž๋Š”๋ฐ ๋ช‡ ๋‹ฌ ๋’ค ํŠน์ • ๊ฒ€์ƒ‰ ํ™”๋ฉด๋งŒ ๋А๋ ค์กŒ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…๋‹ˆ๋‹ค. ๋ชจ๋‹ˆํ„ฐ๋ง์„ ๋ณด๋ฉด ๊ทธ ์‹œ๊ฐ„๋Œ€์— Long Active Backend๊ฐ€ 1~2๋กœ ์˜ฌ๋ผ์˜ค๊ณ  CPU์™€ Blks Read๋„ ๊ฐ™์ด ๋œ๋‹ˆ๋‹ค. pg_stat_activity๋กœ ์žก์•„ ๋ณด๋‹ˆ, ์ธ๋ฑ์Šค ์—†๋Š” ์ปฌ๋Ÿผ์„ ์กฐ๊ฑด์œผ๋กœ ๊ฑด ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๊ฐ€ ๋งค๋ฒˆ ์ˆ˜๋ฐฑ๋งŒ ํ–‰์„ ์ˆœ์ฐจ ์Šค์บ”ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์ ๋˜ ์ดˆ๊ธฐ์—๋Š” 0.01์ดˆ์˜€๋˜ ์ฟผ๋ฆฌ๊ฐ€, ๋ฐ์ดํ„ฐ๊ฐ€ ์Œ“์ด๋ฉด์„œ 5์ดˆ๋กœ ๋Š˜์–ด๋‚œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜์ž Long Active Backend๋Š” ๋‹ค์‹œ 0์œผ๋กœ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. ์žฅ๊ธฐ ์‹คํ–‰ backend๋Š” ์ด๋ ‡๊ฒŒ "๋А๋ ค์ง„ ์ฟผ๋ฆฌ๊ฐ€ ์žˆ๋‹ค" ๋Š” ๊ฐ€์žฅ ๋จผ์ € ์ผœ์ง€๋Š” ๊ฒฝ๊ณ ๋“ฑ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

Locks Waiting (๊ฐœ)

์ง€๊ธˆ ๋ฝ์„ ์–ป์œผ๋ ค๊ณ  ๋Œ€๊ธฐ ์ค‘์ธ ์ „์ฒด backend ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ฝ ๊ฒฝํ•ฉ์„ ์ง์ ‘ ๋ณด์—ฌ ์ฃผ๋Š” ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค. (๋ฝ ์ž์ฒด๋Š” ์•„๋ž˜ 6๋ฒˆ ๋ฝ ์„น์…˜์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค.)

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 0.003, ๋ฒ”์œ„ 0 ~ 5. 0์ด ์ •์ƒ์ด๊ณ , 0์ด ์•„๋‹ˆ๋ฉด ์ง€๊ธˆ ๋ˆ„๊ตฐ๊ฐ€ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜ ๋•Œ๋ฌธ์— ๋ง‰ํ˜€ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๊ฒฝ๊ณ  1, ์œ„ํ—˜ 2. ์ž‘์€ ๊ฐ’์ด๋ผ๋„ ๋ฐ˜๋ณต๋˜๋ฉด ํŠน์ • ์ฟผ๋ฆฌ·ํŠธ๋žœ์žญ์…˜์ด ์ž์ฃผ ์ถฉ๋Œํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ํ•œ ํŠธ๋žœ์žญ์…˜์ด ํ–‰์„ ์ฅ” ์ฑ„ ์ปค๋ฐ‹์„ ๋ฏธ๋ฃธ(ํŠนํžˆ idle in transaction), ๊ฐ™์€ ํ–‰์— ๋Œ€ํ•œ ๋™์‹œ ์ˆ˜์ • ๊ฒฝํ•ฉ.
-- ์ง€๊ธˆ ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” backend์™€, ๋ˆ„๊ฐ€ ๋ง‰๊ณ  ์žˆ๋Š”์ง€ (PostgreSQL 9.6+ ๋‚ด์žฅ ํ•จ์ˆ˜)
SELECT pid, pg_blocking_pids(pid) AS blocked_by, state, query
FROM   pg_stat_activity
WHERE  cardinality(pg_blocking_pids(pid)) > 0;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Active Backend๊ฐ€ ๊ฐ™์ด ์Œ“์ด๋ฉด → ๋Œ€๊ธฐ๊ฐ€ ๋ถ€ํ•˜๋กœ ๋ฒˆ์ง€๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. Deadlocks๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๊ฒฝํ•ฉ์ด ๊ต์ฐฉ์œผ๋กœ ๋ฒˆ์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋ถ„์„์€ 6๋ฒˆ ๋ฝ ์„น์…˜์„ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ๋Œ€๊ธฐ backend๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋ˆ„๊ตฐ๊ฐ€ ๋ฝ์„ ์˜ค๋ž˜ ์ฅ๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต ๋ฝ์„ ์žก์€ ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹์„ ๋ฏธ๋ฃจ๋Š” ๊ฒฝ์šฐ(ํŠนํžˆ ํŠธ๋žœ์žญ์…˜์„ ์—ฐ ์ฑ„ ๋…ธ๋Š” idle in transaction)์ด๋ฏ€๋กœ, ๋ณ€๊ฒฝ ํ›„ ์ฆ‰์‹œ ์ปค๋ฐ‹ํ•˜๋„๋ก ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„๋ฅผ ์ขํžˆ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.


3. ํŠธ๋žœ์žญ์…˜ · ์ฒ˜๋ฆฌ๋Ÿ‰

์ด ์˜์—ญ์€ PostgreSQL์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ํŠธ๋žœ์žญ์…˜์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ทธ ๊ณผ์ •์—์„œ ํ–‰์„ ์–ผ๋งˆ๋‚˜ ์ฝ๊ณ  ์“ฐ๋Š”์ง€๋ฅผ ๋ด…๋‹ˆ๋‹ค. ๊ฐ€๊ฒŒ์˜ ํ’ˆ๋ชฉ๋ณ„ ํŒ๋งค ๊ฑด์ˆ˜ ๊ฐ™์€ ๊ฒƒ์ด๋ผ, ์ ˆ๋Œ€๊ฐ’๋ณด๋‹ค ํ‰์†Œ ๋Œ€๋น„ ํŒจํ„ด์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๋จผ์ € ์šฉ์–ด๋ฅผ ์งš์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ํŠธ๋žœ์žญ์…˜(Transaction): ์—ฌ๋Ÿฌ DB ์ž‘์—…์„ "์ „๋ถ€ ์„ฑ๊ณต ์•„๋‹ˆ๋ฉด ์ „๋ถ€ ์ทจ์†Œ" ๋กœ ๋ฌถ์€ ํ•œ ๋ฌถ์Œ์ž…๋‹ˆ๋‹ค. ๋‹ค ์ž˜ ๋์œผ๋ฉด COMMIT, ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ROLLBACK ํ•ฉ๋‹ˆ๋‹ค.
  • ํŠœํ”Œ(tuple): PostgreSQL์—์„œ "ํ–‰(row)" ์„ ๋ถ€๋ฅด๋Š” ๋ง์ž…๋‹ˆ๋‹ค. Tup์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ง€ํ‘œ(Tup Fetched·Returned·Inserted·Updated·Deleted)๋Š” ๋ชจ๋‘ "๋ช‡ ๊ฐœ์˜ ํ–‰์„ ๋‹ค๋ค˜๋‚˜" ๋ฅผ ์…‰๋‹ˆ๋‹ค.
  • sigma ์ง€ํ‘œ: ์ด ์˜์—ญ ๋‹ค์ˆ˜ ์ง€ํ‘œ ์•ž์— ๋ถ™์€ (sigma) ๋Š” ๋ˆ„์  ์นด์šดํ„ฐ์˜ ๊ตฌ๊ฐ„ ํ•ฉ์„ ๋œปํ•ฉ๋‹ˆ๋‹ค. 1๋ถ„ ๋™์•ˆ ๋ฐœ์ƒํ•œ ์–‘์„ ๋”ํ•œ ๊ฐ’์œผ๋กœ ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

TPS (๊ฑด/์ดˆ)

์ดˆ๋‹น ํŠธ๋žœ์žญ์…˜ ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ปค๋ฐ‹·๋กค๋ฐฑ์œผ๋กœ ๋๋‚œ ํŠธ๋žœ์žญ์…˜์„ ์ดˆ๋‹น ๋‹จ์œ„๋กœ ๋ณธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 799, ๋ฒ”์œ„ 0 ~ 47,500. ํ‰์†Œ์—๋„ ๊ฝค ๋†’๊ณ , ์ˆœ๊ฐ„ 4๋งŒ์„ ๋„˜๊ธด ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. PostgreSQL ์ธ์Šคํ„ด์Šค๊ฐ€ MySQL·Oracle๋ณด๋‹ค ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ํ›จ์”ฌ ๋†’์€ ํ™˜๊ฒฝ์ž„์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ๋Œ€๋Ÿ‰ ๋ฐฐ์น˜(์žฆ์€ ๋‹จ๊ฑด ์ปค๋ฐ‹), ํŠธ๋ž˜ํ”ฝ ๊ธ‰์ฆ, ํ•œ ์ž‘์—…์„ ์ž˜๊ฒŒ ์ชผ๊ฐœ ์ปค๋ฐ‹ํ•˜๋Š” ์ฝ”๋“œ.

์“ฐ๊ธฐ ์ชฝ TPS๊ฐ€ ๋น„์ •์ƒ์ ์œผ๋กœ ๋†’์€ ํ”ํ•œ ์›์ธ์€ ํ•œ ๊ฑด์”ฉ ์ปค๋ฐ‹ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: ํ•œ ๊ฑด์”ฉ INSERT + ๋งค ๊ฑด COMMIT (ํŠธ๋žœ์žญ์…˜ ์ˆ˜๊ฐ€ ํญ์ฆ)
-- ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฃจํ”„๋ฅผ ๋Œ๋ฉฐ ๋งค ๊ฑด ์ปค๋ฐ‹ํ•˜๋ฉด TPS์™€ WAL flush๊ฐ€ ํ•จ๊ป˜ ์น˜์†Ÿ๋Š”๋‹ค
-- for (row : rows) { insert(row); conn.commit(); }
-- ๊ณ ์นœ ์˜ˆ: ์—ฌ๋Ÿฌ ๊ฑด์„ ๋ชจ์•„ ํ•œ ๋ฒˆ์— ์ปค๋ฐ‹ (ํŠธ๋žœ์žญ์…˜ ์ˆ˜๊ฐ€ ํฌ๊ฒŒ ์ค€๋‹ค)
-- conn.setAutoCommit(false);
-- for (row : rows) { insert(row); }
-- conn.commit();   // ํ•œ ๋ฒˆ๋งŒ ์ปค๋ฐ‹
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Xact Commit·Xact Rollback์ด ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ํŠธ๋žœ์žญ์…˜ ์ˆ˜ ์ž์ฒด๊ฐ€ ๋Š˜์–ด๋‚œ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์•„๋ž˜). Active Backend·CPU๊ฐ€ ๋™๋ฐ˜์ด๋ฉด → ์‹ค์ œ ๋ถ€ํ•˜ ์ฆ๊ฐ€์ž…๋‹ˆ๋‹ค. Write IOPS๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ์ปค๋ฐ‹์ด ๋””์Šคํฌ ์“ฐ๊ธฐ(WAL flush)๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — TPS๋Š” ์ปค๋ฐ‹·๋กค๋ฐฑ ํšŸ์ˆ˜์— ๋น„๋ก€ํ•ฉ๋‹ˆ๋‹ค. ๋งค ๊ฑด๋งˆ๋‹ค ์ปค๋ฐ‹ํ•˜๋Š” ์ฝ”๋“œ๋Š” ํŠธ๋žœ์žญ์…˜ ์ˆ˜๋ฅผ ์ž˜๊ฒŒ ๋Š˜๋ฆฌ๊ณ  WAL flush ๋ถ€๋‹ด์„ ํ‚ค์›๋‹ˆ๋‹ค. ํ•œ ๋ฌถ์Œ ๋‹จ์œ„๋กœ ์ปค๋ฐ‹ํ•˜๋ฉด TPS์™€ ๋””์Šคํฌ ์“ฐ๊ธฐ ๋ถ€๋‹ด์ด ํ•จ๊ป˜ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ๋‹จ, ๋„ˆ๋ฌด ํฌ๊ฒŒ ๋ฌถ์œผ๋ฉด ๊ทธ ํŠธ๋žœ์žญ์…˜์ด ์˜ค๋ž˜ ์‚ด์•„ ์ฃฝ์€ ํ–‰ ์ •๋ฆฌ(VACUUM)๋ฅผ ๋ง‰์œผ๋ฏ€๋กœ, ์ ๋‹นํ•œ ๋‹จ์œ„(์ˆ˜์ฒœ~์ˆ˜๋งŒ ๊ฑด)๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ๊ท ํ˜•์ ์ž…๋‹ˆ๋‹ค.

Xact Commit (๊ฑด) / Xact Rollback (๊ฑด)

๊ฐ๊ฐ Commit / Rollback์œผ๋กœ ๋๋‚œ ํŠธ๋žœ์žญ์…˜ ์ˆ˜์ž…๋‹ˆ๋‹ค(1๋ถ„ ๊ตฌ๊ฐ„ ํ•ฉ).

  • ๊ด€์ธก๊ฐ’: Xact Commit ํ‰๊ท  ์•ฝ 3,989 / 904 ~ 237,484, Xact Rollback ํ‰๊ท  ์•ฝ 7.1 / 0 ~ 37. ์ปค๋ฐ‹์ด ์••๋„์ ์œผ๋กœ ๋งŽ๊ณ  ๋กค๋ฐฑ์€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค. ์ •์ƒ์ ์ธ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.
  • ์ฝ๋Š” ๋ฒ•: Rollback์ด ํ‰์†Œ๋ณด๋‹ค ๋Š˜๋ฉด ํŠธ๋žœ์žญ์…˜์ด ์ž์ฃผ ์‹คํŒจํ•ด ๋˜๋Œ๋ ค์ง€๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๋ฝ ๊ฒฝํ•ฉ·๊ต์ฐฉ(deadlock)·์ œ์•ฝ์กฐ๊ฑด ์œ„๋ฐ˜·์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์˜ˆ์™ธ ๋“ฑ์„ ์˜์‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: Commit ๊ธ‰์ฆ → ๋Œ€๋Ÿ‰ ๋ฐฐ์น˜·์žฆ์€ ๋‹จ๊ฑด ์ปค๋ฐ‹. Rollback ๊ธ‰์ฆ → ํŠธ๋žœ์žญ์…˜ ์‹คํŒจ ์ฆ๊ฐ€(์—๋Ÿฌ·๊ต์ฐฉ).
-- ์ปค๋ฐ‹/๋กค๋ฐฑ ๋ˆ„์  ์นด์šดํ„ฐ ํ™•์ธ (ํ˜„์žฌ DB ๊ธฐ์ค€)
SELECT datname, xact_commit, xact_rollback
FROM   pg_stat_database
WHERE  datname = current_database();
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Xact Commit·TPS·Write IOPS๊ฐ€ ํ•จ๊ป˜ ์˜ค๋ฅด๋ฉด → ์ •์ƒ์ ์ธ ์“ฐ๊ธฐ ๋ถ€ํ•˜์ž…๋‹ˆ๋‹ค. Xact Rollback์ด Deadlocks·Locks Waiting๊ณผ ํ•จ๊ป˜ ์˜ค๋ฅด๋ฉด → ๊ต์ฐฉ·๋ฝ ๊ฒฝํ•ฉ์œผ๋กœ ํŠธ๋žœ์žญ์…˜์ด ๋˜๋Œ๋ ค์ง€๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ๋กค๋ฐฑ์ด ์žฆ๋‹ค๋Š” ๊ฒƒ์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์‹คํŒจ๋ฅผ ์ž์ฃผ ๋งŒ๋‚œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ต์ฐฉ(deadlock)์œผ๋กœ ์ธํ•œ ๋กค๋ฐฑ์ด๋ผ๋ฉด ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”·ํ–‰์„ ๊ฑด๋“œ๋ฆฌ๋Š” ์ˆœ์„œ๋ฅผ ์ฝ”๋“œ ์ „๋ฐ˜์—์„œ ์ผ์ •ํ•˜๊ฒŒ ๋งž์ถฐ ๊ต์ฐฉ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ž…๋‹ˆ๋‹ค. ์ œ์•ฝ์กฐ๊ฑด ์œ„๋ฐ˜์ด ์žฆ๋‹ค๋ฉด ์‚ฌ์ „ ๊ฒ€์ฆ์„ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.

Trx Time (์ดˆ)

ํŠธ๋žœ์žญ์…˜ ๋น„๊ต ์„œ๋จธ๋ฆฌ ์ง€ํ‘œ๋กœ, ํŠธ๋žœ์žญ์…˜์ด ์ง„ํ–‰๋œ ์‹œ๊ฐ„์„ ๊ฐ€๋Š ํ•˜๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค. ํ•œ ํŠธ๋žœ์žญ์…˜์ด ์–ผ๋งˆ๋‚˜ ์˜ค๋ž˜ ์‚ด์•„ ์žˆ๋Š”์ง€๋ฅผ ๋ด…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 0.24์ดˆ, ๋ฒ”์œ„ 0 ~ 1,017.48์ดˆ. ํ‰์†Œ์—” ๋งค์šฐ ์งง์€๋ฐ ์–ด๋–ค ์ˆœ๊ฐ„ 1,000์ดˆ(์•ฝ 17๋ถ„)๋ฅผ ๋„˜๊ธด ํŠธ๋žœ์žญ์…˜์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธด ํŠธ๋žœ์žญ์…˜์ด ์œ„ํ—˜ ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ํŠธ๋žœ์žญ์…˜์„ ์—ด์–ด ๋‘” ์ฑ„ ์˜ค๋ž˜ ๋ฐฉ์น˜(idle in transaction), ์™ธ๋ถ€ ์ž‘์—…์„ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ๊ธฐ๋‹ค๋ฆผ, ๊ฑฐ๋Œ€ํ•œ ๋‹จ์ผ ํŠธ๋žœ์žญ์…˜.

PostgreSQL์—์„œ ๊ธด ํŠธ๋žœ์žญ์…˜์€ ํŠนํžˆ ์กฐ์‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜์ด ์˜ค๋ž˜ ์‚ด์•„ ์žˆ์œผ๋ฉด ๊ทธ ์‹œ์  ์ดํ›„์˜ ์ฃฝ์€ ํ–‰์„ VACUUM์ด ์ฒญ์†Œํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํŠธ๋žœ์žญ์…˜์ด ์˜› ๋ฒ„์ „์„ ์•„์ง ๋ณผ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ๋ณด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ธด ํŠธ๋žœ์žญ์…˜ ํ•˜๋‚˜๊ฐ€ ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ๊ณผ Age ์ƒ์Šน์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

-- ์˜ค๋ž˜ ์‚ด์•„ ์žˆ๋Š” ํŠธ๋žœ์žญ์…˜ ์ฐพ๊ธฐ (idle in transaction ํฌํ•จ)
SELECT pid, usename, state,
       now() - xact_start AS xact_age,
       now() - state_change AS in_state_for,
       query
FROM   pg_stat_activity
WHERE  xact_start IS NOT NULL
ORDER  BY xact_age DESC;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Current Age·Age Used Ratio๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๊ธด ํŠธ๋žœ์žญ์…˜์ด ์ฃฝ์€ ํ–‰ ์ •๋ฆฌ๋ฅผ ๋ง‰์•„ ๋…ธํ™”๊ฐ€ ์ง„ํ–‰๋˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. Locks Waiting์ด ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๊ทธ ํŠธ๋žœ์žญ์…˜์ด ๋ฝ์„ ์ฅ๊ณ  ์•ˆ ๋†“๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ํŠธ๋žœ์žญ์…˜์€ ์งง๊ฒŒ ๊ฐ€์ ธ๊ฐ€๋Š” ๊ฒƒ์ด PostgreSQL์—์„œ ํŠนํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ์•ˆ์— ์™ธ๋ถ€ API ํ˜ธ์ถœ·ํŒŒ์ผ ์ฒ˜๋ฆฌ·์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋Œ€๊ธฐ ๊ฐ™์€ ๊ธด ์ž‘์—…์„ ๋„ฃ์œผ๋ฉด ๊ทธ ์‹œ๊ฐ„๋งŒํผ ํŠธ๋žœ์žญ์…˜์ด ์‚ด์•„ ์žˆ์–ด VACUUM์„ ๋ง‰๊ณ  ๋ฝ์„ ์ฅก๋‹ˆ๋‹ค. DB ๋ณ€๊ฒฝ ๊ตฌ๊ฐ„๋งŒ ์งง๊ฒŒ ๋ฌถ์–ด ์ฆ‰์‹œ ์ปค๋ฐ‹ํ•˜๊ณ , ๊ธด ์ž‘์—…์€ ํŠธ๋žœ์žญ์…˜ ๋ฐ–์œผ๋กœ ๋นผ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Tup Fetched (๊ฑด) / Tup Returned (๊ฑด)

  • Tup Fetched: ์ฟผ๋ฆฌ๋กœ ์‹ค์ œ๋กœ ๊ฐ€์ ธ์˜จ(fetched) ํ–‰ ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค ๋“ฑ์„ ํ†ตํ•ด ์‹ค์ œ๋กœ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌ๋œ ํ–‰์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.
  • Tup Returned: ์ฟผ๋ฆฌ๊ฐ€ ์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ ์ฝ์–ด ํ›‘์€(returned/scanned) ํ–‰ ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ˆœ์ฐจ ์Šค์บ”์œผ๋กœ ํ›‘์€ ํ–‰๊นŒ์ง€ ํฌํ•จํ•˜๋ฏ€๋กœ, ํ’€ ์Šค์บ”์ด ๋งŽ์œผ๋ฉด ์ด ๊ฐ’์ด ์ปค์ง‘๋‹ˆ๋‹ค.
  • ๊ด€์ธก๊ฐ’: Tup Fetched ํ‰๊ท  ์•ฝ 5,723 / 1,203 ~ 43,031, Tup Returned ํ‰๊ท  ์•ฝ 63,236 / 10,030 ~ ์•ฝ 1.36์–ต. Returned์˜ ์ตœ๋Œ“๊ฐ’์ด 1์–ต์„ ๋„˜๋Š” ๊ฒƒ์ด ๋ˆˆ์— ๋•๋‹ˆ๋‹ค. ์ˆœ๊ฐ„์ ์œผ๋กœ ์—„์ฒญ๋‚œ ์–‘์˜ ํ–‰์„ ํ›‘์—ˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
  • ์ฝ๋Š” ๋ฒ•: Returned๊ฐ€ Fetched๋ณด๋‹ค ํ›จ์”ฌ ํฌ๋ฉด, ๋งŽ์ด ํ›‘์—ˆ๋Š”๋ฐ ์‹ค์ œ๋กœ ์“ด ํ–‰์€ ์ ๋‹ค๋Š” ๋œป — ์ฆ‰ ๋น„ํšจ์œจ์ ์œผ๋กœ ํ’€ ์Šค์บ”ํ•˜๊ณ  ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ง€ํ‘œ(Rows Hit Ratio)๊ฐ€ ๋ฐ”๋กœ ์ด ๋น„์œจ์„ ๋ด…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ํ’€ ์Šค์บ”, ๋„“์€ ๋ฒ”์œ„ ์กฐํšŒ, ๋Œ€ํ˜• ์กฐ์ธ.
-- ๊ฐ€์ ธ์˜จ ํ–‰ / ํ›‘์€ ํ–‰ ๋ˆ„์  ์นด์šดํ„ฐ
SELECT datname, tup_fetched, tup_returned
FROM   pg_stat_database
WHERE  datname = current_database();
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Tup Returned๊ฐ€ Tup Fetched๋ณด๋‹ค ํ›จ์”ฌ ํฌ๊ณ  Blks Read·CPU๊ฐ€ ๋™๋ฐ˜์ด๋ฉด → ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ํ’€ ์Šค์บ”์ž…๋‹ˆ๋‹ค. Rows Hit Ratio๊ฐ€ ๊ฐ™์ด ๋–จ์–ด์ง€๋ฉด → ํ›‘์€ ๊ฒƒ ๋Œ€๋น„ ์“ด ํ–‰์ด ์ ์€ ๋น„ํšจ์œจ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — Returned๊ฐ€ Fetched๋ณด๋‹ค ํ›จ์”ฌ ํฌ๋‹ค๋Š” ๊ฒƒ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋งŽ์ด ์ฝ๊ณ  ๋Œ€๋ถ€๋ถ„์„ ๋ฒ„๋ฆฐ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. WHERE ์กฐ๊ฑด์— ๋งž๋Š” ์ธ๋ฑ์Šค๊ฐ€ ์—†์–ด ์ „๋ถ€ ํ›‘์€ ๋’ค ๊ฑฐ๋ฅด๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€ํ‘œ์ ์ž…๋‹ˆ๋‹ค. ์กฐํšŒ ์กฐ๊ฑด·์กฐ์ธ ํ‚ค์— ์ธ๋ฑ์Šค๋ฅผ ์„ค๊ณ„ํ•ด "ํ•„์š”ํ•œ ํ–‰๋งŒ ๊ณจ๋ผ ์ฝ๋„๋ก" ๋งŒ๋“ค๋ฉด ๋‘ ๊ฐ’์˜ ๊ฒฉ์ฐจ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

Tup Inserted (๊ฑด) / Tup Updated (๊ฑด) / Tup Deleted (๊ฑด)

๊ฐ๊ฐ ์ฟผ๋ฆฌ๋กœ ์‚ฝ์ž…·๊ฐฑ์‹ ·์‚ญ์ œ๋œ ํ–‰ ์ˆ˜์ž…๋‹ˆ๋‹ค(1๋ถ„ ๊ตฌ๊ฐ„ ํ•ฉ). PostgreSQL์—์„œ ์ด ์„ธ ์ง€ํ‘œ, ํŠนํžˆ Update์™€ Delete๋Š” Dead Tuple๊ณผ ์ง๊ฒฐ๋˜๋ฏ€๋กœ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’:
  • Tup Inserted: ํ‰๊ท  ์•ฝ 1,041 / 223 ~ 3,267
  • Tup Updated: ํ‰๊ท  ์•ฝ 408 / 103 ~ 970
  • Tup Deleted: ํ‰๊ท  ์•ฝ 93 / 0 ~ 35,123
  • ์ฝ๋Š” ๋ฒ•: Insert๋Š” ์ฃฝ์€ ํ–‰์„ ๊ฑฐ์˜ ์•ˆ ๋งŒ๋“ค์ง€๋งŒ, Update์™€ Delete๋Š” ์˜› ๋ฒ„์ „ ํ–‰์„ ์ฃฝ์€ ํ–‰์œผ๋กœ ๋‚จ๊น๋‹ˆ๋‹ค. Update ํ•œ ๋ฒˆ์€ "์ƒˆ ๋ฒ„์ „ ์ถ”๊ฐ€ + ์˜› ๋ฒ„์ „์„ ์ฃฝ์€ ํ–‰์œผ๋กœ ํ‘œ์‹œ" ์ด๊ณ , Delete๋Š” ๊ทธ ํ–‰์„ ์ฃฝ์€ ํ–‰์œผ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Tup Updated·Tup Deleted๊ฐ€ ํฌ๋ฉด ๊ทธ๋งŒํผ ์ฃฝ์€ ํ–‰์ด ์Œ“์—ฌ ์ดํ›„ autovacuum์ด ์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Tup Deleted ์ตœ๋Œ“๊ฐ’ 35,123์€ ๋Œ€๋Ÿ‰ ์‚ญ์ œ ๋ฐฐ์น˜๊ฐ€ ๋ˆ ์ˆœ๊ฐ„์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ๋Œ€๋Ÿ‰ ๋ฐฐ์น˜(์ ์žฌ·๊ฐฑ์‹ ·์‚ญ์ œ), ๋ฐ์ดํ„ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜. ํŠนํžˆ Update/Delete ๊ธ‰์ฆ ๋’ค์—๋Š” ์ฃฝ์€ ํ–‰ ๋ˆ„์ ๊ณผ autovacuum ๋™์ž‘์ด ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค.

๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ์„ ํ•œ ๋ฒˆ์— ๋ชฐ์•„ ํ•˜๋ฉด ์ฃฝ์€ ํ–‰์ด ํ•œ๊บผ๋ฒˆ์— ์Ÿ์•„์ง‘๋‹ˆ๋‹ค. ๋‚˜๋ˆ ์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ถ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: ์ˆ˜๋ฐฑ๋งŒ ํ–‰์„ ํ•œ ๋ฒˆ์— ๊ฐฑ์‹  → ์ฃฝ์€ ํ–‰์ด ํ•œ๊บผ๋ฒˆ์— ์Ÿ์•„์ง„๋‹ค
UPDATE orders SET status = 'ARCHIVED'
WHERE created_at < '2025-01-01';
-- ๊ณ ์นœ ์˜ˆ: ๋ช‡ ๋งŒ ๊ฑด์”ฉ ๋‚˜๋ˆ ์„œ ๊ฐฑ์‹  (์ฃฝ์€ ํ–‰ ๋ฐœ์ƒ์„ ๋ถ„์‚ฐ, VACUUM ๋ถ€๋‹ด ์™„ํ™”)
-- ํ•œ ๋ฒˆ์— 5๋งŒ ๊ฑด์”ฉ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ทธ๋•Œ๊ทธ๋•Œ ์ปค๋ฐ‹ํ•œ๋‹ค
WITH target AS (
  SELECT order_id FROM orders
  WHERE created_at < '2025-01-01' AND status <> 'ARCHIVED'
  LIMIT 50000
)
UPDATE orders o SET status = 'ARCHIVED'
FROM target t WHERE o.order_id = t.order_id;
-- ์œ„ UPDATE๋ฅผ ์˜ํ–ฅ ํ–‰์ด 0์ด ๋  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•˜๋ฉฐ ๋ฌถ์Œ๋งˆ๋‹ค ์ปค๋ฐ‹
-- ํ…Œ์ด๋ธ”๋ณ„ ์‚ฝ์ž…·๊ฐฑ์‹ ·์‚ญ์ œ์™€ ํ˜„์žฌ ์ฃฝ์€ ํ–‰ ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋ณธ๋‹ค
SELECT relname, n_tup_ins, n_tup_upd, n_tup_del,
       n_live_tup, n_dead_tup, last_autovacuum
FROM   pg_stat_user_tables
ORDER  BY n_dead_tup DESC;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Tup Updated·Tup Deleted ๊ธ‰์ฆ ๋’ค์— pg_stat_user_tables์˜ n_dead_tup์ด ์˜ค๋ฅด๋ฉด → ์ฃฝ์€ ํ–‰์ด ์Œ“์ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ดํ›„ CPU์™€ Write IOPS๊ฐ€ ์˜ค๋ฅด๋ฉด → autovacuum์ด ์ฒญ์†Œ๋ฅผ ์‹œ์ž‘ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Age Used Ratio๊ฐ€ ํ•จ๊ป˜ ์˜ค๋ฅด๋ฉด → ์ •๋ฆฌ๊ฐ€ ๋ชป ๋”ฐ๋ผ๊ฐ€ ๋…ธํ™”๊ฐ€ ์ง„ํ–‰๋˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — PostgreSQL์—์„œ UPDATE/DELETE๋Š” ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊พธ๋Š” ๊ฒƒ ์ด์ƒ์œผ๋กœ, ์ฃฝ์€ ํ–‰์„ ๋งŒ๋“ค์–ด VACUUM ๋ถ€๋‹ด์„ ๋‚จ๊น๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ์„ ํ•˜๋‚˜์˜ ํฐ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ชฐ๋ฉด ์ฃฝ์€ ํ–‰์ด ํ•œ๊บผ๋ฒˆ์— ์Œ“์ด๊ณ  ํ…Œ์ด๋ธ”์ด ํŒฝ์ฐฝํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์น˜๋Š” ๋ช‡ ๋งŒ ๊ฑด ๋‹จ์œ„๋กœ ๋‚˜๋ˆ  ์ปค๋ฐ‹ํ•˜๊ณ , ์ž์ฃผ ๊ฐฑ์‹ ๋˜๋Š” ํ…Œ์ด๋ธ”์€ ๋ถˆํ•„์š”ํ•œ UPDATE(๊ฐ’์ด ์•ˆ ๋ฐ”๋€Œ๋Š”๋ฐ๋„ ๊ฐฑ์‹ )๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ ํ–‰์„ ๋ฐ˜๋ณต ๊ฐฑ์‹ ํ•˜๋Š” ํŒจํ„ด์ด๋ผ๋ฉด HOT update๊ฐ€ ์ž˜ ์ผ์–ด๋‚˜๋„๋ก ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ์„ ์ž์ฃผ ์•ˆ ๋ฐ”๊พธ๋Š” ์„ค๊ณ„๋„ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ๋งค์ผ ์ƒˆ๋ฒฝ ๋Œ€๋Ÿ‰ UPDATE ๋ฐฐ์น˜๊ฐ€ ๋„๋Š” ํ…Œ์ด๋ธ”์ด ์ ์  ๋А๋ ค์ง„๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋งค๋ฒˆ ์ˆ˜์‹ญ๋งŒ ํ–‰์„ ํ•œ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๊ฐฑ์‹ ํ•˜๋ฉด์„œ ์ฃฝ์€ ํ–‰์ด ์Ÿ์•„์ง€๋Š”๋ฐ, autovacuum์ด ๊ทธ ์†๋„๋ฅผ ๋ชป ๋”ฐ๋ผ๊ฐ€ n_dead_tup์ด ๊ณ„์† ์Œ“์ด๊ณ  ํ…Œ์ด๋ธ”์ด ์‹ค์ œ ๋ฐ์ดํ„ฐ์˜ ๋ช‡ ๋ฐฐ๋กœ ํŒฝ์ฐฝํ•ฉ๋‹ˆ๋‹ค. ํŒฝ์ฐฝํ•œ ํ…Œ์ด๋ธ”์€ ๊ฐ™์€ ์ฟผ๋ฆฌ๋„ ๋” ๋งŽ์€ ๋ธ”๋ก์„ ์ฝ์–ด ๋А๋ ค์ง‘๋‹ˆ๋‹ค. ๋ฐฐ์น˜๋ฅผ 5๋งŒ ๊ฑด ๋‹จ์œ„๋กœ ๋‚˜๋ˆ  ์ปค๋ฐ‹ํ•˜๊ณ  ํ•ด๋‹น ํ…Œ์ด๋ธ”์˜ autovacuum์„ ๋” ์ž์ฃผ ๋Œ๋„๋ก ์กฐ์ •ํ•˜๋ฉด, ์ฃฝ์€ ํ–‰์ด ์ œ๋•Œ ์ •๋ฆฌ๋˜๋ฉฐ ํŒฝ์ฐฝ๊ณผ ์†๋„ ์ €ํ•˜๊ฐ€ ์žกํž™๋‹ˆ๋‹ค.


4. ์บ์‹œ · ์ฝ๊ธฐ

PostgreSQL๋„ ์ž์ฃผ ์“ฐ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ(shared_buffers, ๋ฒ„ํผ ์บ์‹œ)์— ์บ์‹ฑํ•ด ๋””์Šคํฌ ์ ‘๊ทผ์„ ์ค„์ž…๋‹ˆ๋‹ค. ์ž์ฃผ ๋ณด๋Š” ์ž๋ฃŒ๋ฅผ ์„œ๊ฐ€๊นŒ์ง€ ๊ฐ€์ง€ ์•Š๊ณ  ์ฑ…์ƒ ์œ„์— ์˜ฌ๋ ค๋‘๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ฑ…์ƒ์—์„œ ๋ฐ”๋กœ ์ฐพ์œผ๋ฉด ๋น ๋ฅด๊ณ (๋ฉ”๋ชจ๋ฆฌ), ์„œ๊ฐ€๊นŒ์ง€ ๊ฐ€์•ผ ํ•˜๋ฉด ๋А๋ฆฝ๋‹ˆ๋‹ค(๋””์Šคํฌ).

์ด ์˜์—ญ์˜ ์šฉ์–ด๋ฅผ ๋จผ์ € ํ’€์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ๋…ผ๋ฆฌ ์ฝ๊ธฐ(Blks Hit) / ๋ฌผ๋ฆฌ ์ฝ๊ธฐ(Blks Read): "๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด ๋‹ฌ๋ผ" ๋Š” ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ๋จผ์ € ๋ฒ„ํผ ์บ์‹œ(๋ฉ”๋ชจ๋ฆฌ)๋ถ€ํ„ฐ ์ฐพ์•„๋ด…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฐ”๋กœ ์ฐพ์€ ๊ฒƒ์ด Blks Hit(๋…ผ๋ฆฌ ์ฝ๊ธฐ) ์ด๊ณ , ์บ์‹œ์— ์—†์–ด ๋””์Šคํฌ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ€ ์ฝ์€ ๊ฒƒ์ด Blks Read(๋ฌผ๋ฆฌ ์ฝ๊ธฐ) ์ž…๋‹ˆ๋‹ค. Blks Hit๋Š” ๋น ๋ฅด๊ณ  Blks Read๋Š” ๋А๋ฆฝ๋‹ˆ๋‹ค.
  • ์ ์ค‘๋ฅ (Cache Hit Ratio): ์ „์ฒด ์ฝ๊ธฐ ์ค‘์—์„œ ๋””์Šคํฌ๊นŒ์ง€ ๊ฐ€์ง€ ์•Š๊ณ  ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฐ”๋กœ ์ฐพ์€ ๋น„์œจ์ž…๋‹ˆ๋‹ค. ๋†’์„์ˆ˜๋ก ๋””์Šคํฌ๋ฅผ ๋œ ๊ฑด๋“œ๋ ค ๋น ๋ฆ…๋‹ˆ๋‹ค.

Cache Hit Ratio (%)

๋ฒ„ํผ ์บ์‹œ ์ ์ค‘๋ฅ ์ž…๋‹ˆ๋‹ค. ์‚ฐ์‹์€ 100 * blksHit / (blksRead + blksHit), "๋””์Šคํฌ๊นŒ์ง€ ์•ˆ ๊ฐ€๊ณ  ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฐ”๋กœ ์ฐพ์€ ๋น„์œจ" ์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 99.13%, ๋ฒ”์œ„ 99.02 ~ 99.22%. ๊ฑฐ์˜ ๋ชจ๋“  ์ฝ๊ธฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์ด ์ •๋„๊ฐ€ ์ •์ƒ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๋ˆˆ์— ๋„๊ฒŒ ๋–จ์–ด์ง€๋ฉด(์˜ˆ: 95% ์ดํ•˜) ๋””์Šคํฌ๋ฅผ ์ž์ฃผ ์ฝ๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ  ์„ฑ๋Šฅ์ด ๋‚˜๋น ์ง‘๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด(๋–จ์–ด์ง€๋ฉด) ์˜์‹ฌํ•  ๊ฒƒ: shared_buffers ๋ถ€์กฑ, ์บ์‹œ์— ์—†๋Š” ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ‘์ž๊ธฐ ์กฐํšŒ(๋Œ€ํ˜• ํ’€ ์Šค์บ”), ์ฝœ๋“œ ์Šคํƒ€ํŠธ(์žฌ๊ธฐ๋™ ์งํ›„ ์บ์‹œ๊ฐ€ ๋น„์–ด ์žˆ์Œ), ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ์œผ๋กœ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋” ๋งŽ์€ ๋ธ”๋ก์— ํฉ์–ด์ง.

์ ์ค‘๋ฅ ์„ ๋–จ์–ด๋œจ๋ฆฌ๋Š” ๋Œ€ํ‘œ ์›์ธ์€ "ํฐ ํ…Œ์ด๋ธ”์„ ํ•œ ๋ฒˆ์— ํ’€ ์Šค์บ”" ํ•ด์„œ ์ฑ…์ƒ(์บ์‹œ)์„ ๊ทธ ๋ฐ์ดํ„ฐ๋กœ ๊ฐ€๋“ ์ฑ„์›Œ ํ‰์†Œ ์“ฐ๋˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ€์–ด๋‚ด๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: ์ธ๋ฑ์Šค ์—†์ด ๊ฑฐ๋Œ€ํ•œ ํ…Œ์ด๋ธ” ์ „์ฒด๋ฅผ ๋Œ์–ด์™€ ์บ์‹œ๋ฅผ ์˜ค์—ผ์‹œํ‚จ๋‹ค
SELECT * FROM event_logs ORDER BY created_at;
-- ๊ณ ์นœ ์˜ˆ: ํ•„์š”ํ•œ ๋ฒ”์œ„๋งŒ, ์ธ๋ฑ์Šค๋กœ ์ขํ˜€์„œ ์ฝ๋Š”๋‹ค
SELECT id, type, created_at
FROM   event_logs
WHERE  created_at >= TIMESTAMP '2026-06-18 00:00:00'
  AND  created_at <  TIMESTAMP '2026-06-19 00:00:00';
-- ํ˜„์žฌ DB์˜ ์บ์‹œ ์ ์ค‘๋ฅ  ์ง์ ‘ ๊ณ„์‚ฐ
SELECT datname,
       ROUND(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 2) AS cache_hit_pct
FROM   pg_stat_database
WHERE  datname = current_database();
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: ์ ์ค‘๋ฅ  ํ•˜๋ฝ๊ณผ ํ•จ๊ป˜ Blks Read·Read IOPS๊ฐ€ ์˜ค๋ฅด๋ฉด → ๋””์Šคํฌ ์ฝ๊ธฐ๊ฐ€ ์‹ค์ œ๋กœ ๋Š˜์–ด๋‚œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Tup Returned๋„ ๊ฐ™์ด ๋›ฐ๋ฉด → ๋Œ€ํ˜• ํ’€ ์Šค์บ”์ด ์บ์‹œ๋ฅผ ์˜ค์—ผ์‹œํ‚ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. ์žฌ๊ธฐ๋™ ์งํ›„ ์ผ์‹œ์ ์œผ๋กœ ๋‚ฎ์œผ๋ฉด → ์ฝœ๋“œ ์Šคํƒ€ํŠธ๋กœ, ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค์‹œ ์ฑ„์›Œ์ง€๋ฉด ํšŒ๋ณต๋ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์ž์ฃผ ์“ฐ์ง€ ์•Š๋Š” ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ํ›‘์œผ๋ฉด(์˜ˆ: ์ „์ฒด ํ…Œ์ด๋ธ” ์ง‘๊ณ„) ์บ์‹œ์— ์žˆ๋˜ ์ž์ฃผ ์“ฐ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ€๋ ค๋‚˜ ์ ์ค‘๋ฅ ์ด ๋–จ์–ด์ง‘๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰ ์ฒ˜๋ฆฌ๋Š” ์šด์˜ ํŠธ๋ž˜ํ”ฝ๊ณผ ์‹œ๊ฐ„๋Œ€๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ , ๊ผญ ํ•„์š”ํ•œ ๋ฒ”์œ„๋งŒ ์ธ๋ฑ์Šค๋กœ ์ขํ˜€ ์ฝ๋„๋ก ์งœ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Rows Hit Ratio (%)

์ฟผ๋ฆฌ row ์ ์ค‘๋ฅ ์ž…๋‹ˆ๋‹ค. ์‚ฐ์‹์€ 100 * tup_fetched / tup_returned, "ํ›‘์€ ํ–‰ ์ค‘ ์‹ค์ œ๋กœ ๊ฐ€์ ธ๋‹ค ์“ด ํ–‰์˜ ๋น„์œจ" ์ž…๋‹ˆ๋‹ค. ์บ์‹œ ์ ์ค‘๋ฅ (๋ธ”๋ก ๋‹จ์œ„)๊ณผ๋Š” ๋‹ค๋ฅธ, ํ–‰ ๋‹จ์œ„์˜ ํšจ์œจ ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 13.2%, ๋ฒ”์œ„ 0 ~ 50.9%. ๋‚ฎ๊ฒŒ ๊น”๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฐ’์ด ๋‚ฎ๋‹ค๋Š” ๊ฒƒ์€ ํ›‘์€ ํ–‰์— ๋น„ํ•ด ์‹ค์ œ๋กœ ์“ฐ๋Š” ํ–‰์ด ์ ๋‹ค๋Š” ๋œป์œผ๋กœ, ์ˆœ์ฐจ ์Šค์บ” ๋น„์ค‘์ด ํฌ๋‹ค๋Š” ์‹ ํ˜ธ๋กœ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์›Œํฌ๋กœ๋“œ ํŠน์„ฑ์— ํฌ๊ฒŒ ์ขŒ์šฐ๋˜๋ฏ€๋กœ ์ ˆ๋Œ€๊ฐ’๋ณด๋‹ค ์ถ”์„ธ๋กœ ๋ด…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด(๋–จ์–ด์ง€๋ฉด) ์˜์‹ฌํ•  ๊ฒƒ: ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๊ณ  ๋งŽ์ด ํ›‘์–ด ๊ฑฐ๋ฅด๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๋Š˜์–ด๋‚จ, ๋„“์€ ๋ฒ”์œ„๋ฅผ ์ฝ๊ณ  ์ผ๋ถ€๋งŒ ์“ฐ๋Š” ํŒจํ„ด.
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Rows Hit Ratio๊ฐ€ ๋–จ์–ด์ง€๋ฉฐ Tup Returned·Blks Read·CPU๊ฐ€ ์˜ค๋ฅด๋ฉด → ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๋Š” ํ’€ ์Šค์บ”์ด ๋Š˜์–ด๋‚œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ํ‰ํƒ„ํ•˜๋ฉด ์›Œํฌ๋กœ๋“œ์˜ ์ •์ƒ ํŠน์„ฑ์œผ๋กœ ๋ด…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์ด ๋น„์œจ์ด ๋‚ฎ๋‹ค๋Š” ๊ฒƒ์€ "๋งŽ์ด ์ฝ๊ณ  ์ ๊ฒŒ ์“ด๋‹ค" ๋Š” ๋œป์ด๋ผ, ์ธ๋ฑ์Šค๋กœ ํ•„์š”ํ•œ ํ–‰๋งŒ ๊ณจ๋ผ ์ฝ๋„๋ก ๋ฐ”๊พธ๋ฉด ๊ฐœ์„ ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์›Œํฌ๋กœ๋“œ์— ๋”ฐ๋ผ ๋ณธ๋ž˜ ๋‚ฎ์„ ์ˆ˜ ์žˆ์–ด, ์ ˆ๋Œ€๊ฐ’๋ณด๋‹ค ๊ฐ‘์ž๊ธฐ ๋” ๋–จ์–ด์กŒ๋Š”์ง€๋ฅผ ๋ด…๋‹ˆ๋‹ค.

Blks Read (blocks) / Blks Hit (๊ฑด)

  • Blks Read: ์บ์‹œ์— ์—†์–ด ๋””์Šคํฌ์—์„œ ์ง์ ‘ ์ฝ์€ ๋ธ”๋ก ์ˆ˜(๋ฌผ๋ฆฌ ์ฝ๊ธฐ). ๊ด€์ธก ํ‰๊ท  ์•ฝ 3,551, ๋ฒ”์œ„ 208 ~ ์•ฝ 1,520๋งŒ.
  • Blks Hit: ์บ์‹œ(๋ฉ”๋ชจ๋ฆฌ)์—์„œ ๋ฐ”๋กœ ์ฐพ์€ ๋ธ”๋ก ์ˆ˜(๋…ผ๋ฆฌ ์ฝ๊ธฐ). ๊ด€์ธก ํ‰๊ท  ์•ฝ 46,252, ๋ฒ”์œ„ 11,977 ~ ์•ฝ 611๋งŒ.

ํ‰์†Œ Blks Hit๊ฐ€ Blks Read๋ณด๋‹ค ํ›จ์”ฌ ํฌ๊ธฐ ๋•Œ๋ฌธ์— ์ ์ค‘๋ฅ ์ด 99%๋Œ€๋กœ ๋‚˜์˜ต๋‹ˆ๋‹ค. Blks Read๊ฐ€ ํ‰์†Œ๋ณด๋‹ค ํฌ๊ฒŒ ๋Š˜๋ฉด "์บ์‹œ์— ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋งŽ์ด ์ฝ๊ณ  ์žˆ๋‹ค" ๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค. Blks Read ์ตœ๋Œ“๊ฐ’ 1,520๋งŒ์€ ๋Œ€ํ˜• ํ’€ ์Šค์บ”์ด ๋””์Šคํฌ๋ฅผ ํ†ต์งธ๋กœ ํ›‘์€ ์ˆœ๊ฐ„์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

-- ๋””์Šคํฌ ์ฝ๊ธฐ(Blks Read)๋ฅผ ๋งŽ์ด ์œ ๋ฐœํ•˜๋Š” ํ…Œ์ด๋ธ” ์ฐพ๊ธฐ
SELECT relname, heap_blks_read, heap_blks_hit,
       idx_blks_read, idx_blks_hit
FROM   pg_statio_user_tables
ORDER  BY heap_blks_read DESC
LIMIT  20;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Blks Read๊ฐ€ ์˜ค๋ฅด๋ฉฐ Cache Hit Ratio๊ฐ€ ๋–จ์–ด์ง€๋ฉด → ์บ์‹œ ๋ฏธ์Šค๊ฐ€ ์‹ค์ œ๋กœ ๋Š˜์–ด๋‚œ ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋‘˜์€ ๊ฐ™์€ ํ˜„์ƒ์˜ ์•ž๋’ท๋ฉด). Read IOPS·Tup Returned๊ฐ€ ๋™๋ฐ˜์ด๋ฉด → ๋Œ€๋Ÿ‰ ํ’€ ์Šค์บ”์ด ๋””์Šคํฌ ์ฝ๊ธฐ๋ฅผ ์œ ๋ฐœํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — Blks Read(๋””์Šคํฌ ์ฝ๊ธฐ)๊ฐ€ ๋Š˜์—ˆ๋‹ค๋Š” ๊ฒƒ์€ ์ฝ”๋“œ๊ฐ€ ์บ์‹œ์— ์—†๋Š” ๋ธ”๋ก์„ ์ž์ฃผ ์š”์ฒญํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ž‘์—… ์ง‘ํ•ฉ(์ž์ฃผ ์“ฐ๋Š” ๋ฐ์ดํ„ฐ)์ด ์บ์‹œ์— ๋“ค์–ด์˜ฌ ๋งŒํผ ์กฐํšŒ ๋ฒ”์œ„๋ฅผ ์ขํžˆ๊ณ , ํ•œ ๋ฒˆ ์“ฐ๊ณ  ๋งˆ๋Š” ๋Œ€์šฉ๋Ÿ‰ ์Šค์บ”์€ ์‹œ๊ฐ„๋Œ€๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ๋””์Šคํฌ ์ฝ๊ธฐ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ๋„ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋” ๋งŽ์€ ๋ธ”๋ก์— ํฉ์–ด ๋†“์•„ Blks Read๋ฅผ ๋Š˜๋ฆฌ๋ฏ€๋กœ, VACUUM์ด ์ž˜ ๋„๋Š”์ง€๋„ ํ•จ๊ป˜ ๋ด…๋‹ˆ๋‹ค.

Read IOPS Max (๊ฑด/์ดˆ) / Write IOPS Max (๊ฑด/์ดˆ)

์ดˆ๋‹น ๋””์Šคํฌ ์ฝ๊ธฐ/์“ฐ๊ธฐ I/O ์—ฐ์‚ฐ ์ˆ˜์˜ ์ตœ๋Œ€์น˜์ž…๋‹ˆ๋‹ค. IOPS๋Š” "์ดˆ๋‹น ๋ช‡ ๋ฒˆ ๋””์Šคํฌ์— ์ ‘๊ทผํ–ˆ๋‚˜" ๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค.

๋จผ์ € ์šฉ์–ด๋ฅผ ์งง๊ฒŒ ํ’€์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

  • IOPS(์ดˆ๋‹น ์ž…์ถœ๋ ฅ ํšŸ์ˆ˜): 1์ดˆ์— ๋””์Šคํฌ๋ฅผ ๋ช‡ ๋ฒˆ ์ฝ๊ฑฐ๋‚˜ ์ผ๋Š”์ง€, ๊ทธ ํšŸ์ˆ˜์ž…๋‹ˆ๋‹ค. "์„œ๊ฐ€๋ฅผ 1์ดˆ์— ๋ช‡ ๋ฒˆ ๋‹ค๋…€์™”๋‚˜" ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • Throughput(์ฒ˜๋ฆฌ๋Ÿ‰): 1์ดˆ์— ์‹ค์ œ๋กœ ๋ช‡ ๋ฐ”์ดํŠธ๋ฅผ ์ฃผ๊ณ ๋ฐ›์•˜๋Š”์ง€, ๊ทธ ์–‘์ž…๋‹ˆ๋‹ค(๋’ค์˜ ๋„คํŠธ์›Œํฌ ์ง€ํ‘œ์—์„œ ๋‹ค๋ฃน๋‹ˆ๋‹ค). ํšŸ์ˆ˜๊ฐ€ ์ ์–ด๋„ ํ•œ ๋ฒˆ์— ํฐ ์ง์„ ๋‚˜๋ฅด๋ฉด ์ฒ˜๋ฆฌ๋Ÿ‰์€ ํด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ด€์ธก๊ฐ’: Read IOPS Max ํ‰๊ท  ์•ฝ 520(๋ฒ”์œ„ 55 ~ 54,427), Write IOPS Max ํ‰๊ท  ์•ฝ 2,800(๋ฒ”์œ„ 612 ~ 102,877). MySQL๊ณผ ๋‹ฌ๋ฆฌ ์“ฐ๊ธฐ IOPS๊ฐ€ ํ‰์†Œ์—๋„ ๊ฝค ๋†’์€๋ฐ, TPS๊ฐ€ ๋†’์€(์“ฐ๊ธฐ·์ปค๋ฐ‹์ด ๋งŽ์€) ์›Œํฌ๋กœ๋“œ๋ผ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ์ˆœ๊ฐ„ ์ตœ๋Œ“๊ฐ’์ด ์ฝ๊ธฐ·์“ฐ๊ธฐ ๋ชจ๋‘ ์ˆ˜๋งŒ๊นŒ์ง€ ํŠ‘๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: Read IOPS๊ฐ€ ์˜ค๋ฅด๋ฉด → ์บ์‹œ ๋ฏธ์Šค(๋ฌผ๋ฆฌ ์ฝ๊ธฐ ์ฆ๊ฐ€, Blks Read ๋™๋ฐ˜). Write IOPS๊ฐ€ ์˜ค๋ฅด๋ฉด → ๋Œ€๋Ÿ‰ ์“ฐ๊ธฐ·์ปค๋ฐ‹·์ฃฝ์€ ํ–‰ ์ •๋ฆฌ(VACUUM). ํด๋ผ์šฐ๋“œ(RDS)์—์„œ๋Š” IOPS์— ํ•œ๋„๊ฐ€ ์žˆ์–ด, ํ•œ๋„์— ๋ถ€๋”ชํžˆ๋ฉด ์ „์ฒด๊ฐ€ ๋А๋ ค์ง‘๋‹ˆ๋‹ค.
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Read IOPS๋Š” Blks Read·Cache Hit Ratio์™€ ํ•จ๊ป˜ ๋ด…๋‹ˆ๋‹ค — ์ ์ค‘๋ฅ ์ด ๋–จ์–ด์ง€๋ฉฐ Read IOPS๊ฐ€ ์˜ค๋ฅด๋ฉด ์บ์‹œ ๋ฏธ์Šค์ž…๋‹ˆ๋‹ค. Write IOPS๋Š” Xact Commit·Tup Inserted/Updated/Deleted์™€ ํ•จ๊ป˜ ๋ณด๋ฉด → ์“ฐ๊ธฐ์™€ ์ฃฝ์€ ํ–‰ ์ •๋ฆฌ๊ฐ€ ๋””์Šคํฌ๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ์–‘์„ ๊ฐ€๋Š ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — Read IOPS๋Š” ์บ์‹œ์—์„œ ๋ชป ์ฐพ์€ ์ฝ๊ธฐ๊ฐ€, Write IOPS๋Š” ๋ณ€๊ฒฝ·์ปค๋ฐ‹·VACUUM์ด ๋””์Šคํฌ๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ์–‘์ž…๋‹ˆ๋‹ค. ๋งค ๊ฑด๋งˆ๋‹ค ์ปค๋ฐ‹ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋””์Šคํฌ ์“ฐ๊ธฐ(WAL flush)๋ฅผ ์ž˜๊ฒŒ ๋Š˜๋ฆฌ๋ฏ€๋กœ ๋ฌถ์–ด์„œ ์ปค๋ฐ‹ํ•˜๋ฉด ๋ถ€๋‹ด์ด ์ค๋‹ˆ๋‹ค. ํด๋ผ์šฐ๋“œ DB๋Š” IOPS์— ํ•œ๋„๊ฐ€ ์žˆ์–ด, ํ•œ๋„๋ฅผ ๋„˜๊ธฐ๋Š” ํŒจํ„ด(์žฆ์€ ๋‹จ๊ฑด ์ปค๋ฐ‹·๋Œ€๋Ÿ‰ ํ’€ ์Šค์บ”·๊ณผ๋„ํ•œ ์ฃฝ์€ ํ–‰ ์ •๋ฆฌ)์€ ์ฝ”๋“œ์™€ ์šด์˜ ๋‹จ๊ณ„์—์„œ ์ค„์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.


5. Vacuum · MVCC (ํŠธ๋žœ์žญ์…˜ ID)

์ด ์˜์—ญ์ด PostgreSQL ์ง€ํ‘œ ์ค‘ ๊ฐ€์žฅ PostgreSQL๋‹ค์šด ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์•ž์—์„œ ํ’€์–ด ๋‘” MVCC·Dead Tuple·VACUUM·ํŠธ๋žœ์žญ์…˜ ID wraparound ๊ฐœ๋…์ด ์—ฌ๊ธฐ์„œ ์ง€ํ‘œ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

ํ•œ ์ค„๊ธฐ๋กœ ์ •๋ฆฌํ•˜๋ฉด ์ด๋ ‡์Šต๋‹ˆ๋‹ค. UPDATE·DELETE๊ฐ€ ์ฃฝ์€ ํ–‰(dead tuple)์„ ๋งŒ๋“ค๊ณ  → VACUUM(๋ณดํ†ต autovacuum)์ด ๊ทธ ์ฃฝ์€ ํ–‰์„ ์ฒญ์†Œํ•˜๋ฉฐ, ๋™์‹œ์— ์•„์ฃผ ์˜ค๋ž˜๋œ ํ–‰์„ freeze(๋™๊ฒฐ)ํ•ด ํŠธ๋žœ์žญ์…˜ ID๊ฐ€ ํ•œ ๋ฐ”ํ€ด ๋„๋Š” ์‚ฌ๊ณ (wraparound)๋ฅผ ๋ง‰์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ณ€๊ฒฝ๋Ÿ‰์ด ๋งŽ์€๋ฐ VACUUM์ด ๋ชป ๋”ฐ๋ผ๊ฐ€๋ฉด, ์ฃฝ์€ ํ–‰์ด ์Œ“์—ฌ ํ…Œ์ด๋ธ”์ด ํŒฝ์ฐฝํ•˜๊ณ , ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํŠธ๋žœ์žญ์…˜์˜ ๋‚˜์ด(Age)๊ฐ€ ์œ„ํ—˜ ์ˆ˜์ค€์œผ๋กœ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ์ด ์˜์—ญ์˜ ๋‘ ์ง€ํ‘œ๊ฐ€ ๋ฐ”๋กœ ๊ทธ "๋‚˜์ด" ๋ฅผ ๋ด…๋‹ˆ๋‹ค.

์šฉ์–ด๋ฅผ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์งง๊ฒŒ ์ •๋ฆฌํ•˜๋ฉด:

  • ํŠธ๋žœ์žญ์…˜ ID(XID): PostgreSQL์ด ๋ชจ๋“  ํŠธ๋žœ์žญ์…˜์— ๋งค๊ธฐ๋Š” ๋ฒˆํ˜ธ. ์•ฝ 21์–ต์—์„œ ํ•œ ๋ฐ”ํ€ด ๋Œ์•„ 0์œผ๋กœ ๋Œ์•„์˜ค๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค(wraparound).
  • Age(๋‚˜์ด): ๊ฐ€์žฅ ์˜ค๋ž˜๋œ(freeze ์•ˆ ๋œ) ํŠธ๋žœ์žญ์…˜์ด ์ง€๊ธˆ์œผ๋กœ๋ถ€ํ„ฐ ๋ช‡ ๊ฐœ์˜ ํŠธ๋žœ์žญ์…˜๋งŒํผ ๋–จ์–ด์ ธ ์žˆ๋Š”์ง€์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ’์ด wraparound ํ•œ๊ณ„(์•ฝ 21์–ต)์— ๊ฐ€๊นŒ์›Œ์ง€๋ฉด ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค.
  • autovacuum_freeze_max_age: ์ด ๋‚˜์ด์— ๋„๋‹ฌํ•˜๋ฉด PostgreSQL์ด ๊ฐ•์ œ๋กœ freeze ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๋Š” ๊ธฐ์ค€์„ ์ž…๋‹ˆ๋‹ค. Age Used Ratio๊ฐ€ ์ด ๊ธฐ์ค€ ๋Œ€๋น„ ๋น„์œจ์„ ๋ด…๋‹ˆ๋‹ค.

Age Used Ratio (%)

autovacuum_freeze_max_age ๊ธฐ์ค€์œผ๋กœ ํ˜„์žฌ ๋‚˜์ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ฐผ๋Š”์ง€์˜ ๋น„์œจ์ž…๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ID๊ฐ€ ํ•œ ๋ฐ”ํ€ด ๋Œ๊ธฐ๊นŒ์ง€ ์–ผ๋งˆ๋‚˜ ์—ฌ์œ ๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ํ•œ ์ˆซ์ž๋กœ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ์‚ฌ์ „ ๊ธฐ์ค€์ƒ 85% ์ดํ•˜๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 95.3%, ๋ฒ”์œ„ 81.7 ~ 100.0%. ๊ถŒ์žฅ์„ (85%)๋ณด๋‹ค ๋†’๊ฒŒ ๊น”๋ ค ์žˆ๊ณ , ์ˆœ๊ฐ„ 100%๋ฅผ ๋„˜๊ธด ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ธ์Šคํ„ด์Šค๋Š” ๋‚˜์ด๊ฐ€ ๊พธ์ค€ํžˆ ๋†’๊ฒŒ ์œ ์ง€๋˜๋Š” ํŽธ์ด๋ผ, freeze๊ฐ€ ์ž„๋ฐ•ํ•œ ์ƒํƒœ๋ฅผ ์ž์ฃผ ์ง€๋‚œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ PostgreSQL์€ ์ด ๊ธฐ์ค€์— ๋„๋‹ฌํ•˜๋ฉด autovacuum์ด ๊ฐ•์ œ๋กœ freeze๋ฅผ ๋Œ๋ฆฌ๋„๋ก ์„ค๊ณ„๋ผ ์žˆ์–ด, 100%์— ๋‹ฟ์•„๋„ ๊ณง๋ฐ”๋กœ ์žฅ์• ๋Š” ์•„๋‹ˆ๊ณ  "์ง€๊ธˆ freeze๊ฐ€ ํ•„์š”ํ•œ ์ƒํƒœ" ๋ผ๋Š” ์‹ ํ˜ธ๋กœ ์ฝ์Šต๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ์‚ฌ์ „ ๊ธฐ์ค€ 85% ์ดํ•˜ ๊ถŒ์žฅ. ์ด๋ฅผ ๋„˜์–ด ์ง€์†์ ์œผ๋กœ ๋†’์œผ๋ฉด autovacuum์ด freeze๋ฅผ ๋ชป ๋”ฐ๋ผ๊ฐ€๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ์–ด ๋“ค์—ฌ๋‹ค๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ง„์งœ ์œ„ํ—˜์€ ์ด ๋‚˜์ด๊ฐ€ wraparound ํ•œ๊ณ„๊นŒ์ง€ ๊ณ„์† ์˜ฌ๋ผ๊ฐ€ PostgreSQL์ด ์ƒˆ ์“ฐ๊ธฐ๋ฅผ ๊ฑฐ๋ถ€ํ•˜๊ณ  ๋ฉˆ์ถ”๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ์˜ค๋ž˜ ์‚ด์•„ ์žˆ๋Š” ํŠธ๋žœ์žญ์…˜(idle in transaction)์ด freeze๋ฅผ ๋ง‰์Œ, ๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ์— ๋น„ํ•ด autovacuum์ด ๋„ˆ๋ฌด ๋А๋ฆฌ๊ฒŒ ์„ค์ •๋จ, ํŠน์ • ํ…Œ์ด๋ธ”์ด ๋งค์šฐ ์ปค์„œ freeze๊ฐ€ ์˜ค๋ž˜ ๊ฑธ๋ฆผ.
-- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ณ„ ๋‚˜์ด — wraparound๊นŒ์ง€์˜ ์—ฌ์œ ๋ฅผ ๋ณธ๋‹ค
SELECT datname, age(datfrozenxid) AS xid_age
FROM   pg_database
ORDER  BY xid_age DESC;
-- ๋‚˜์ด๊ฐ€ ํฐ(freeze๊ฐ€ ์‹œ๊ธ‰ํ•œ) ํ…Œ์ด๋ธ” ์ฐพ๊ธฐ
SELECT relname, age(relfrozenxid) AS xid_age, last_autovacuum
FROM   pg_class c
JOIN   pg_stat_user_tables s ON s.relid = c.oid
WHERE  c.relkind = 'r'
ORDER  BY xid_age DESC
LIMIT  20;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Current Age๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๊ฐ™์€ ํ˜„์ƒ(๋‚˜์ด ์ƒ์Šน)์„ ๋‹ค๋ฅธ ๊ฐ๋„๋กœ ๋ณธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Trx Time(๊ธด ํŠธ๋žœ์žญ์…˜)์ด ๊ฐ™์ด ํฌ๋ฉด → ์˜ค๋ž˜ ์‚ด์•„ ์žˆ๋Š” ํŠธ๋žœ์žญ์…˜์ด freeze๋ฅผ ๋ง‰๋Š” ์›์ธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Tup Updated·Tup Deleted๊ฐ€ ๋งŽ์€๋ฐ last_autovacuum์ด ์˜ค๋ž˜๋์œผ๋ฉด → autovacuum์ด ๋ชป ๋”ฐ๋ผ๊ฐ€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — Age๋Š” ์ง์ ‘ ์ฝ”๋“œ๋กœ ์ค„์ด๋Š” ๊ฐ’์€ ์•„๋‹ˆ์ง€๋งŒ, ์ฝ”๋“œ๊ฐ€ ๊ธด ํŠธ๋žœ์žญ์…˜์„ ๋งŒ๋“ค๋ฉด freeze๋ฅผ ๋ง‰์•„ ๋‚˜์ด๋ฅผ ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜์„ ์—ฐ ์ฑ„ ๋…ธ๋Š” idle in transaction์„ ์—†์• ๊ณ (์ž‘์—… ๋๋‚˜๋ฉด ์ฆ‰์‹œ ์ปค๋ฐ‹/๋กค๋ฐฑ), ํŠธ๋žœ์žญ์…˜์„ ์งง๊ฒŒ ๊ฐ€์ ธ๊ฐ€๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ํฐ ๊ธฐ์—ฌ์ž…๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ์ด ๋งŽ์€ ํ…Œ์ด๋ธ”์€ autovacuum ์„ค์ •์„ ๋” ๊ณต๊ฒฉ์ ์œผ๋กœ ์žก๋Š” ์šด์˜ ์กฐ์ •๋„ ํ•จ๊ป˜ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ์–ด๋–ค backend๊ฐ€ ํŠธ๋žœ์žญ์…˜์„ ์—ฐ ์ฑ„ idle in transaction์œผ๋กœ ๋ช‡ ์‹œ๊ฐ„ ๋ฐฉ์น˜๋๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋™์•ˆ PostgreSQL์€ ๊ทธ ํŠธ๋žœ์žญ์…˜์ด ์˜› ๋ฒ„์ „์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ณด๊ณ  freeze์™€ ์ฃฝ์€ ํ–‰ ์ •๋ฆฌ๋ฅผ ๋ฏธ๋ฃจ๋ฉฐ, Age Used Ratio๊ฐ€ ๊ณ„์† ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ๋ฐฉ์น˜๋œ ํŠธ๋žœ์žญ์…˜์„ ์ฐพ์•„ ์ •๋ฆฌํ•˜๋ฉด autovacuum์ด ๋‹ค์‹œ ์ง„ํ–‰๋˜๋ฉฐ ๋‚˜์ด๊ฐ€ ๋‚ด๋ ค๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ธด idle in transaction ์„ธ์…˜์€ PostgreSQL์—์„œ ํŠนํžˆ ์œ„ํ—˜ ์‹ ํ˜ธ๋กœ ๋ด…๋‹ˆ๋‹ค.

Current Age (age)

ํ˜„์žฌ DB์—์„œ ์‚ฌ์šฉ ์ค‘์ธ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํŠธ๋žœ์žญ์…˜ ID์˜ ๋‚˜์ด์ž…๋‹ˆ๋‹ค. Age Used Ratio๊ฐ€ ๋น„์œจ(%)์ด๋ผ๋ฉด, ์ด์ชฝ์€ ๋‚˜์ด์˜ ์ ˆ๋Œ€๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 1.91์–ต(age), ๋ฒ”์œ„ ์•ฝ 1.63์–ต ~ 2.0์–ต. wraparound ํ•œ๊ณ„(์•ฝ 21์–ต)์— ๋น„ํ•˜๋ฉด ์—ฌ์œ ๊ฐ€ ์žˆ์ง€๋งŒ, autovacuum_freeze_max_age(๊ธฐ๋ณธ 2์–ต) ๊ธฐ์ค€์œผ๋กœ ๋ณด๋ฉด ๊ฑฐ์˜ ๊ทธ ๊ทผ์ฒ˜์—์„œ ์›€์ง์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Age Used Ratio๊ฐ€ 95%๋Œ€๋กœ ๋†’๊ฒŒ ๋‚˜์˜ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: Age Used Ratio์™€ ๋™์ผ — ๊ธด ํŠธ๋žœ์žญ์…˜, autovacuum ์ง€์—ฐ, ๊ฑฐ๋Œ€ํ•œ ํ…Œ์ด๋ธ”์˜ freeze ์ง€์—ฐ.
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Age Used Ratio์™€ ๊ฐ™์€ ๋ฐฉํ–ฅ์œผ๋กœ ์›€์ง์ด๋Š” ๊ฒƒ์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค(๊ฐ™์€ ํ˜„์ƒ์˜ ์ ˆ๋Œ€๊ฐ’/๋น„์œจ ํ‘œํ˜„). ๋‘˜ ๋‹ค ๊พธ์ค€ํžˆ ์šฐ์ƒํ–ฅํ•˜๋ฉด freeze๊ฐ€ ๋ชป ๋”ฐ๋ผ๊ฐ€๋Š” ๊ฒƒ์ด๋ฏ€๋กœ autovacuum ๋™์ž‘๊ณผ ๊ธด ํŠธ๋žœ์žญ์…˜์„ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — Current Age๊ฐ€ ๊พธ์ค€ํžˆ ์šฐ์ƒํ–ฅํ•œ๋‹ค๋ฉด, ๋ณ€๊ฒฝ๋Ÿ‰ ๋Œ€๋น„ freeze๊ฐ€ ๋А๋ฆฌ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ ์ชฝ์—์„œ๋Š” ๊ธด ํŠธ๋žœ์žญ์…˜์„ ์—†์• ๊ณ , ์šด์˜ ์ชฝ์—์„œ๋Š” autovacuum์˜ freeze ๋™์ž‘์ด ์ œ๋•Œ ๋Œ๋„๋ก ์„ค์ •์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ง€ํ‘œ๋Š” PostgreSQL ๊ณ ์œ ์˜ "๋ฐฉ์น˜ํ•˜๋ฉด DB๊ฐ€ ๋ฉˆ์ถœ ์ˆ˜ ์žˆ๋Š”" ํ•ญ๋ชฉ์ด๋ผ, ์ ˆ๋Œ€๊ฐ’์ด wraparound ํ•œ๊ณ„๋กœ ํ–ฅํ•˜๋Š” ์ถ”์„ธ๋ฅผ ํŠนํžˆ ์ฃผ์˜ ๊นŠ๊ฒŒ ๋ด…๋‹ˆ๋‹ค.


6. ๋ฝ · ๋™์‹œ์„ฑ

๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋™์‹œ์— ๋ฐ”๊พธ๋ ค ํ•  ๋•Œ ๋ฝ(Lock) ์œผ๋กœ ์ˆœ์„œ๋ฅผ ์ •ํ•ฉ๋‹ˆ๋‹ค. ํ™”์žฅ์‹ค ํ•œ ์นธ์„ ํ•œ ์‚ฌ๋žŒ์”ฉ ์“ฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์„œ, ํ•œ ์‚ฌ๋žŒ์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ์“ฐ๋ฉด ๋’ค์— ์ค„์ด ๊ธธ์–ด์ง‘๋‹ˆ๋‹ค.

์ด ์˜์—ญ์˜ ๊ฐœ๋…์„ ๋จผ์ € ์งง๊ฒŒ ํ’€์–ด ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค. (์•„๋ž˜ ์ง€ํ‘œ๋Š” ์ด ๊ฐœ๋…๋“ค์„ ์ „์ œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.)

  • ํŠธ๋žœ์žญ์…˜(Transaction): ์—ฌ๋Ÿฌ DB ์ž‘์—…์„ "์ „๋ถ€ ์„ฑ๊ณต ์•„๋‹ˆ๋ฉด ์ „๋ถ€ ์ทจ์†Œ" ๋กœ ๋ฌถ์€ ํ•œ ๋ฌถ์Œ์ž…๋‹ˆ๋‹ค. ๋‹ค ์ž˜ ๋์œผ๋ฉด COMMIT, ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ROLLBACK ํ•ฉ๋‹ˆ๋‹ค.
  • ํ–‰ ๋ฝ(Row Lock): PostgreSQL์—์„œ ์–ด๋–ค ํ–‰์„ ๊ณ ์น˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด, ์ปค๋ฐ‹ํ•  ๋•Œ๊นŒ์ง€ ๊ทธ ํ–‰์— ๋ฝ์„ ๊ฑธ์–ด ๋‘ก๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ๊ฐ™์€ ํ–‰์„ ๊ณ ์น˜๋ ค๋ฉด ๊ทธ ๋ฝ์ด ํ’€๋ฆด ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ์ „์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๊ณ ์น˜๋Š” ๊ทธ ํ–‰๋งŒ ์ž ๊ทธ๋ฏ€๋กœ, ๊ฐ™์€ ํ…Œ์ด๋ธ”์ด๋ผ๋„ ๋‹ค๋ฅธ ํ–‰์€ ๋™์‹œ์— ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ต์ฐฉ(Deadlock): ๋‘ ํŠธ๋žœ์žญ์…˜์ด ์„œ๋กœ ์ƒ๋Œ€๊ฐ€ ์ฅ” ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์˜์›ํžˆ ๋ชป ํ’€๋ฆฌ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. A๊ฐ€ 1๋ฒˆ ํ–‰์„ ์ฅ๊ณ  2๋ฒˆ ํ–‰์„ ๊ธฐ๋‹ค๋ฆฌ๋Š”๋ฐ, B๊ฐ€ 2๋ฒˆ ํ–‰์„ ์ฅ๊ณ  1๋ฒˆ ํ–‰์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉด ๋‘˜ ๋‹ค ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. PostgreSQL์€ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๋ฉด ํ•œ์ชฝ ํŠธ๋žœ์žญ์…˜์„ ๊ฐ•์ œ๋กœ ๋กค๋ฐฑ์‹œ์ผœ ํ’‰๋‹ˆ๋‹ค.

Locks Waiting (๊ฐœ)

์ง€๊ธˆ ๋ฝ์„ ์–ป์œผ๋ ค๊ณ  ๋Œ€๊ธฐ ์ค‘์ธ ์ „์ฒด backend ์ˆ˜์ž…๋‹ˆ๋‹ค. (์•ž์˜ 2๋ฒˆ ์„ธ์…˜ ์„น์…˜์—๋„ ๋‚˜์™”์ง€๋งŒ, ๋ฝ ๊ด€์ ์—์„œ ๋‹ค์‹œ ๋ด…๋‹ˆ๋‹ค.) ๋ฝ ๊ฒฝํ•ฉ์„ ์ง์ ‘ ๋ณด์—ฌ ์ฃผ๋Š” ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 0.003, ๋ฒ”์œ„ 0 ~ 5. 0์ด ์ •์ƒ์ด๊ณ , 0์ด ์•„๋‹ˆ๋ฉด ์ง€๊ธˆ ๋ˆ„๊ตฐ๊ฐ€ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜ ๋•Œ๋ฌธ์— ๋ง‰ํ˜€ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ๊ฒฝ๊ณ  1, ์œ„ํ—˜ 2. ์ž‘์€ ๊ฐ’์ด๋ผ๋„ ๋ฐ˜๋ณต๋˜๋ฉด ํŠน์ • ์ฟผ๋ฆฌ·ํŠธ๋žœ์žญ์…˜์ด ์ž์ฃผ ์ถฉ๋Œํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ํ•œ ํŠธ๋žœ์žญ์…˜์ด ํ–‰์„ ์ฅ” ์ฑ„ ์ปค๋ฐ‹์„ ๋ฏธ๋ฃธ(ํŠนํžˆ idle in transaction), ๊ฐ™์€ ํ–‰์— ๋Œ€ํ•œ ๋™์‹œ ์ˆ˜์ • ๊ฒฝํ•ฉ.

๋ฝ ๋Œ€๊ธฐ๋Š” ๊ฑฐ์˜ "ํŠธ๋žœ์žญ์…˜์„ ์—ด์–ด๋†“๊ณ  ์ปค๋ฐ‹์„ ๋ฏธ๋ฃจ๋Š”" ์ฝ”๋“œ์—์„œ ์ƒ๊น๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: ํ–‰์„ ์ˆ˜์ •ํ•œ ๋’ค ์™ธ๋ถ€ ์ž‘์—…(API ํ˜ธ์ถœ·ํŒŒ์ผ ์ฒ˜๋ฆฌ ๋“ฑ)์„ ํ•˜๋А๋ผ ์ปค๋ฐ‹์ด ๋Šฆ์–ด์ง„๋‹ค
-- ๊ทธ๋™์•ˆ ๊ฐ™์€ ํ–‰(id=1)์„ ๊ฑด๋“œ๋ฆฌ๋ ค๋Š” ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์€ ์ „๋ถ€ ๋Œ€๊ธฐํ•œ๋‹ค
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- ... ์—ฌ๊ธฐ์„œ ์™ธ๋ถ€ API ํ˜ธ์ถœ ๋“ฑ์œผ๋กœ ์ˆ˜ ์ดˆ~์ˆ˜์‹ญ ์ดˆ ์ง€์—ฐ ...
COMMIT;   -- ๋„ˆ๋ฌด ๋Šฆ๊ฒŒ ์ปค๋ฐ‹ → ๊ทธ ์‚ฌ์ด account_id=1์„ ๋…ธ๋ฆฌ๋Š” ์ž‘์—…๋“ค์ด ๋ฝ ๋Œ€๊ธฐ
-- ๊ณ ์นœ ์˜ˆ: DB ๋ณ€๊ฒฝ ๊ตฌ๊ฐ„๋งŒ ๋น ๋ฅด๊ฒŒ ๋ฌถ์–ด ๊ณง๋ฐ”๋กœ ์ปค๋ฐ‹ํ•œ๋‹ค (์™ธ๋ถ€ ์ž‘์—…์€ ํŠธ๋žœ์žญ์…˜ ๋ฐ–์—์„œ)
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
COMMIT;   -- ์ฆ‰์‹œ ์ปค๋ฐ‹ → ๋ฝ ์ ์œ  ์‹œ๊ฐ„์ด ์งง์•„ ๋Œ€๊ธฐ๊ฐ€ ๊ฑฐ์˜ ์—†๋‹ค
-- ์ง€๊ธˆ ๋ฝ ๊ฒฝํ•ฉ์ด ์žˆ๋Š”์ง€ — ๋ง‰์€ backend์™€ ๋ง‰ํžŒ backend ์ฐพ๊ธฐ
SELECT blocked.pid          AS blocked_pid,
       blocked.query        AS blocked_query,
       blocking.pid         AS blocking_pid,
       blocking.query       AS blocking_query
FROM   pg_stat_activity blocked
JOIN   LATERAL unnest(pg_blocking_pids(blocked.pid)) AS bp(pid) ON true
JOIN   pg_stat_activity blocking ON blocking.pid = bp.pid
WHERE  cardinality(pg_blocking_pids(blocked.pid)) > 0;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Active Backend๊ฐ€ ๊ฐ™์ด ์Œ“์ด๋ฉด → ๋Œ€๊ธฐ ์„ธ์…˜์ด ๋ถ€ํ•˜๋กœ ๋ฒˆ์ง€๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. Deadlocks๊ฐ€ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๊ฒฝํ•ฉ์ด ๊ต์ฐฉ์œผ๋กœ ๋ฒˆ์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Trx Time(๊ธด ํŠธ๋žœ์žญ์…˜)์ด ํฌ๋ฉด → ๊ทธ ๊ธด ํŠธ๋žœ์žญ์…˜์ด ๋ฝ์„ ์ฅ๊ณ  ์žˆ๋Š” ์›์ธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ์•ˆ์— ์™ธ๋ถ€ API ํ˜ธ์ถœ์ด๋‚˜ ๊ธด ๋กœ์ง์„ ๋„ฃ์œผ๋ฉด ๊ทธ๋™์•ˆ ํ–‰ ๋ฝ์„ ์ฅ๊ณ  ์žˆ์–ด ๊ฐ™์€ ํ–‰์„ ๊ฑด๋“œ๋ฆฌ๋Š” ๋‹ค๋ฅธ ์š”์ฒญ์ด ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜์€ ์งง๊ฒŒ ๊ฐ€์ ธ๊ฐ€๊ณ , ์™ธ๋ถ€ ํ˜ธ์ถœ์ด๋‚˜ ๋ฌด๊ฑฐ์šด ์ฒ˜๋ฆฌ๋Š” ํŠธ๋žœ์žญ์…˜ ๋ฐ–์œผ๋กœ ๋นผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์ด ๊ฐ™์€ ํ–‰์„ ์ž์ฃผ ๊ฐฑ์‹ ํ•˜๋Š” ์„ค๊ณ„ ์ž์ฒด๋„ ๊ฒฝํ•ฉ์„ ๋Š˜๋ฆฌ๋Š” ์›์ธ์ž…๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ํ•œ ํŠธ๋žœ์žญ์…˜์ด ์–ด๋–ค ํ–‰์„ ์ˆ˜์ •ํ•œ ๋’ค ์ปค๋ฐ‹ํ•˜์ง€ ์•Š๊ณ  ์™ธ๋ถ€ ๊ฒฐ์ œ API ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ ์‘๋‹ต์ด ๋Šฆ์–ด์ง€๋Š” ๋™์•ˆ ๊ฐ™์€ ํ–‰(์˜ˆ: ๊ฐ™์€ ์ƒํ’ˆ ์žฌ๊ณ )์„ ์ˆ˜์ •ํ•˜๋ ค๋Š” ์š”์ฒญ๋“ค์ด ์ค„์ค„์ด ๋Œ€๊ธฐํ•˜๋ฉด์„œ Locks Waiting์ด ์˜ค๋ฅด๊ณ , ๋Œ€๊ธฐํ•˜๋Š” ๋งŒํผ Active Backend๊ฐ€ ์Œ“์—ฌ CPU์™€ ์‘๋‹ต์‹œ๊ฐ„๊นŒ์ง€ ๋™๋ฐ˜ ์•…ํ™”๋ฉ๋‹ˆ๋‹ค. ์œ„ pg_blocking_pids ์ฟผ๋ฆฌ๋กœ ๋ง‰์€ backend๋ฅผ ์ฐพ์•„ ์ •๋ฆฌํ•˜๋ฉด ํ•œ๊บผ๋ฒˆ์— ํ’€๋ฆฝ๋‹ˆ๋‹ค. ๊ทผ๋ณธ ํ•ด๊ฒฐ์€ ์™ธ๋ถ€ ํ˜ธ์ถœ์„ ํŠธ๋žœ์žญ์…˜ ๋ฐ–์œผ๋กœ ๋นผ๊ณ  ์ปค๋ฐ‹์„ ๋ฏธ๋ฃจ์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Deadlocks (๊ฑด)

๊ต์ฐฉ(deadlock)์ด ๋ฐœ์ƒํ•œ ๊ฑด์ˆ˜์ž…๋‹ˆ๋‹ค(1๋ถ„ ๊ตฌ๊ฐ„ ํ•ฉ). ๋‘ ํŠธ๋žœ์žญ์…˜์ด ์„œ๋กœ์˜ ๋ฝ์„ ๊ธฐ๋‹ค๋ ค ๋ชป ํ’€๋ฆฌ๋Š” ์ƒํƒœ๊ฐ€ ๊ฐ์ง€๋˜์–ด ํ•œ์ชฝ์ด ๊ฐ•์ œ ๋กค๋ฐฑ๋œ ํšŸ์ˆ˜์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ๊ฑฐ์˜ 0(๋ฒ”์œ„ 0 ~ 1). ํ•œ ๋‹ฌ๊ฐ„ ๊ฑฐ์˜ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. 0์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: 1๊ฑด๋งŒ ๋‚˜ํƒ€๋‚˜๋„ ๋“ค์—ฌ๋‹ค๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ณต๋˜๋ฉด ํŠน์ • ํŠธ๋žœ์žญ์…˜ ์กฐํ•ฉ์ด ์ž์ฃผ ์ถฉ๋Œํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์ด ์—ฌ๋Ÿฌ ํ–‰·ํ…Œ์ด๋ธ”์„ ์„œ๋กœ ๋‹ค๋ฅธ ์ˆœ์„œ๋กœ ์ž ๊ทธ๋Š” ์ฝ”๋“œ. ๋ฝ ํš๋“ ์ˆœ์„œ๊ฐ€ ์—‡๊ฐˆ๋ฆฌ๋ฉด ๊ต์ฐฉ์ด ์ƒ๊น๋‹ˆ๋‹ค.

๊ต์ฐฉ์€ ๋ฝ์„ ์žก๋Š” ์ˆœ์„œ๋ฅผ ์ฝ”๋“œ ์ „๋ฐ˜์—์„œ ์ผ์ •ํ•˜๊ฒŒ ๋งž์ถ”๋ฉด ํฌ๊ฒŒ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: ํ•œ ํŠธ๋žœ์žญ์…˜์€ A→B ์ˆœ์„œ๋กœ, ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์€ B→A ์ˆœ์„œ๋กœ ์ž ๊ทผ๋‹ค → ๊ต์ฐฉ ์œ„ํ—˜
-- ํŠธ๋žœ์žญ์…˜ 1: UPDATE account A; ... UPDATE account B;
-- ํŠธ๋žœ์žญ์…˜ 2: UPDATE account B; ... UPDATE account A;
-- ๊ณ ์นœ ์˜ˆ: ํ•ญ์ƒ ๊ฐ™์€ ์ˆœ์„œ(์˜ˆ: id ์˜ค๋ฆ„์ฐจ์ˆœ)๋กœ ์ž ๊ทธ๋„๋ก ํ†ต์ผํ•œ๋‹ค
-- ๋‘ ํŠธ๋žœ์žญ์…˜ ๋ชจ๋‘: ์ž‘์€ id๋ถ€ํ„ฐ ํฐ id ์ˆœ์„œ๋กœ UPDATE
UPDATE accounts SET balance = balance - 100
WHERE account_id IN (1, 2)
ORDER BY account_id;   -- ๋ฝ ํš๋“ ์ˆœ์„œ๋ฅผ ํ†ต์ผ
-- ๊ต์ฐฉ ๋ˆ„์  ๊ฑด์ˆ˜ ํ™•์ธ
SELECT datname, deadlocks
FROM   pg_stat_database
WHERE  datname = current_database();
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Xact Rollback์ด ๊ฐ™์ด ์˜ค๋ฅด๋ฉด → ๊ต์ฐฉ์œผ๋กœ ํŠธ๋žœ์žญ์…˜์ด ๊ฐ•์ œ ๋กค๋ฐฑ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Locks Waiting์ด ํ•จ๊ป˜ ์˜ค๋ฅด๋ฉด → ๋ฝ ๊ฒฝํ•ฉ์ด ์‹ฌํ•ด์ง„ ๋์— ๊ต์ฐฉ๊นŒ์ง€ ๋ฒˆ์ง„ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ๊ต์ฐฉ์€ ๊ฑฐ์˜ ํ•ญ์ƒ "๋ฝ ํš๋“ ์ˆœ์„œ๊ฐ€ ์ฝ”๋“œ๋งˆ๋‹ค ๋‹ค๋ฅธ" ๋ฐ์„œ ์ƒ๊น๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ํ–‰·์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์„ ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ๊ฑด๋“œ๋ฆฐ๋‹ค๋ฉด, ํ•ญ์ƒ ๊ฐ™์€ ์ˆœ์„œ(์˜ˆ: ๊ธฐ๋ณธํ‚ค ์˜ค๋ฆ„์ฐจ์ˆœ)๋กœ ์ ‘๊ทผํ•˜๋„๋ก ์ฝ”๋“œ ์ „๋ฐ˜์—์„œ ๊ทœ์น™์„ ํ†ต์ผํ•˜๋ฉด ๊ต์ฐฉ ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๊ฒŒ ์ค๋‹ˆ๋‹ค. PostgreSQL์€ ๊ต์ฐฉ์„ ๊ฐ์ง€ํ•˜๋ฉด ํ•œ์ชฝ์„ ๋กค๋ฐฑ์‹œ์ผœ ํ’€์–ด ์ฃผ๋ฏ€๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๊ต์ฐฉ ์˜ˆ์™ธ๋ฅผ ์žก์•„ ์žฌ์‹œ๋„ํ•˜๋Š” ์ฒ˜๋ฆฌ๋ฅผ ํ•จ๊ป˜ ๋‘๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.


7. ๋„คํŠธ์›Œํฌ · ์Šคํ† ๋ฆฌ์ง€ · Temp

DB๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ, ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ ์‚ฌ์šฉ๋Ÿ‰, ๊ทธ๋ฆฌ๊ณ  ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ชป ๋๋‚ธ ์ •๋ ฌ·ํ•ด์‹œ๊ฐ€ ๋””์Šคํฌ๋กœ ํ˜๋Ÿฌ๊ฐ„ ์ž„์‹œ ํŒŒ์ผ์„ ๋ด…๋‹ˆ๋‹ค. ๋ฒ„ํผ ์บ์‹œ๊ฐ€ ์ฑ…์ƒ์ด๋ผ๋ฉด, ์—ฌ๊ธฐ๋Š” ์†๋‹˜์—๊ฒŒ ๋“ค๊ณ  ๋‚˜๊ฐ„ ์ง(๋„คํŠธ์›Œํฌ)์˜ ์–‘๊ณผ ์ฐฝ๊ณ  ์‚ฌ์šฉ๋Ÿ‰(ํŒŒ์ผ ์‹œ์Šคํ…œ), ๊ทธ๋ฆฌ๊ณ  ์ฑ…์ƒ์ด ๋ชจ์ž๋ผ ๋ฐ”๋‹ฅ์— ์ž„์‹œ๋กœ ํŽผ์นœ ์ž‘์—…๋ฌผ(temp)์ž…๋‹ˆ๋‹ค.

Network Transmit Throughput (Bytes/์ดˆ) / Network Receive Throughput (Bytes/์ดˆ)

DB ์ธ์Šคํ„ด์Šค๊ฐ€ ์ฃผ๊ณ ๋ฐ›๋Š” ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ์ž…๋‹ˆ๋‹ค. Transmit(์†ก์‹ )์€ DB๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ์–‘, Receive(์ˆ˜์‹ )๋Š” DB๋กœ ๋“ค์–ด์˜ค๋Š” ์ฟผ๋ฆฌ·๋ฐ์ดํ„ฐ์˜ ์–‘์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ์†ก์‹  ํ‰๊ท  ์•ฝ 967KB/s(๋ฒ”์œ„ 227KB ~ ์•ฝ 2.4MB/s), ์ˆ˜์‹  ํ‰๊ท  ์•ฝ 795KB/s(๋ฒ”์œ„ 235KB ~ ์•ฝ 2.2MB/s). ํ‰ํƒ„ํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ๋Œ€๋Ÿ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฟผ๋ฆฌ(SELECT *๋กœ ํฐ ํ…Œ์ด๋ธ” ์ „์ฒด ๋ฐ˜ํ™˜ ๋“ฑ), ๋Œ€๋Ÿ‰ ์ ์žฌ, ๋ณต์ œ ํŠธ๋ž˜ํ”ฝ.
-- ๋‚˜์œ ์˜ˆ: ํŽ˜์ด์ง• ์—†์ด ํฐ ํ…Œ์ด๋ธ” ์ „์ฒด๋ฅผ ๋ชจ๋“  ์ปฌ๋Ÿผ์œผ๋กœ ๋ฐ˜ํ™˜ → ์†ก์‹  ํŠธ๋ž˜ํ”ฝ ํญ์ฆ
SELECT * FROM products;
-- ๊ณ ์นœ ์˜ˆ: ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ, ํŽ˜์ด์ง•์œผ๋กœ ์ž˜๋ผ์„œ ๋ฐ˜ํ™˜
SELECT product_id, name, price
FROM   products
ORDER  BY product_id
LIMIT  100 OFFSET 0;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: ์†ก์‹  ํŠธ๋ž˜ํ”ฝ ๊ธ‰์ฆ๊ณผ Tup Returned·Tup Fetched๊ฐ€ ๋™๋ฐ˜์ด๋ฉด → ํฐ ๊ฒฐ๊ณผ์…‹์„ ํผ๋‚ด๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ˆ˜์‹  ํŠธ๋ž˜ํ”ฝ๊ณผ Tup Inserted·Write IOPS๊ฐ€ ๋™๋ฐ˜์ด๋ฉด → ๋Œ€๋Ÿ‰ ์ ์žฌ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ํ‰ํƒ„ํ•œ๋ฐ ํ•œ์ชฝ๋งŒ ํŠ€๋ฉด ๋ณต์ œ ํŠธ๋ž˜ํ”ฝ ๋“ฑ ํŠน์ • ๊ฒฝ๋กœ๋ฅผ ์˜์‹ฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ํŽ˜์ด์ง• ์—†์ด ํฐ ๊ฒฐ๊ณผ๋ฅผ ํ†ต์งธ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ SELECT *๋กœ ๋ถˆํ•„์š”ํ•œ ์ปฌ๋Ÿผ๊นŒ์ง€ ํผ๋‚ด๋ฉด ์†ก์‹  ํŠธ๋ž˜ํ”ฝ์ด ์ปค์ง‘๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ, ํŽ˜์ด์ง€ ๋‹จ์œ„๋กœ ์ž˜๋ผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์†ก์‹ ๋Ÿ‰์ด ์ค„๊ณ  ์‘๋‹ต๋„ ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰ ์ ์žฌ ์ชฝ์€ ํ•œ ๊ฑด์”ฉ ๋„ฃ๋Š” ๋Œ€์‹  COPY๋‚˜ ๋ฌถ์Œ INSERT๋กœ ๋ณด๋‚ด๋ฉด ์ˆ˜์‹  ํŠธ๋ž˜ํ”ฝ๊ณผ ์™•๋ณต ํšŸ์ˆ˜๋ฅผ ํ•จ๊ป˜ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Filesystem Usage (Bytes)

ํŒŒ์ผ ์‹œ์Šคํ…œ ์‚ฌ์šฉ๋Ÿ‰์ž…๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค์˜ ๋””์Šคํฌ๊ฐ€ ์‹ค์ œ๋กœ ์–ผ๋งˆ๋‚˜ ์ฐจ ์žˆ๋Š”์ง€๋ฅผ ๋ฐ”์ดํŠธ๋กœ ๋ด…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: ํ‰๊ท  ์•ฝ 226GB, ๋ฒ”์œ„ ์•ฝ 209 ~ 245GB. ์™„๋งŒํ•˜๊ฒŒ ์›€์ง์ž…๋‹ˆ๋‹ค.
  • ์œ„ํ—˜ ์‹ ํ˜ธ: ์ ˆ๋Œ€ ์ž„๊ณ„๋Š” ๋น„ํ™œ์„ฑ์ด์ง€๋งŒ, ๋””์Šคํฌ๊ฐ€ ๊ฐ€๋“ ์ฐจ๋ฉด(ํŠนํžˆ ๋ฐ์ดํ„ฐ·WAL ์˜์—ญ) ์“ฐ๊ธฐ ์ž์ฒด๊ฐ€ ๋ฉˆ์ถฐ ์žฅ์• ๋กœ ์ง๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊พธ์ค€ํžˆ ์šฐ์ƒํ–ฅํ•˜๋Š” ์ถ”์„ธ๋ฅผ ๋ด…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด(๋Š˜๋ฉด) ์˜์‹ฌํ•  ๊ฒƒ: ๋Œ€๋Ÿ‰ ์ ์žฌ๋กœ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€, ์ •๋ฆฌ๋˜์ง€ ์•Š๊ณ  ์Œ“์ด๋Š” WAL, ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ(์ฃฝ์€ ํ–‰์ด VACUUM์œผ๋กœ ํšŒ์ˆ˜๋˜์ง€ ์•Š์•„ ๊ณต๊ฐ„์„ ๊ณ„์† ์ฐจ์ง€), temp ์˜์—ญ์„ ํฌ๊ฒŒ ์“ฐ๋Š” ์ •๋ ฌ.

PostgreSQL์—์„œ ํŒŒ์ผ ์‹œ์Šคํ…œ์ด ์˜ˆ์ƒ๋ณด๋‹ค ๋นจ๋ฆฌ ์ฐจ๋Š” ํ”ํ•œ ์›์ธ ํ•˜๋‚˜๊ฐ€ ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ์ž…๋‹ˆ๋‹ค. ์ฃฝ์€ ํ–‰์ด ํšŒ์ˆ˜๋˜์ง€ ์•Š์œผ๋ฉด ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ณด๋‹ค ํ›จ์”ฌ ํฐ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค.

-- ํ…Œ์ด๋ธ”๋ณ„ ๋””์Šคํฌ ์ ์œ  ํฌ๊ธฐ์™€ ์ฃฝ์€ ํ–‰ ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋ณธ๋‹ค (ํŒฝ์ฐฝ ์ ๊ฒ€)
SELECT relname,
       pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
       n_live_tup, n_dead_tup, last_autovacuum
FROM   pg_stat_user_tables
ORDER  BY pg_total_relation_size(relid) DESC
LIMIT  20;
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Tup Updated·Tup Deleted๊ฐ€ ๋งŽ์€๋ฐ last_autovacuum์ด ์˜ค๋ž˜๋์œผ๋ฉด → ์ฃฝ์€ ํ–‰ ๋ˆ„์ ์œผ๋กœ ํŒฝ์ฐฝ์ด ๊ณต๊ฐ„์„ ๋จน๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. Temp Bytes๊ฐ€ ํฌ๋ฉด → ์ •๋ ฌ ์ž„์‹œ ํŒŒ์ผ์ด ๊ณต๊ฐ„์„ ์“ฐ๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. WAL์ด ์Œ“์ด๋ฉด ๋ณ„๋„ ๊ฒฝ๋กœ๋กœ ํ•จ๊ป˜ ๋ด…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์Šคํ† ๋ฆฌ์ง€๋Š” ํ•œ ๋ฒˆ ์ฐจ๋ฉด ์“ฐ๊ธฐ๊ฐ€ ๋ฉˆ์ถฐ ๊ฐ€์žฅ ์น˜๋ช…์ ์ž…๋‹ˆ๋‹ค. PostgreSQL์—์„œ๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€ ์™ธ์— ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ์ด ๊ณต๊ฐ„์„ ๊ฐ‰์•„๋จน์œผ๋ฏ€๋กœ, ๋ณ€๊ฒฝ์ด ๋งŽ์€ ํ…Œ์ด๋ธ”์˜ VACUUM์ด ์ž˜ ๋„๋Š”์ง€ ํ•จ๊ป˜ ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์ •๋ฆฌ·์•„์นด์ด๋ธŒํ•˜๊ณ , ๋Œ€๋Ÿ‰ ์ ์žฌ·์‚ญ์ œ๋Š” ํ•œ ๋ฒˆ์— ๋ชฐ์ง€ ๋ง๊ณ  ๋‚˜๋ˆ ์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ํŒŒ์ผ ์‹œ์Šคํ…œ ์‚ฌ์šฉ๋Ÿ‰์ด ํ‰์†Œ์—” ์™„๋งŒํ•˜๋‹ค๊ฐ€ ์–ด๋А ๋‚ ๋ถ€ํ„ฐ ๋งค์ผ ์ผ์ •๋Ÿ‰์”ฉ ๋น ๋ฅด๊ฒŒ ๋А๋Š” ์šฐํ•˜ํ–ฅ(์—ฌ์œ  ๊ธฐ์ค€) ์ถ”์„ธ๊ฐ€ ๊ทธ๋ ค์ง„๋‹ค๋ฉด, ์ •๋ฆฌ๋˜์ง€ ์•Š๋Š” WAL์ด๋‚˜ ๋ฉˆ์ถ”์ง€ ์•Š๋Š” ์ ์žฌ ๋ฐฐ์น˜, ํ˜น์€ autovacuum์ด ๋ชป ๋”ฐ๋ผ๊ฐ€๋Š” ํ…Œ์ด๋ธ” ํŒฝ์ฐฝ์„ ์˜์‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ถ”์„ธ๋Œ€๋กœ๋ฉด ๋ฉฐ์น  ๋’ค ๊ณต๊ฐ„์ด ๋ฐ”๋‹ฅ๋‚˜ ์“ฐ๊ธฐ๊ฐ€ ๋ฉˆ์ถ”๋ฏ€๋กœ, ์ ˆ๋Œ€๊ฐ’์ด ์œ„ํ—˜์„ ์— ๋‹ฟ๊ธฐ ์ „์— ์ถ”์„ธ๋ฅผ ๋ณด๊ณ  ๋ฏธ๋ฆฌ ์†์“ฐ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

Temp Bytes (Bytes) / Temp Files (๊ฑด)

  • Temp Bytes: ์ž„์‹œ ํŒŒ์ผ(temporary file)์— ์“ฐ์ธ ๋ฐ์ดํ„ฐ ์–‘์ž…๋‹ˆ๋‹ค(1๋ถ„ ๊ตฌ๊ฐ„ ํ•ฉ).
  • Temp Files: ์ฟผ๋ฆฌ๋กœ ์ƒ์„ฑ๋œ ์ „์ฒด ์ž„์‹œ ํŒŒ์ผ ์ˆ˜์ž…๋‹ˆ๋‹ค(1๋ถ„ ๊ตฌ๊ฐ„ ํ•ฉ).

์ž„์‹œ ํŒŒ์ผ์€ ์ •๋ ฌ·ํ•ด์‹œ·๊ทธ๋ฃนํ•‘ ์ž‘์—…์ด backend์˜ ์ž‘์—… ๋ฉ”๋ชจ๋ฆฌ(work_mem) ์•ˆ์—์„œ ๋ชป ๋๋‚˜๊ณ  ๋””์Šคํฌ๋กœ ๋„˜์ณ ๋‚ฌ์„ ๋•Œ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ์ฆ‰ ์ด ์ง€ํ‘œ๊ฐ€ 0์ด ์•„๋‹ˆ๋ฉด "๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋๋‚˜์ง€ ๋ชปํ•œ ๋ฌด๊ฑฐ์šด ์ •๋ ฌ·ํ•ด์‹œ๊ฐ€ ์žˆ์—ˆ๋‹ค" ๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.

  • ๊ด€์ธก๊ฐ’: Temp Bytes ํ‰๊ท  ์•ฝ 131KB(๋ฒ”์œ„ 0 ~ ์•ฝ 1.07GB), Temp Files ํ‰๊ท  ๊ฑฐ์˜ 0(๋ฒ”์œ„ 0 ~ 1). ํ‰์†Œ์—” ๊ฑฐ์˜ 0์ด๋‹ค๊ฐ€ ์–ด๋–ค ์ˆœ๊ฐ„ 1GB๊ฐ€ ๋„˜๋Š” ์ž„์‹œ ํŒŒ์ผ์ด ์ƒ๊ธด ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ˆœ๊ฐ„์ด ํฐ ์ •๋ ฌ·ํ•ด์‹œ๊ฐ€ ๋””์Šคํฌ๋กœ ๋„˜์นœ ์‹œ์ ์ž…๋‹ˆ๋‹ค.
  • ํŠ€๋ฉด ์˜์‹ฌํ•  ๊ฒƒ: ์ธ๋ฑ์Šค ์—†๋Š” ๋Œ€๋Ÿ‰ ORDER BY, ํฐ ํ•ด์‹œ ์กฐ์ธ, ๋Œ€๋Ÿ‰ GROUP BY·DISTINCT, work_mem ๋ถ€์กฑ.

ํฐ ์ •๋ ฌ์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋„˜์œผ๋ฉด ๋””์Šคํฌ ์ž„์‹œ ํŒŒ์ผ์ด ์ƒ๊น๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ์„ ๋Œ€์‹ ํ•˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ๊ฒฐ๊ณผ๋ฅผ ์ขํžˆ๋ฉด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

-- ๋‚˜์œ ์˜ˆ: ์ธ๋ฑ์Šค ์—†๋Š” ์ปฌ๋Ÿผ์œผ๋กœ ๋Œ€๋Ÿ‰ ์ •๋ ฌ → work_mem์„ ๋„˜๊ฒจ ๋””์Šคํฌ temp ๋ฐœ์ƒ
SELECT * FROM logs ORDER BY message;
-- ๊ณ ์นœ ์˜ˆ: ์ •๋ ฌ ๊ธฐ์ค€ ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ๋‘๊ณ , ํ•„์š”ํ•œ ๋ฒ”์œ„·์ปฌ๋Ÿผ๋งŒ ์ขํ˜€ ์ฝ๋Š”๋‹ค
-- (์ธ๋ฑ์Šค๊ฐ€ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ์ œ๊ณตํ•˜๋ฉด ๋””์Šคํฌ ์ •๋ ฌ์ด ์‚ฌ๋ผ์ง„๋‹ค)
SELECT id, level, created_at
FROM   logs
WHERE  created_at >= TIMESTAMP '2026-06-18 00:00:00'
ORDER  BY created_at        -- created_at ์ธ๋ฑ์Šค๊ฐ€ ์ •๋ ฌ์„ ๋Œ€์‹ 
LIMIT  100;
-- ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ๋””์Šคํฌ ์ •๋ ฌ์„ ํ•˜๋Š”์ง€ — ์‹คํ–‰๊ณ„ํš์—์„œ ํ™•์ธ
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM logs ORDER BY message;
-- ๊ฒฐ๊ณผ์— 'Sort Method: external merge  Disk: ...kB' ๊ฐ€ ๋ณด์ด๋ฉด ๋””์Šคํฌ ์ •๋ ฌ(temp ๋ฐœ์ƒ)
  • ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ: Temp Bytes·Temp Files๊ฐ€ ์˜ค๋ฅด๋ฉฐ Blks Read·Read IOPS·Write IOPS๊ฐ€ ๋™๋ฐ˜์ด๋ฉด → ํฐ ์ •๋ ฌ·ํ•ด์‹œ๊ฐ€ ๋””์Šคํฌ๋ฅผ ์˜ค๊ฐ€๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. CPU๋„ ๊ฐ™์ด ์˜ค๋ฅด๋ฉด ๋ฌด๊ฑฐ์šด ์ •๋ ฌ ์—ฐ์‚ฐ์ด ๋ถ€ํ•˜๋กœ ์žกํžŒ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Filesystem Usage๊ฐ€ ์ผ์‹œ์ ์œผ๋กœ ์˜ค๋ฅด๋ฉด → ํฐ ์ž„์‹œ ํŒŒ์ผ์ด ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ๊ด€์  — ์ž„์‹œ ํŒŒ์ผ์€ ์ •๋ ฌ·ํ•ด์‹œ·๊ทธ๋ฃนํ•‘์ด work_mem์„ ๋„˜์ณ ๋””์Šคํฌ๋กœ ํ˜๋ €๋‹ค๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ์„ ๋Œ€์‹ ํ•˜๊ฒŒ ํ•˜๊ณ (ORDER BY ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค), ๊ฒฐ๊ณผ ํฌ๊ธฐ๋ฅผ ํŽ˜์ด์ง€ ๋‹จ์œ„๋กœ ์ค„์ด๋ฉฐ, ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ ์ฝ์œผ๋ฉด ๋””์Šคํฌ ์ž„์‹œ ํŒŒ์ผ์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ๊ฐ™์€ ๋ฌด๊ฑฐ์šด ์ง‘๊ณ„๊ฐ€ ๋ฐ˜๋ณต๋œ๋‹ค๋ฉด ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•œ ์ง‘๊ณ„ ํ…Œ์ด๋ธ”์ด๋‚˜ ๊ตฌ์ฒดํ™” ๋ทฐ(materialized view)๋ฅผ ๋‘๋Š” ๊ฒƒ๋„ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค — ํ‰์†Œ Temp Files๊ฐ€ 0์ด๋˜ ์ธ์Šคํ„ด์Šค์—์„œ ํŠน์ • ์‹œ๊ฐ„๋Œ€์—๋งŒ 1GB๊ฐ€ ๋„˜๋Š” Temp Bytes๊ฐ€ ์ฐํžŒ๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ ์‹œ๊ฐ„์— ๋„๋Š” ๋ฆฌํฌํŠธ ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค ์—†์ด ํฐ ํ…Œ์ด๋ธ”์„ ์ •๋ ฌ·์ง‘๊ณ„ํ•˜๋ฉด์„œ work_mem์„ ๋„˜๊ฒจ ๋””์Šคํฌ ์ •๋ ฌ์„ ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. EXPLAIN์œผ๋กœ ๋ณด๋ฉด Sort Method: external merge Disk๊ฐ€ ๋‚˜์˜ต๋‹ˆ๋‹ค. ์ •๋ ฌ ๊ธฐ์ค€ ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ์งœ์„œ ๋””์Šคํฌ ์ •๋ ฌ์„ ์—†์• ๋ฉด Temp Bytes๊ฐ€ 0์œผ๋กœ ๋Œ์•„์˜ค๊ณ  ๊ทธ ์ฟผ๋ฆฌ๋„ ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค.


8. ๊ธฐํƒ€

(์ฐธ๊ณ ) Postgresql Slow Query Monitor (ms)

PostgreSQL Slow Query๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์ง€ํ‘œ์ธ๋ฐ, ํ™˜๊ฒฝ์— ๋”ฐ๋ผ 1๋ถ„ ๋‹จ์œ„ ๋ฉ”ํŠธ๋ฆญ์œผ๋กœ ๋“ค์–ด์˜ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์–ด(์ด ์ธ์Šคํ„ด์Šค์—์„œ๋Š” ๋ฏธ์ œ๊ณต) ๋“ค์–ด์˜ฌ ๋•Œ๋งŒ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค. ๋А๋ฆฐ ์ฟผ๋ฆฌ ์ž์ฒด๋Š” ์•ž์—์„œ ๋ณธ Long Active Backend·Active Backend·Blks Read ๊ฐ™์€ ์ง€ํ‘œ์™€ pg_stat_activity๋กœ ์ถฉ๋ถ„ํžˆ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๊ณ , ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” pg_stat_statements ํ™•์žฅ์„ ์ผœ ๋‘๋ฉด ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ๋ˆ„์ ์œผ๋กœ ๊ฐ€์žฅ ๋ฌด๊ฑฐ์šด์ง€ ์ •ํ™•ํžˆ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

-- (์šด์˜ ํ™˜๊ฒฝ์—์„œ pg_stat_statements๊ฐ€ ์ผœ์ ธ ์žˆ๋‹ค๋ฉด) ๋ˆ„์  ์ˆ˜ํ–‰์‹œ๊ฐ„์ด ํฐ ์ฟผ๋ฆฌ ์ฐพ๊ธฐ
SELECT query,
       calls,
       ROUND(total_exec_time::numeric, 1) AS total_ms,
       ROUND(mean_exec_time::numeric, 2)  AS mean_ms
FROM   pg_stat_statements
ORDER  BY total_exec_time DESC
LIMIT  20;

๊ฐœ๋ฐœ์ž ๊ด€์  — ๋ณ„๋„์˜ slow query ์ง€ํ‘œ๊ฐ€ ์—†์–ด๋„, "๋А๋ฆฐ ์ฟผ๋ฆฌ" ๋Š” ๊ฒฐ๊ตญ ์ธ๋ฑ์Šค๋ฅผ ๋ชป ํƒ€๊ฑฐ๋‚˜ ๊ฒฐ๊ณผ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ๋‹ค๋ฃจ๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. pg_stat_statements๋กœ ํ‰๊ท  ์ˆ˜ํ–‰์‹œ๊ฐ„์ด ๊ธด ์ฟผ๋ฆฌ๋ฅผ ์ฐพ์•„ EXPLAIN (ANALYZE, BUFFERS)๋กœ ์‹คํ–‰๊ณ„ํš์„ ๋ณด๊ณ  ์ธ๋ฑ์Šค·๊ฒฐ๊ณผ ํฌ๊ธฐ๋ฅผ ์†๋ณด๋Š” ํ๋ฆ„์€ ์•ž์˜ ๋‹ค๋ฅธ ์ง€ํ‘œ๋“ค๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.


์ƒํ™ฉ๋ณ„๋กœ ๋ณด๊ธฐ — ๋ฐฐ์น˜·๋ฐฑ์—…์ด ๋Œ ๋•Œ ์–ด๋–ค ์ง€ํ‘œ๊ฐ€ ์›€์ง์ด๋‚˜

์ง€๊ธˆ๊นŒ์ง€๋Š” ์ง€ํ‘œ๋ฅผ ํ•˜๋‚˜์”ฉ ๋ดค์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ํ•˜๋‚˜์˜ ์ž‘์—…์ด ์—ฌ๋Ÿฌ ์ง€ํ‘œ๋ฅผ ๋™์‹œ์— ์›€์ง์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ์ •๊ธฐ ๋ฐฐ์น˜๋‚˜ ๋ฐฑ์—…์ฒ˜๋Ÿผ ์ •ํ•ด์ง„ ์‹œ๊ฐ„์— ๋„๋Š” ์ž‘์—…์€ ๋งค๋ฒˆ ๋น„์Šทํ•œ ์ง€ํ‘œ ๋ฌถ์Œ์„ ๋Œ์–ด์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. PostgreSQL์€ ๋ณ€๊ฒฝ ์ž‘์—…์ด ์ฃฝ์€ ํ–‰๊ณผ VACUUM์œผ๋กœ ์ด์–ด์ง€๋Š” ํŠน์„ฑ์ด ์žˆ์–ด์„œ, ๋ฐฐ์น˜์˜ ์ข…๋ฅ˜๋ฅผ ์ง€ํ‘œ ํŒจํ„ด์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค.

๋ฐฐ์น˜ ์œ ํ˜•๋ณ„ ์˜ˆ์ƒ ์ง€ํ‘œ ๋ณ€ํ™”

๋ฐฐ์น˜ ์œ ํ˜• ํ•จ๊ป˜ ์˜ค๋ฅด๋Š” ์ง€ํ‘œ ์ด์œ 
๋Œ€๋Ÿ‰ UPDATE/DELETE ๋ฐฐ์น˜ Tup Updated·Tup Deleted, (์งํ›„) n_dead_tup·autovacuum์œผ๋กœ CPU·Write IOPS, Locks Waiting, Filesystem Usage ๋ณ€๊ฒฝํ•  ๋•Œ๋งˆ๋‹ค ์ฃฝ์€ ํ–‰์ด ์Œ“์ด๊ณ , ์ดํ›„ autovacuum์ด ์ฒญ์†Œํ•˜๋ฉฐ, ์ •๋ฆฌ๊ฐ€ ๋Šฆ์œผ๋ฉด ํ…Œ์ด๋ธ”์ด ํŒฝ์ฐฝํ•จ
๋Œ€๋Ÿ‰ ์ ์žฌ (INSERT) Tup Inserted, Xact Commit·TPS, Write IOPS, Network ์ˆ˜์‹ , Filesystem Usage ํ–‰์„ ๋Œ€๋Ÿ‰์œผ๋กœ ์“ฐ๋ฉด ์ปค๋ฐ‹·WAL flush·๋””์Šคํฌ ์“ฐ๊ธฐ๊ฐ€ ๋Š˜๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ์ฆ๊ฐ€ํ•จ
์ง‘๊ณ„·๋ฆฌํฌํŠธ (๋Œ€๋Ÿ‰ SELECT) Tup Returned, Blks Read, Read IOPS, Temp Bytes·Temp Files, CPU / Cache Hit Ratio๋Š” ํ•˜๋ฝ ํฐ ํ…Œ์ด๋ธ”์„ ํ›‘์–ด ์ง‘๊ณ„·์ •๋ ฌํ•˜๋ฏ€๋กœ ์ฝ์€ ๋ธ”๋ก·๋””์Šคํฌ ์ฝ๊ธฐ·์ž„์‹œ ํŒŒ์ผ์ด ๊ธ‰์ฆํ•˜๊ณ  ์บ์‹œ๊ฐ€ ๋ฐ€๋ฆผ
๋ฐฑ์—… Read IOPS, Network, CPU(์•ฝ๊ฐ„) ๋ฐ์ดํ„ฐ ์ „์ฒด๋ฅผ ์ฝ์–ด ๋‚ด๋ณด๋‚ด๋ฏ€๋กœ ๋””์Šคํฌ ์ฝ๊ธฐ·๋„คํŠธ์›Œํฌ๊ฐ€ ์˜ค๋ฆ„
๊ธด ํŠธ๋žœ์žญ์…˜ ๋ฐฉ์น˜ (idle in transaction) Trx Time, Age Used Ratio·Current Age, Locks Waiting ํŠธ๋žœ์žญ์…˜์ด ์˜ค๋ž˜ ์‚ด์•„ VACUUM·freeze๋ฅผ ๋ง‰์•„ ๋‚˜์ด๊ฐ€ ์˜ค๋ฅด๊ณ , ๋ฝ๋„ ์˜ค๋ž˜ ์ฅ 

์˜ˆ๋ฅผ ๋“ค๋ฉด

๋งค์ผ ์ƒˆ๋ฒฝ ํ†ต๊ณ„ ๋ฐฐ์น˜๊ฐ€ ํฐ ํ…Œ์ด๋ธ”์„ ํ’€ ์Šค์บ”ํ•ด ์ง‘๊ณ„·์ •๋ ฌํ•œ๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ ์‹œ๊ฐ„์—๋Š” Tup Returned๊ฐ€ ์ˆ˜์ฒœ๋งŒ~์ˆ˜์–ต์œผ๋กœ ๋›ฐ๊ณ , Blks Read์™€ Read IOPS๊ฐ€ ๋”ฐ๋ผ ์˜ค๋ฅด๋ฉฐ, ์ •๋ ฌ์ด work_mem์„ ๋„˜๊ฒจ Temp Bytes·Temp Files๊ฐ€ ์ƒ๊ธฐ๊ณ , ๊ทธ ๋ฐ์ดํ„ฐ๊ฐ€ ์บ์‹œ๋ฅผ ๋ฐ€์–ด๋‚ด Cache Hit Ratio๊ฐ€ ์ž ๊น ๋–จ์–ด์ง‘๋‹ˆ๋‹ค. CPU๋„ ์ง‘๊ณ„·์ •๋ ฌ ์—ฐ์‚ฐ์œผ๋กœ ๊ฐ™์ด ์˜ค๋ฆ…๋‹ˆ๋‹ค. ์ด ๋ฌถ์Œ์ด ๊ฐ™์€ ์‹œ๊ฐ์— ํ•จ๊ป˜ ์›€์ง์ด๋Š” ๊ฒƒ์ด ์ด ๋ฐฐ์น˜์˜ ์ง€๋ฌธ ๊ฐ™์€ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

์›”๋ง ๋Œ€๋Ÿ‰ UPDATE/DELETE ๋ฐฐ์น˜๋ผ๋ฉด ๋ฐ˜๋Œ€๋กœ Tup Updated·Tup Deleted๊ฐ€ ๊ฐ™์ด ์˜ค๋ฆ…๋‹ˆ๋‹ค. ๊ทธ ์งํ›„ ์ฃฝ์€ ํ–‰(n_dead_tup)์ด ์Œ“์ด๊ณ  autovacuum์ด ๋Œ๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด์„œ CPU์™€ Write IOPS๊ฐ€ ํ•œ ๋ฒˆ ๋” ์˜ค๋ฆ…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด๋•Œ ๋ณ€๊ฒฝ์„ ํ•˜๋‚˜์˜ ํฐ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ฌถ์–ด ์˜ค๋ž˜ ๋Œ๋ฉด, ๊ทธ ํŠธ๋žœ์žญ์…˜์ด VACUUM์„ ๋ง‰์•„ ์ฃฝ์€ ํ–‰์ด ์ •๋ฆฌ๋˜์ง€ ์•Š๊ณ  ํ…Œ์ด๋ธ”์ด ํŒฝ์ฐฝํ•˜๋ฉฐ Age Used Ratio๊นŒ์ง€ ์˜ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋Œ€๋Ÿ‰ ์ž‘์—…์€ ๋„ˆ๋ฌด ํฌ์ง€๋„ ๋„ˆ๋ฌด ์ž˜์ง€๋„ ์•Š์€ ๋ฌถ์Œ(์ˆ˜์ฒœ~์ˆ˜๋งŒ ๊ฑด)์œผ๋กœ ๋‚˜๋ˆ  ์ปค๋ฐ‹ํ•˜๋Š” ๊ฒƒ์ด ๊ท ํ˜•์ ์ž…๋‹ˆ๋‹ค.

ํ•ต์‹ฌ — "์–ธ์ œ" ์˜ฌ๋ž๋Š”์ง€๊ฐ€ ์ค‘์š”ํ•˜๋‹ค

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€, ์ด ์ง€ํ‘œ๋“ค์ด ๋ฐฐ์น˜ ์‹œ๊ฐ„๋Œ€์— ํ•จ๊ป˜ ์˜ค๋ฅด๋Š” ๊ฒƒ์€ ์ •์ƒ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ •ํ•ด์ง„ ์ž‘์—…์ด ์ •ํ•ด์ง„ ์‹œ๊ฐ„์— ์ž์›์„ ์“ฐ๋Š” ๊ฒƒ์ด๋‹ˆ๊นŒ์š”. ๋”ํ•˜์—ฌ PostgreSQL์—์„œ๋Š” ๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ ๋ฐฐ์น˜ ์งํ›„์— autovacuum์ด ๋”ฐ๋ผ ๋„๋Š” ๊ฒƒ ๋˜ํ•œ ์ •์ƒ์ ์ธ ๋ฆฌ๋“ฌ์ž…๋‹ˆ๋‹ค(์ฃฝ์€ ํ–‰์„ ์น˜์›Œ ์ฃผ๋Š” ๊ณ ๋งˆ์šด ๋™์ž‘์ž…๋‹ˆ๋‹ค). ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๊ฒฝ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋ฐฐ์น˜๊ฐ€ ์—†๋Š” ์‹œ๊ฐ„๋Œ€์— ๊ฐ™์€ ํŒจํ„ด์ด ๋‚˜ํƒ€๋‚  ๋•Œ — ๋ˆ„๊ตฐ๊ฐ€ ์ˆ˜๋™์œผ๋กœ ๋ฌด๊ฑฐ์šด ์ฟผ๋ฆฌ๋ฅผ ๋Œ๋ ธ๊ฑฐ๋‚˜, ์˜๋„์น˜ ์•Š์€ ์ž‘์—…์ด ๋ˆ๋‹ค๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.
  • ๋ฐฐ์น˜ ์‹œ๊ฐ„๋Œ€์ธ๋ฐ ํ‰์†Œ๋ณด๋‹ค ํ›จ์”ฌ ํฌ๊ฒŒ, ์˜ค๋ž˜ ํŠˆ ๋•Œ — ๋ฐ์ดํ„ฐ๊ฐ€ ๊ทธ๋งŒํผ ๋Š˜์—ˆ๊ฑฐ๋‚˜, ์ฟผ๋ฆฌ๊ฐ€ ๋น„ํšจ์œจ์ ์œผ๋กœ ๋ฐ”๋€Œ์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ณ€๊ฒฝ ๋ฐฐ์น˜ ๋’ค์— ์ฃฝ์€ ํ–‰์ด ์ค„์ง€ ์•Š๊ณ  Age๊ฐ€ ๊ณ„์† ์˜ค๋ฅผ ๋•Œ — autovacuum์ด ๋ชป ๋”ฐ๋ผ๊ฐ€๊ฑฐ๋‚˜ ๊ธด ํŠธ๋žœ์žญ์…˜์ด ์ •๋ฆฌ๋ฅผ ๋ง‰๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(PostgreSQL ๊ณ ์œ ์˜ ์ ๊ฒ€ ํฌ์ธํŠธ).

๊ทธ๋ž˜์„œ ๋ชจ๋‹ˆํ„ฐ๋ง์—์„œ๋Š” ์ ˆ๋Œ€๊ฐ’๋งŒํผ "ํ‰์†Œ ์ด ์‹œ๊ฐ„๋Œ€์™€ ๋น„๊ตํ•ด์„œ ์–ด๋–ค๊ฐ€" ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋งค์ผ ๊ฐ™์€ ์‹œ๊ฐ์— ๊ฐ™์€ ๋ชจ์–‘์œผ๋กœ ์˜ค๋ฅด๋‚ด๋ฆฌ๋Š” ๊ทธ๋ž˜ํ”„๋ผ๋ฉด ๊ทธ๊ฑด ๋ฐฐ์น˜์˜ ์ •์ƒ ๋ฆฌ๋“ฌ์ด๊ณ , ๊ทธ ๋ฆฌ๋“ฌ์—์„œ ๋ฒ—์–ด๋‚˜๋Š” ์ˆœ๊ฐ„์ด ๋“ค์—ฌ๋‹ค๋ณผ ์ง€์ ์ž…๋‹ˆ๋‹ค.


์ •๋ฆฌํ•˜๋ฉฐ

PostgreSQL ์ง€ํ‘œ๋Š” MySQL·Oracle๊ณผ ๊ณตํ†ต๋œ ๋ถ€๋ถ„(CPU·๋ฉ”๋ชจ๋ฆฌ·์„ธ์…˜·์ฝ๊ธฐ·๋ฝ)์ด ๋งŽ์œผ๋ฉด์„œ๋„, MVCC·Dead Tuple·VACUUM·ํŠธ๋žœ์žญ์…˜ ID(Age) ๋ผ๋Š” ๊ทธ DB๋งŒ์˜ ์ค„๊ธฐ๊ฐ€ ๋ถ„๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ ๊ฐœ๋…์„ ๋จผ์ € ์žก์•„ ๋‘๋‹ˆ, ์ง€ํ‘œ๋“ค์ด ๊ทธ ๊ฐœ๋…๋“ค์˜ ๋™์ž‘์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด์–ด์กŒ์Šต๋‹ˆ๋‹ค.

PostgreSQL์—์„œ ๊ธฐ์–ตํ•ด ๋‘˜ ํ•ต์‹ฌ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • "์—ฐ๊ฒฐ(Numbackends)" ๊ณผ "ํ™œ์„ฑ(Active Backend)" ์€ ๋‹ค๋ฅด๋‹ค. ์œ„ ์ธ์Šคํ„ด์Šค๋„ ์—ฐ๊ฒฐ์€ ์•ฝ 837์ธ๋ฐ ํ™œ์„ฑ์€ 1 ์•ˆํŒŽ์ด์—ˆ๋‹ค. ๋ถ€ํ•˜๋Š” ํ™œ์„ฑ์œผ๋กœ ๋ณธ๋‹ค. PostgreSQL์€ ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋„์šฐ๋ฏ€๋กœ ์ปค๋„ฅ์…˜ ํ’€·PgBouncer๊ฐ€ ํŠนํžˆ ์ค‘์š”ํ•˜๋‹ค.
  • UPDATE/DELETE๋Š” ์ฃฝ์€ ํ–‰์„ ๋‚จ๊ธด๋‹ค. Tup Updated·Tup Deleted๊ฐ€ ํฌ๋ฉด ์ฃฝ์€ ํ–‰์ด ์Œ“์ด๊ณ , VACUUM(autovacuum)์ด ์ฒญ์†Œํ•œ๋‹ค. ๋Œ€๋Ÿ‰ ๋ณ€๊ฒฝ์€ ๋‚˜๋ˆ ์„œ ์ปค๋ฐ‹ํ•ด ์ฃฝ์€ ํ–‰์ด ํ•œ๊บผ๋ฒˆ์— ์Ÿ์•„์ง€์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค.
  • Age(ํŠธ๋žœ์žญ์…˜ ID ๋‚˜์ด)๋Š” PostgreSQL ๊ณ ์œ ์˜ ์œ„ํ—˜ ์ง€ํ‘œ๋‹ค. Age Used Ratio๊ฐ€ ๊ถŒ์žฅ์„ (85%) ์œ„๋กœ ๊พธ์ค€ํžˆ ๋†’๊ฑฐ๋‚˜ Current Age๊ฐ€ wraparound ํ•œ๊ณ„๋กœ ํ–ฅํ•˜๋ฉด freeze๊ฐ€ ๋ชป ๋”ฐ๋ผ๊ฐ€๋Š” ๊ฒƒ์ด๋‹ค. ๊ธด idle in transaction ํŠธ๋žœ์žญ์…˜์ด ๊ฐ€์žฅ ํ”ํ•œ ์›์ธ์ด๋‹ค.
  • ์บ์‹œ ์ ์ค‘๋ฅ (Cache Hit Ratio)์€ 99% ํ›„๋ฐ˜์ด ์ •์ƒ์ด๊ณ , ๋–จ์–ด์ง€๋ฉด ๋””์Šคํฌ๋ฅผ ์ฝ๊ณ  ์žˆ๋‹ค๋Š” ์‹ ํ˜ธ๋‹ค. Blks Read์˜ ์ˆœ๊ฐ„ ์ตœ๋Œ“๊ฐ’์ด ํฌ๋ฉด ํ’€ ์Šค์บ”์„ ์˜์‹ฌํ•œ๋‹ค.
  • Temp Bytes·Temp Files๊ฐ€ 0์ด ์•„๋‹ˆ๋ฉด ์ •๋ ฌ·ํ•ด์‹œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋„˜์–ด ๋””์Šคํฌ๋กœ ํ˜๋ €๋‹ค๋Š” ๋œป์ด๋‹ค. ์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ์„ ๋Œ€์‹ ํ•˜๊ฒŒ ํ•œ๋‹ค.
  • ๋Œ€๋ถ€๋ถ„์˜ ์ง€ํ‘œ๋Š” ํ˜ผ์ž ํŠ€์ง€ ์•Š๋Š”๋‹ค. CPU·Active Backend·Blks Read·Tup·IOPS๊ฐ€ ๊ฐ™์€ ์‹œ๊ฐ์— ํ•จ๊ป˜ ์›€์ง์ด๋Š”์ง€๋ฅผ ๋ณด๋ฉด ์›์ธ์˜ ์œค๊ณฝ์ด ์žกํžŒ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ ์ง€ํ‘œ๋งˆ๋‹ค "ํ•จ๊ป˜ ํ™•์ธํ•  ์ง€ํ‘œ" ๋ฅผ ๊ฐ™์ด ์ ์–ด ๋‘” ๊ฒƒ์ด๋‹ค.

์ด๋กœ์จ MySQL·Oracle·PostgreSQL ์„ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฐ™์€ ํ‹€๋กœ ์ •๋ฆฌํ•ด ๋ดค์Šต๋‹ˆ๋‹ค. ์„ธ ๊ธ€์„ ๋‚˜๋ž€ํžˆ ๋†“๊ณ  ๋ณด๋ฉด, ๊ฐ™์€ "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค" ๋ผ๋„ ๋ฌด์—‡์„ ๊ฐ€์žฅ ์‹ ๊ฒฝ ์จ์„œ ๋ณด๋Š”์ง€๊ฐ€ ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์ด ๋ถ„๋ช…ํ•ด์ง‘๋‹ˆ๋‹ค.

  • MySQL์€ ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„์ธ InnoDB์—์„œ ์ƒ‰๊น”์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. ๋ฒ„ํผํ’€ ์ ์ค‘๋ฅ , ํ–‰ ๋ฝ ๋Œ€๊ธฐ, History list length(undo) ๊ฐ™์€ ์ง€ํ‘œ๊ฐ€ InnoDB์˜ ๋™์ž‘์—์„œ ๋น„๋กฏ๋ฉ๋‹ˆ๋‹ค.
  • Oracle์€ Redo·Undo·Library Cache·ํŒŒ์‹ฑ์ด ์ค‘์‹ฌ์ž…๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ๋Ÿ‰์€ Redo·Undo๋กœ, ๋™์‹œ์„ฑ·์ฝ๊ธฐ ์ผ๊ด€์„ฑ์€ Undo๋กœ, SQL ํšจ์œจ์€ ํŒŒ์‹ฑ(๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜)์œผ๋กœ ๋“œ๋Ÿฌ๋‚ฉ๋‹ˆ๋‹ค.
  • PostgreSQL์€ MVCC์™€ ๊ทธ ์ฒญ์†Œ(VACUUM) ๊ฐ€ ์ค‘์‹ฌ์ž…๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ์ด ์ฃฝ์€ ํ–‰์„ ๋‚จ๊ธฐ๊ณ , ๊ทธ๊ฒƒ์„ VACUUM์ด ์น˜์šฐ๋ฉฐ, ํŠธ๋žœ์žญ์…˜ ID์˜ ๋‚˜์ด(Age)๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ผ์ด ์ด DB์˜ ๊ณ ์œ ํ•œ ์ ๊ฒ€ ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

์„ธ DB ๋ชจ๋‘ ๊ฒฐ๊ตญ์€ "๋ณ€๊ฒฝ ์ „ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ•˜๊ณ  ์ •๋ฆฌํ•˜๋А๋ƒ" ๋ผ๋Š” ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๊ฐ์ž ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ’‰๋‹ˆ๋‹ค. Oracle์€ Undo๋ผ๋Š” ๋ณ„๋„ ๊ณต๊ฐ„์—, PostgreSQL์€ ํ…Œ์ด๋ธ” ์•ˆ์— ์˜› ๋ฒ„์ „์„ ๋‚จ๊ฒผ๋‹ค๊ฐ€ VACUUM์œผ๋กœ ์น˜์šฐ๊ณ , MySQL์˜ InnoDB๋Š” undo ๋กœ๊ทธ(History list)๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฐจ์ด๋ฅผ ์•Œ๊ณ  ๋ณด๋ฉด, ๊ฐ™์€ ๋ชจ๋‹ˆํ„ฐ๋ง ํ™”๋ฉด์ด๋ผ๋„ ์–ด๋А ์ง€ํ‘œ๋ฅผ ๋จผ์ € ๋ด์•ผ ํ•˜๋Š”์ง€๊ฐ€ DB๋งˆ๋‹ค ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ์„ธ ํŽธ์— ๊ฑธ์ณ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ด, ์–ด๋–ค DB์˜ ์ง€ํ‘œ๋ฅผ ๋ณด๋“  "๋ฌด์—‡์„ ์˜๋ฏธํ•˜๊ณ  / ํ‰์†Œ ์–ด๋А ์ •๋„์ด๊ณ  / ํŠ€๋ฉด ๋ญ˜ ์˜์‹ฌํ•˜๊ณ  / ์–ด๋–ค ์ฟผ๋ฆฌ๋กœ ํ™•์ธํ•˜๋Š”์ง€" ๋ผ๋Š” ๊ฐ™์€ ํ‹€๋กœ ์ ‘๊ทผํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.