JiwonDev

PostgreSQL ์™€ vaccum์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

by JiwonDev

PostgreSQL ๋ฟŒ-์šฐ

 

๐Ÿ€ PostgreSql

Oracle ์‚ฌ์šฉ์ž๋“ค์ด ๊ฐ€์žฅ ์‰ฝ๊ฒŒ ์ ์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์˜คํ”ˆ์†Œ์Šค DBMS์ด๋‹ค. postgres(ํฌ์ŠคํŠธ๊ทธ๋ฆฌ)๋ผ๊ณ ๋„ ๋งŽ์ด ๋ถ€๋ฅธ๋‹ค. ์กฐํšŒ ์„ฑ๋Šฅ์ ์ธ ์ธก๋ฉด์—์„œ ๋›ฐ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— MySQL์ฒ˜๋Ÿผ ํ•จ๊ป˜ ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค. http://www.postgresql.org/

https://d2.naver.com/helloworld/227936 , 1986๋…„ Ingres์—์„œ ์‹œ์ž‘ํ•˜์—ฌ 1995๋…„์— Postgres95 ์ด๋ฆ„์ด ์ฒ˜์Œ ๋ถ™์—ฌ์กŒ๋‹ค.

https://techblog.woowahan.com/6550/

 

Aurora MySQL vs Aurora PostgreSQL | ์šฐ์•„ํ•œํ˜•์ œ๋“ค ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ

์•ˆ๋…•ํ•˜์„ธ์š”, ํด๋ผ์šฐ๋“œ์Šคํ† ๋ฆฌ์ง€๊ฐœ๋ฐœํŒ€ ์ •์ง€์› ์ž…๋‹ˆ๋‹ค. ์ตœ๊ทผ ์ €ํฌ ํŒ€์—์„œ๋Š” Aurora MySQL๋กœ ์šด์˜๋˜๊ณ  ์žˆ๋˜ ๋Œ€๋Ÿ‰ ํ†ต๊ณ„์„ฑ DB๋ฅผ Aurora PostgreSQL๋กœ ์ด๊ด€ํ•˜๋Š” ๊ฒƒ์„ ๊ฒ€ํ† ์ค‘์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์˜ค๋Š˜์€ ์ค€๋น„ ๊ณผ์ •์—

techblog.woowahan.com

 

 

 

๐Ÿ€  PostgreSQL ๋Š” ์–ด๋–ค ๊ธฐ์ค€์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ์š”?

์ค‘์š”ํ•œ ๋‚ด์šฉ์€ ์•„๋‹ˆ๋ผ์„œ, ๊ถ๊ธˆํ•˜๋ฉด ๋ˆŒ๋Ÿฌ๋ณด์ž

๋”๋ณด๊ธฐ

์ „์„ธ๊ณ„์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ•œ๋ฒˆ ํ›‘์–ด์„œ ๋น„๊ตํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

https://db-engines.com/en/ranking - 2021๋…„ 10์›” ๊ธฐ์ค€

Orcale๊ณผ Microsoft ๋Š” ์œ ๋ฃŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋น„์Šค์ด๊ณ  MySQL๊ณผ PostgreSQL์€ ์˜คํ”ˆ์†Œ์Šค ๋ฌด๋ฃŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค.

๋ณดํ†ต MySQL๊ณผ PostgreSQL์˜ ์ธ๊ธฐ๊ฐ€ ๋งŽ์œผ๋ฉฐ ํšŒ์‚ฌ๋‚˜ ๊ด€๊ณต์„œ์ฒ˜๋Ÿผ ์‚ฌํ›„์ง€์›์ด ํ•„์š”ํ•œ ์ƒ์šฉ์„œ๋น„์Šค๋Š” ๋น„์‹ผ ์š”๊ธˆ์„ ์ง€๋ถˆํ•˜๊ณ  Oracle, Microsoft๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

 

์—ฌ๋‹ด์œผ๋กœ 2010๋…„๋Œ€๋Š” ๋‹ค์–‘ํ•œ DBMS๋“ค์ด ์šฐํ›„์ฃฝ์ˆœ์œผ๋กœ ํƒ„์ƒํ•˜๋˜ ์‹œ๊ธฐ์˜€๋‹ค.

๋ชจ๋ฐ”์ผ์˜ ๋“ฑ์žฅ์œผ๋กœ ์ „ํ†ต์ ์ธ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, RDBMS์˜ ์‹œ๋Œ€๋Š” ์ €๋ฌธ๋‹ค๋Š” ์ด์•ผ๊ธฐ๊ฐ€ ๋‚˜์™”๊ณ  NoSQL๊ณผ ๊ฐ™์€ ๋‹จ์ˆœํ•œ ๋กœ๊ทธ ์„ฑ๊ฒฉ์˜ ๋น…๋ฐ์ดํ„ฐ์˜ ์ €์žฅ์ด ํ•„์š”ํ•ด์ง€๋ฉฐ Cassandra๋‚˜ HBase, ๋‚˜์ค‘์— ๋‚˜์˜จ MongoDB๋“ฑ์ด ๋งŽ์€ ๊ด€์‹ฌ์„ ๋ฐ›์•˜์—ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ 10๋…„์ด ์ง€๋‚œ ์ง€๊ธˆ, ๊ทธ ๋ˆ„๊ตฌ๋„ ๊ทธ๋•Œ ์ถœ์‹œ๋๋˜ NoSQL DBMS๊ฐ€ ์ƒ์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ž ์‹ํ–ˆ๋‹ค๊ณ ๋Š” ์–ธ๊ธ‰ํ•˜์ง€ ์•Š๋Š” ๋“ฏ ํ•˜๋‹ค.

* ์บ์‹œ ์„œ๋ฒ„๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” Redis์™€ Memcached๋Š” ์„œ๋น„์Šค DBMS๋ผ๊ณ  ๋ณด๊ธฐ์—๋Š” ๋ฒ”์ฃผ๊ฐ€ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๋‹ค. ElasticSearch๋„ ๋งˆ์ฐฌ๊ฐ€์ง€

๊ทธ๋‚˜๋งˆ HBase์™€ MongoDB์ •๋„๊ฐ€ ์ž๊ธฐ๋งŒ์˜ ์˜์—ญ์—์„œ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์œผ๋ฉฐ ์˜ˆ์ƒ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์—ฌ์ „ํžˆ MySQL, Postgres์™€ ๊ฐ™์€ ๊ด€๊ณ„ํ˜• DB๊ฐ€ ์ˆ˜๋งŽ์€ NoSQL DBMS์˜ ์—ญํ• ์„ ๋Œ€์ฒดํ•˜๋ฉฐ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค.

 

 

์˜คํ”ˆ์†Œ์Šค DB ๋Œ€๊ฒฐ, MySQL vs Postgres

์›๋ž˜ ๋ฌด๋ฃŒ DBMS์ค‘์—์„  MySQL ์‚ฌ์šฉ๋ฅ ์ด ์••๋„์ ์ด์—ˆ์œผ๋‚˜ 2009๋…„์— ์˜ค๋ผํด์ด Sun์‚ฌ๋ฅผ ์ธ์ˆ˜ํ•˜๋ฉด์„œ MySQL์˜ ์†Œ์œ ๊ถŒ ์ด์Šˆ, ์œ ๋ฃŒํ™”๋“ฑ์˜ ๋ฌธ์ œ ๋•Œ๋ฌธ์— PostgreSQL ์‚ฌ์šฉ๋ฅ ์ด ์ฆ๊ฐ€ํ–ˆ๊ณ  ์ดํ›„ ์ด๋ž˜์˜ ์žฅ์ ๋“ค ๋•๋ถ„์— ์‚ฌ์šฉ๋ฅ ์ด ๊พธ์ค€ํ•˜๊ฒŒ ์ฆ๊ฐ€๋˜๊ณ ์žˆ๋‹ค.

https://news.hada.io/topic?id=8018

https://news.hada.io/topic?id=11287

https://news.hada.io/topic?id=8018&utm_source=slack&utm_medium=bot&utm_campaign=T03385HMGMD

PostgreSQL ์žฅ์ 

  • PostgreSQL์€ SQL ํ‘œ์ค€์„ ๊ฒฝ์Ÿ์‚ฌ๋ณด๋‹ค ์ž˜ ์ง€ํ‚ค๊ณ  ์žˆ๋Š” ํŽธ์ด๋‹ค.
  • ๋‹ค์–‘ํ•œ join ๋ฐฉ๋ฒ• (sort merge join , hash join)์„ ์ œ๊ณตํ•˜์—ฌ ๋ณต์žกํ•œ ์กฐํšŒ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์ด ์ข‹๋‹ค.
  • PostGIS(์ขŒํ‘œ๊ณ„)์™€ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ํ™•์žฅ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ๊ณตํ•œ๋‹ค.

PostgreSQL ๋‹จ์ 

  • update ๋ฅผ ๊ณผ๊ฑฐ ํ–‰์„ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ์šด ํ–‰์„ ์ถ”๊ฐ€ํ•˜๋Š” ํ˜•์‹์ด๋ผ ๊ฒฝ์Ÿ์‚ฌ์— ๋น„ํ•ด ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๋Š” ํŽธ์ด๋‹ค
    ์ฆ‰ ์ˆ˜์ •๋ณด๋‹ค insert ๋ฅผ ์ฃผ๋กœ ํ•˜๊ณ  ๋ณต์žกํ•œ ์กฐํšŒ๊ฐ€ ๋งŽ์€ ์„œ๋น„์Šค์—์„œ ์ ํ•ฉํ•˜๋‹ค.
  • MVCC ๊ฐ€ ์ถ”๊ฐ€ ์ €์žฅํ•˜๋Š” ์‹์œผ๋กœ ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค. ์ดํ›„ ๋งˆ์น˜ Java GC ์ฒ˜๋Ÿผ auto vaccum์„ ํ†ตํ•ด ์ฃฝ์€ ๋ฐ์ดํ„ฐ๋“ค์„ ์ •๋ฆฌํ•œ๋‹ค. ์ฆ‰ auto vaccum ๋™์ž‘์— ๋Œ€ํ•ด ์ž˜ ์•Œ๊ณ  ์žˆ์ง€์•Š๊ณ  ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ฃฝ์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์Œ“์—ฌ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

 

 

๐Ÿ€ Postgre MVCC ์™€ vaccum

MVCC(Multi-Version Concurrency Control)๋Š” ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์—์„œ ๋ฝ์„ ๊ฑธ์ง€ ์•Š๊ณ  ๋™์‹œ์„ฑ์„ ๊ด€๋ฆฌํ•ด ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ•์„ ์˜๋ฏธํ•œ๋‹ค.

postgreSQL์˜ MVCC๋Š” ์ˆ˜์ •ํ›„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์œผ๋กœ insertํ•œ ๋’ค ๋‚˜์ค‘์— ๋”ฐ๋กœ vaccum ํ•ด์ค€๋‹ค. ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ๋™์‹œ์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”์‹œ์ผฐ๋‹ค.

MySql์€ undo log๋กœ ๊ตฌํ˜„ํ•œ๊ฑฐ๋ผ ์ผ์ •์‹œ๊ฐ„ ์ดํ›„ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ •๋ฆฌํ•œ๋‹ค. postgre๋Š” ๊ฐ™์€ ๊ณต๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์† ์Œ“๋Š” ํ˜•์‹์ด๋ผ GC(vaccum)์ด ํ•„์š”ํ•˜๋‹ค.

 

๋‹ค์‹œ ์„ค๋ช…ํ•˜์ž๋ฉด (* ํŠธ๋žœ์žญ์…˜ID = tx_id , ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ = Tuple )

  • Postgre MVCC๋Š” ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘ํ•˜๊ฒŒ ๋˜๋ฉด ๋ณธ์ธ์˜ id ๋ฅผ ํ• ๋‹น๋ฐ›๋Š”๋‹ค.
  • ์ดํ›„ UPDATE๋“ฑ์„ ํ•  ๋•Œ page (=Free Space Map page)๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ณ€๊ฒฝ๋  ๋•Œ ๋งˆ๋‹ค ํ˜„์žฌ์˜ ์Šค๋ƒ…์ƒท์„ insert ํ˜•์‹์œผ๋กœ ์Œ“์•„๊ฐ„๋‹ค.
  • MVCC ๊ตฌํ˜„์„ ์œ„ํ•ด ํ˜„์žฌ ๋ฐ์ดํ„ฐ ํŽ˜์ด์ง€ ๋‚ด์— ์ž์‹ ์˜ tx_id ๋ณด๋‹ค ์ž‘์€๊ฐ’์˜ id๋ฅผ ๊ฐ€์ง„ Tuple์„ ์ฝ์–ด์˜จ๋‹ค.

์ด ๋•Œ ๊ฐ Tuple์— ํ• ๋‹น๋˜๋Š” tmin, tmax๊ฐ’์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • xmin (*tx_id min)
    - INSERT ์‹œ  -> ์‹ ๊ทœ Tuple ์˜ xmin ์— tx_id ํ• ๋‹น
    - UPDATE ์‹œ -> ์‹ ๊ทœ Tuple ์˜ xmin ์— tx_id ํ• ๋‹น
  • xmax (*tx_id max)
    ์‹ ๊ทœ Tuple ์˜ xmax ์—๋Š” NULL ํ• ๋‹น
    DELETE ์‹œ -> ์ด์ „ Tuple ์˜ xmax ์— tx_id ํ• ๋‹น
    UPDATE ์‹œ -> ์ด์ „ Tuple ์˜ xmax ์— tx_id ํ• ๋‹น, 

์ด ๊ณผ์ • ์†์—์„œ ์—ฌ๋Ÿฌ๋ฒˆ ๋ณ€๊ฒฝ๋˜์–ด ์“ธ๋ชจ์—†์–ด์ง„ ์ด์ „ ๋ฐ์ดํ„ฐ๋“ค์€ ์–ด๋””์—๋„ ์ฐธ์กฐ๋˜์ง€ ์•Š๋Š”๋ฐ, ์ด๋ฅผ dead tuple์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ด dead tuple์€ ์ˆ˜๋™ ๋ช…๋ น์–ด๋กœ ์ง€์šธ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๋‹คํ–‰ํžˆ๋„ postgre auto vaccum์„ ํ†ตํ•ด ๋Œ€๋ถ€๋ถ„ ์ฒ˜๋ฆฌ๋œ๋‹ค.

 

 

๐Ÿค” vaccum์ด ๋Œ€์ฒด ๋ญ์ฃ ? ์•ˆํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฑฐ์ฃ ?

์ฐธ๊ณ ๋กœ ์„œ๋น„์Šค ํŠธ๋ž˜ํ”ฝ์ด ์—„์ฒญ๋‚œ ๋Œ€๊ธฐ์—…์ด๋ผ๋ฉด, Postgre auto-vaccum ์„ค์ •๋„ ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•ด๋ณด์•„์•ผํ•œ๋‹ค.

 

์šฐ์„  Postgre์—์„œ๋Š” Vaccum๊ณผ Vaccum full 2๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋Š”๋ฐ, full ์˜ ๊ฒฝ์šฐ ๋””์Šคํฌ ๋ฉ”๋ชจ๋ฆฌ๊นŒ์ง€ ์ •๋ฆฌํ•˜์ง€๋งŒ ํ…Œ์ด๋ธ”์—์„œ ๋ฒ ํƒ€๋ฝ์„ ๊ฑธ์–ด DML, ์ฟผ๋ฆฌ ์–ด๋– ํ•œ ๊ฒƒ๋„ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์‹œ๊ฐ„๋„ ์˜ค๋ž˜๊ฑธ๋ฆฐ๋‹ค. ์šด์˜๋„์ค‘์—๋Š” ๊ฐ€๋Šฅํ•˜๋ฉด vaccum full ์ž‘์—…์„ ํ”ผํ•ด์•ผ ํ•˜๊ธฐ์— auto vaccum ๊ธฐ๋ณธ ๊ฐ’์€ vaccum full ์ž‘์—…์„ ํ•˜์ง€ ์•Š๊ฒŒ ์„ค์ •๋˜์–ด์žˆ๋‹ค. ๋””์Šคํฌ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ๋“ฑ ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์ž. ๋‹จ์ˆœํžˆ ํŠน์ • ํ…Œ์ด๋ธ”์—์„œ ์ƒ๊ธด ๋ฌธ์ œ๋ผ๋ฉด ALTER TABLE๋กœ ์ƒˆ๋กœ์šด ํ…Œ์ด๋ธ”์„ ๋งŒ๋“œ๋Š”๊ฒŒ ๋” ๋‚ซ๋‹ค. + ์ฐธ๊ณ ๋กœ Truncate๋กœ ํ†ต์งธ๋กœ ๋‚ ๋ฆฌ๋ฉด dead tuple๋„ ํ•จ๊ป˜ ์ •๋ฆฌ๋œ๋‹ค.

-- DB ์ „์ฒด ํ’€ ์‹คํ–‰
vacuum full analyze;

-- DB ์ „์ฒด ๊ฐ„๋‹จํ•˜๊ฒŒ ์‹คํ–‰
vacuum verbose analyze;

-- ํ•ด๋‹น ํ…Œ์ด๋ธ”๋งŒ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‹คํ–‰
vacuum analyse [ํ…Œ์ด๋ธ” ๋ช…];

-- ํŠน์ • ํ…Œ์ด๋ธ”๋งŒ ํ’€ ์‹คํ–‰
-- ์ฐธ๊ณ ๋กœ full ์‹คํ–‰์‹œ pg_class.relfilenode ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š”๋ฐ, ์ด๋Š” ๋””์Šคํฌ์— ์ €์žฅ๋˜๋Š” ๋ฌผ๋ฆฌ์ ์ธ ํŒŒ์ผ๋ช…์ด๋‹ค.
vacuum full [ํ…Œ์ด๋ธ”๋ช…];

 

์ผ๋ฐ˜ vaccum ์ž‘์—…์€ ๋ฝ์€ ์•ˆ๊ฑธ๋ฆฌ์ง€๋งŒ Disk I/O ๋ถ€ํ•˜๋ฅผ ๋งŒ๋“ค๊ณ  ๋™์‹œ์— ์ž‘์—…์ค‘์ธ ๋‹ค๋ฅธ DB ์„ธ์…˜์˜ ์„ฑ๋Šฅ์„ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค. ๊ทธ๋ž˜์„œ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰์‹œ ์‚ฌ์šฉ๋Ÿ‰์ด ์ ์€ ์ƒˆ๋ฒฝ์‹œ๊ฐ„๋Œ€์— vaccum ๋ช…๋ น์„ ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค. ๋ฌผ๋ก  ์ด๋Š” ๊ด€๋ จ ์„ค์ • ๋ณ€๊ฒฝ์œผ๋กœ ์–ด๋Š์ •๋„ ์กฐ์ ˆ์€ ๊ฐ€๋Šฅํ•˜๋‹ค. 

 

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

 

auto-vaccum ์€ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฐ๋ชฌ ํ”„๋กœ์„ธ์Šค(autovaccum launcher)๋กœ ํ•ญ์ƒ ์‹คํ–‰๋˜์–ด ์žˆ์œผ๋ฉฐ ํ…Œ์ด๋ธ”์˜ ์ž๋ฃŒ๊ฐ€ ๋งŽ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ  (autovaccum worker) ํ”„๋กœ์„ธ์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ž๋™์œผ๋กœ ์‹คํ–‰๋œ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ๋ฐฉํ•ดํ•˜์ง€ ์•Š์œผ๋‚˜ share update lock์˜ ๊ฒฝ์šฐ์—๋งŒ vaccum์ด ์ค‘๋‹จ๋˜๊ณ , ํ•ด๋‹น ๋ฝ์„ ๊ณ„์† ์žก๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ vaccum์ด ์ œ๋Œ€๋กœ ์™„๋ฃŒ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ๋‹น์—ฐํ•œ๋ง์ด์ง€๋งŒ db max_connection ๊ฐ™์€ ์˜ต์…˜๊ณผ autovaccum ํ”„๋กœ์„ธ์Šค๋Š” ์•„๋ฌด๋Ÿฐ ๊ด€๋ จ์ด ์—†๋‹ค.  

 

์ฐธ๊ณ ๋กœ ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ vaccum ์„ธ์…˜์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

SELECT datname, usename, pid, CURRENT_TIMESTAMP - xact_start AS xact_runtime, query
FROM pg_stat_activity
WHERE upper(query) LIKE '%VACUUM%'
ORDER BY xact_start;

 

 

 

PostgreSQL์—์„œ VACUUM ๋ช…๋ น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ด์œ ๋กœ ์ •๊ธฐ์ ์œผ๋กœ ๊ฐ ํ…Œ์ด๋ธ” ๋‹จ์œ„๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค

  1. ์ฃฝ์€ tuple ๋•Œ๋ฌธ์— ์ƒ๊ธฐ๋Š” ๋ถˆํ•„์š”ํ•œ ์ถ”๊ฐ€ Disk I/O์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ค„์ด๊ธฐ ์œ„ํ•ด  ํ•„์š”ํ•˜๋‹ค.
  2. ํŠธ๋žœ์žญ์…˜ ID ๊ฒน์นจ์ด๋‚˜, ๋‹ค์ค‘ ํŠธ๋žœ์žญ์…˜ ID ๊ฒน์นจ ์ƒํ™ฉ์œผ๋กœ ์˜ค๋ž˜๋œ ์ž๋ฃŒ๊ฐ€ ์†์‹ค ๋  ๊ฐ€๋Šฅ์„ฑ์„ ๋ฐฉ์ง€ํ•ด์•ผํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
  3. PostgreSQL ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ณ„ํš๊ธฐ๊ฐ€ ์‚ฌ์šฉํ•  ์ž๋ฃŒ ํ†ต๊ณ„ ์ •๋ณด(ANALYZE)๋ฅผ ๊ฐฑ์‹ ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
  4. ์ปค๋ฒ„๋ฆฌ์ง€ ์ธ๋ฑ์Šค(only index) ์†๋„๋ฅผ ์œ„ํ•ด, ์‹ค์ž๋ฃŒ ์ง€๋„(visibility map, vm) ๊ฐฑ์‹ ํ•  ํ•„์š” ์žˆ๋‹ค.

 

 

1๏ธโƒฃ ์ฃฝ์€ tuple ๋•Œ๋ฌธ์— ์ƒ๊ธฐ๋Š” ๋ถˆํ•„์š”ํ•œ ์ถ”๊ฐ€ Disk I/O์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•˜๋‹ค.

Postgre๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ๋•Œ FSM page (Free Space Map page) ๋‹จ์œ„๋กœ ์ฝ์–ด๋“ค์ธ๋‹ค. ์ด๋Š” ๊ธฐ๋ณธ 8KB์ธ๋ฐ ํŽ˜์ด์ง€์— ์“ฐ๋ ˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ๋‹ค๋ฉด ๋” ๋งŽ์€ FSM page๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ ค์•ผํ•œ๋‹ค. ์ฆ‰ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‚ญ๋น„๋˜๋Š”๊ฑด ๋ฌผ๋ก ์ด๊ณ  Disk I/O ์ž‘์—… ํšŸ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๊ฒŒ ๋˜๊ณ  ์Œ“์ด๋ฉด ์Œ“์ผ์ˆ˜๋ก ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ ์ €ํ•˜๋กœ ์ด์–ด์ง€๊ฒŒ ๋œ๋‹ค.

์›๋ž˜ 2ํŽ˜์ด์ง€๋กœ ๋๋‚  ๊ฑธ ์ฃฝ์€ ๋ฐ์ดํ„ฐ ๋•Œ๋ฌธ์— ์ˆ˜์‹ญ๋งŒ ๊ฐœ์˜ ํŽ˜์ด์ง€๋ฅผ ๋” ์ฝ์–ด์•ผํ• ์ง€ ๋ชจ๋ฅธ๋‹ค. ์ด๋Š” ๊ณง Disk I/O์˜ ์ฆ๊ฐ€ = ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ ํ•˜๋ฝ์„ ์˜๋ฏธํ•œ๋‹ค.

 

์ฐธ๊ณ ๋กœ ์ด๋ ‡๊ฒŒ ๋ถˆํ•„์š”ํ•œ ํŽ˜์ด์ง€๋ฅผ ๋งŽ์ด ์ฝ๊ฒŒ๋˜๋ฉด, ์ธ๋ฑ์Šค๊ฐ€ ๋ฉ€์ฉกํžˆ ์žˆ์Œ์—๋„ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€์•Š๋Š” ํ™ฉ๋‹นํ•œ ์ƒํ™ฉ๋„ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

2๏ธโƒฃ ํŠธ๋žœ์žญ์…˜ ID ๊ฒน์นจ์œผ๋กœ ์˜ค๋ž˜๋œ ์ž๋ฃŒ๊ฐ€ ์†์‹ค ๋  ๊ฐ€๋Šฅ์„ฑ์„ ๋ฐฉ์ง€ํ•ด์•ผํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

Postgre MVCC์— ์‚ฌ์šฉ๋˜๋Š” ํŠธ๋žœ์žญ์…˜ ID๋Š” 32bit ์–‘์ˆ˜์ด๊ธฐ์— 42์–ต ๊ฐœ๊นŒ์ง€๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋กœ 0์ด ๋˜๋ฉด์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์†์‹ค๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ์œ„ํ•ด ์„ค์ •๋œ ์ˆ˜์น˜๋ฅผ ๋„˜๊ฒŒ๋˜๋ฉด auto-vaccum ์„ ์ด์šฉํ•ด ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ํŠธ๋žœ์žญ์…˜ ID๋ฅผ ๋”ฐ๋กœ ์˜ˆ์•ฝ๋œ Fronzen xid(2)๋กœ ๋ฐ”๊ฟ”๋ฒ„๋ฆฐ๋‹ค. ์ด๋ฅผ freeze (๋˜๋Š” anti wraparound vaccum)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์ฐธ๊ณ ๋กœ Postgre๋Š” ํŠธ๋žœ์žญ์…˜ ID๊ฐ€ Fronzen xid๋กœ ๋˜์–ด์žˆ๋‹ค๋ฉด, ๊ฐ’์„ ๋น„๊ตํ•˜์ง€์•Š๊ณ  ๋ฌด์กฐ๊ฑด ์˜›๋‚  Tuple๋กœ ํŒ๋‹จํ•œ๋‹ค.

์ตœ๋Œ€๊ฐ’์ด 40์–ต๊ฐœ๋ผ, 20์–ต๊ฐœ๊ฐ€ ๋˜๊ธฐ์ „์— Freeze ํ•ด์„œ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ๊ฒน์นจ์—†์ด XID๋ฅผ ์Œ“์•„์„œ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

์ฐธ๊ณ ๋กœ PostgreSQL 9.4 ์ด์ „์—๋Š” ๋‹จ์ˆœํžˆ xmin = 2 (Fronze xid) ๋กœ ๋ฎ์–ด์”Œ์›Œ์„œ ์ €์žฅํ–ˆ๋Š”๋ฐ ์ƒˆ ๋ฒ„์ „์—์„œ๋Š” ๋ณ„๋„์˜ flag(1bit) ๊ฐ’์œผ๋กœ ํ‘œ์‹œํ•ด๋‘๊ณ  ๋‘๊ณ  xmin์„ ๋ณ€๊ฒฝํ•˜์ง€๋Š” ์•Š๊ธฐ์— ์žฅ์•  ๋ถ„์„์šฉ์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜๋„ ์žˆ๋‹ค. 

 

์ด ์ž„๊ณ„์น˜๋Š” vacuum_freeze_min_age ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ธฐ๋ณธ ์ตœ๋Œ€๊ฐ’์€ 5000๋งŒ์ด๋‹ค.

์‹ค์ œ ๋™์ž‘์—์„œ๋Š” ์ฆ‰์‹œ auto-vaccum์ด ์‹คํ–‰๋˜๋Š” ๊ฑด ์•„๋‹ˆ๊ณ  freeze๊ฐ€ ํ•„์š”ํ•œ Tuple์ด ์ƒ๊ธฐ๋ฉด ํ…Œ์ด๋ธ” ํŒŒ๋ผ๋ฉ”ํƒ€(vacuum_freeze_table_age)  ๊ฐ’์— ์ €์žฅํ•ด๋‘์—ˆ๋‹ค๊ฐ€ ์„ค์ •๋œ ์ž„๊ณ„์น˜(autovacuum_freeze_max_age) ๋ฅผ ๋„˜๊ฒŒ๋˜๋ฉด ๊ฐ•์ œ๋กœ freeze(Anti Wraparound Vaccum)๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

๊ทธ๋Ÿด ์ผ์€ ์—†๊ฒ ์ง€๋งŒ auto-vaccum์ด ๋ฌดํ•œ์ • ์‹คํŒจํ•ด์„œ ํŠธ๋žœ์žญ์…˜ID ๊ฒน์นจ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์šฐ๋ ค๊ฐ€ ์žˆ๋‹ค๋ฉด, ์•„๋ž˜์˜ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋„์›Œ์ฃผ๊ณ 

WARNING:  database "mydb" must be vacuumed within 10985967 transactions
HINT:  To avoid a database shutdown, execute a database-wide VACUUM in that database.

 

์ด๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ๊ณ„์† ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์•„๋ž˜ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋‚จ๊ธฐ๋ฉฐ Postgre ์„œ๋ฒ„๋Š” ๋ชจ๋“  ํŠธ๋žœ์žญ์…˜ ์ž‘์—…์„ ์ค‘๋‹จํ•œ๋‹ค.

ERROR:  database is not accepting commands to avoid wraparound data loss in database "mydb"
HINT:  Stop the postmaster and use a standalone backend to VACUUM in "mydb".

 

๋งŒ์•ฝ ์šฐ๋ฆฌ DB์—์„œ ์˜ค๋ž˜๋œ ํŠธ๋žœ์žญ์…˜ID๊ฐ€ ์–ด๋Š์ •๋„์ธ์ง€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, pg_class ์™€ pg_database ํ…Œ์ด๋ธ”๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

-- relfrozenxid ์€ vaccum ์ •๋ฆฌํ–ˆ๋˜ ๊ธฐ์ค€ ํŠธ๋žœ์žญ์…˜ID๊ฐ’ ์ด๋‹ค. (์ด ๊ฐ’๋ณด๋‹ค ์˜ค๋ž˜๋œ ๋ชจ๋“ ID๋Š” freeze ์ฒ˜๋ฆฌ๋จ)
-- age๋Š” ํ˜„์žฌ ์‹œ์ ๊ธฐ์ค€, vaccum์œผ๋กœ ์ •๋ฆฌ๋œ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํŠธ๋žœ์žญ์…˜ID๊ฐ’ ์ด๋‹ค.
SELECT c.oid::regclass as table_name,
       greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age
FROM pg_class c
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r', 'm');

SELECT datname, age(datfrozenxid) FROM pg_database;

 

 

์—ฌ๋‹ด์œผ๋กœ Postgre 9.3 ์ดํ›„๋กœ ๋‹ค์ค‘ ํŠธ๋žœ์žญ์…˜ ID ๊ฒน์นจ๋ฌธ์ œ๊ฐ€ ๊ณต์‹๋ฌธ์„œ์— ์ถ”๊ฐ€๋˜์—ˆ๋Š”๋ฐ, ์„ค๋ช…์€ ์œ„์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ถ๊ธˆํ•˜๋ฉด ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์ž.

 

 

3๏ธโƒฃ PostgreSQL ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ณ„ํš๊ธฐ๊ฐ€ ์‚ฌ์šฉํ•  ์ž๋ฃŒ ํ†ต๊ณ„ ์ •๋ณด(ANALYZE)๋ฅผ ๊ฐฑ์‹ ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

์ด๋Š” ์œ„์—๋„ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ, auto-vaccum ๊ณผ์ •์†์—์„œ ํ•„์š”์— ๋”ฐ๋ผ ANALYZE๋ฅผ ์ถ”๊ฐ€๋กœ ์‹คํ–‰ํ•œ๋‹ค.

์‹ค์ œ DB ๋ฒ„์ „์„ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฒฝ์šฐ ์‹คํ–‰๊ณ„ํš์ด ํฌ๊ฒŒ ๋‹ฌ๋ผ์ ธ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋•Œ ์ฟผ๋ฆฌ๋ฅผ ๊ณ„์† ์‹คํ–‰์‹œ์ผœ์ฃผ๊ฑฐ๋‚˜ ใ…‡ANALYZE ๋ช…๋ น์„ ์ž…๋ ฅํ•˜๋ฉด Postgre ์„œ๋ฒ„๊ฐ€ ์•Œ๋งž์€ ์‹คํ–‰๊ณ„ํš์œผ๋กœ ์ตœ์ ํ™” ํ•ด์ค€๋‹ค.

 

์—ฌ๋‹ด์œผ๋กœ anaylze๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
analyze;

# ํ…Œ์ด๋ธ”
analyze t1;

# ์ปฌ๋Ÿผ
analyze t1 (c1, c2);

# ์ƒ์„ธ ์ˆ˜ํ–‰๋‚ด์—ญ ํ™•์ธ
analyze verbose t1;
-- INFO:  analyzing "public.t1"
-- INFO:  "t1": scanned 443 of 443 pages, containing 100000 live rows and 0 dead rows; 30000 rows in sample, 100000 estimated total rows
-- ANALYZE

 

๋˜ํ•œ ์•„๋ž˜์˜ ์„ค์ •์„ ๊ฑด๋“œ๋ฆฐ ์ ์ด ์—†๋‹ค๋ฉด, ๊ธฐ๋ณธ์ ์œผ๋กœ auto-vaccum ์€ ์‹คํ–‰ํ•˜๋ฉด์„œ ํ†ต๊ณ„ ์ •๋ณด๋ฅผ ๊ฐ™์ด ์ˆ˜์ง‘ํ•˜์—ฌ ํŒ๋‹จ ๊ธฐ์ค€์— ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํ•„์š”ํ•˜๋ฉด pg_class, pg_stats ๋“ฑ์˜ ํ…Œ์ด๋ธ”๋กœ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • autovacuum (๊ธฐ๋ณธ๊ฐ’ on) : autovacuum ํ”„๋กœ์„ธ์Šค ์‚ฌ์šฉ ์—ฌ๋ถ€
  • track_counts (๊ธฐ๋ณธ๊ฐ’ true): ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ†ต๊ณ„์ •๋ณด ์ˆ˜์ง‘์—ฌ๋ถ€
  • autovacuum_analyze_scale_factor (๊ธฐ๋ณธ๊ฐ’0.1) : ํ…Œ์ด๋ธ” ๋‚ด์˜ ๋ ˆ์ฝ”๋“œ ๋ณ€๊ฒฝ ๋น„์œจ
  • autovacuum_analyze_threshold (๊ธฐ๋ณธ๊ฐ’ 50) : ์ตœ์†Œ ๋ณ€๊ฒฝ ๋ ˆ์ฝ”๋“œ ์ˆ˜
#------------------------------------------------------------------------------
# postgresql.conf ํŒŒ์ผ ๋‚ด AUTOVACUUM PARAMETERS
#------------------------------------------------------------------------------
#autovacuum = on                        # Enable autovacuum subprocess?  'on'  ## PostgreSQL 9.x ๋ถ€ํ„ฐ๋Š” default๋กœ ํ™œ์„ฑํ™”๋œ ์ƒํƒœ์ž„
                                        # requires track_counts to also be on.
#log_autovacuum_min_duration = -1       # -1 disables, 0 logs all actions and   ## 0๋ฉด  autovacuum ์ผ์–ด๋‚ ๋•Œ๋งˆ๋‹ค ๋กœ๊ทธ ๋‚จ๊ธฐ๊ณ ,
                                        # their durations, > 0 logs only           200ms ์„ค์ •ํ•˜๋ฉด 200ms ์ด์ƒ ๊ฑธ๋ ค ์‹คํ–‰๋˜๋Š”
                                        # actions running at least this number
                                        # of milliseconds.
#autovacuum_max_workers = 3             # max number of autovacuum subprocesses
                                        # (change requires restart)
#autovacuum_naptime = 1min              # time between autovacuum runs     ## ์‹คํ–‰ ์ฃผ๊ธฐ.. 1min ๋„˜ ์งง๋„ค..
#autovacuum_vacuum_threshold = 50       # min number of row updates before ## vacuum ์ž‘์—…์‹œ ์ตœ์†Œ ๊ฐฏ์ˆ˜.. 1000์ด์ƒ์œผ๋กœ ๋Š˜๋ ค๋„ ๋จ
                                        # vacuum
#autovacuum_analyze_threshold = 50      # min number of row updates before ## ๋งˆ์ฐฌ๊ฐ€์ง€ 500์ด์ƒ
                                        # analyze 
#autovacuum_vacuum_scale_factor = 0.2   # fraction of table size before vacuum
#autovacuum_analyze_scale_factor = 0.1  # fraction of table size before analyze
#autovacuum_freeze_max_age = 200000000  # maximum XID age before forced vacuum
                                        # (change requires restart)
#autovacuum_vacuum_cost_delay = 20ms    # default vacuum cost delay for
                                        # autovacuum, in milliseconds;
                                        # -1 means use vacuum_cost_delay
#autovacuum_vacuum_cost_limit = -1      # default vacuum cost limit for
                                        # autovacuum, -1 means use
                                        # vacuum_cost_limit

์‹ค์ œ๋กœ ์ฟผ๋ฆฌ ์‹คํ–‰๊ณ„ํš (EXPLAIN ANALYZE)์„ ์ธก์ •ํ•  ๋•Œ ํ•ด๋‹น ํ†ต๊ณ„ ํ…Œ์ด๋ธ”๋“ค์„ ์‚ฌ์šฉํ•œ๋‹ค.

 Postgre ์‹คํ–‰๊ณ„ํš ๋ฐ ํ†ต๊ณ„ - ์ฟผ๋ฆฌ์„ฑ๋Šฅ ๋ถ„์„ํ•˜๊ธฐ seunghyunson

 

 

 

4๏ธโƒฃ  ์ปค๋ฒ„๋ฆฌ์ง€ ์ธ๋ฑ์Šค(only index) ์†๋„๋ฅผ ์œ„ํ•ด, vm(visibility map, vm) ๊ฐฑ์‹ ํ•  ํ•„์š” ์žˆ๋‹ค.

3๋ฒˆ ANAYLZE์™€ ๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅธ๋‚ด์šฉ์ธ๋ฐ, postgre๋Š” vaccum ์ž‘์—…์„ ํ†ตํ•ด ๋‚ด๋ถ€์˜ visibility map์„ ๊ฐฑ์‹ ํ•ด์„œ ํ˜„์žฌ์™€ ๋ฏธ๋ž˜์˜ ๋ชจ๋“  ํŠธ๋žœ์žญ์…˜์ด ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ํ…Œ์ด๋ธ”๋ณ„ ์ง€๋„๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘”๋‹ค.

https://postgresql.kr/docs/13/storage-vm.html ๋ฅผ ๊ตฌ๊ธ€๋ฒˆ์—ญํ•œ ๋‚ด์šฉ

 

์ด๋Š” ์ธ๋ฑ์Šค ์ „์šฉ ์ฟผ๋ฆฌ๋“ค (์ปค๋ฒ„๋ฆฌ์ง€ ์ธ๋ฑ์Šค) ์— ๋Œ€ํ•ด ๋น ๋ฅธ ์‘๋‹ต์„ ์ œ๊ณตํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. PostgreSQL์˜ ์ธ๋ฑ์Šค๋Š” ์–ด๋–ค ์ž๋ฃŒ๋ฅผ ์–ด๋–ค DB ์„ธ์…˜์— ๋ณด์—ฌ์ค˜์•ผํ• ์ง€ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ด๋ธ”์˜ page๋ฅผ ์ฝ์–ด๋ณด๋Š”๋ฐ,  ๋งŒ์•ฝ vaccum ๋•Œ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘” visibility map ๋งŒ์œผ๋กœ ์ฐพ์•„์„œ ์‹ค์ œ page ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์ฐพ๊ธฐ์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์€ ํ…Œ์ด๋ธ”์„ ์กฐํšŒํ•  ๋•Œ Disk I/O๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

๐Ÿ€ ์‹ค์ œ๋กœ ์žˆ์—ˆ๋˜ Vaccum ์ด์Šˆ

์‚ฌ๋‚ด์—์„œ ์‚ฌ์šฉ์ž์˜ ํ•™์Šต์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ์œ„ํ•ด SpringStateMachine๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ๊ฐ์˜ ์‚ฌ์šฉ์ž์˜ ํ•™์Šต์ƒํƒœ(Context) ๊ฐ์ฒด๋ฅผ ์ง๋ ฌํ™”ํ•œ ๋’ค ๊ณ„์† ์—…๋ฐ์ดํŠธํ•˜์—ฌ DB์— ์ €์žฅํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

create table state_machine (
     machine_id varchar(255) not null,
     state varchar(255),
     state_machine_context oid,
     primary key (machine_id)
);

 

postgres์—์„œ๋Š” lobs(Large Objects) ๋ฅผ ์ €์žฅํ•  ๋•Œ ์‹๋ณ„์šฉ oid ๊ฐ’ ์นผ๋Ÿผ์— ์ €์žฅํ•ด๋‘๊ณ  ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” pg_largeobject ํ…Œ์ด๋ธ”์— ๋”ฐ๋กœ ์ €์žฅ๋œ๋‹ค.

 

๐Ÿค” ๊ทธ๋ž˜์„œ ๋ญ๊ฐ€ ๋ฌธ์ œ์˜€์ฃ ?

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ๋˜์—ˆ๋˜๊ฑด oid ๊ฐ’์€ auto-vaccum์ด ์ฒ˜๋ฆฌํ•ด์ฃผ์ง€๋งŒ large_object์— ์ €์žฅ๋˜์–ด์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” oid์™€์˜ ๋งํฌ ๋•Œ๋ฌธ์— dead tuple๋กœ ์ทจ๊ธ‰๋˜์ง€ ์•Š์•„ ์ง€์›Œ์ง€์ง€ ์•Š์•˜๋‹ค. ์•„๋งˆ oid๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋”๋ผ๋„ ๊ธฐ์กด ๋ฐ์ดํ„ฐ ์ˆ˜์ •์ด ์•„๋‹Œ ์ƒˆ๋กœ์šด row๊ฐ€ ์ถ”๊ฐ€๋˜๋Š” ํ˜•์‹์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์œผ๋กœ ์ถ”์ธกํ•œ๋‹ค. 

 

ํ•™์Šต์ƒํƒœ ํŠน์„ฑ์ƒ ๊ต‰์žฅํžˆ ์ž์ฃผ ์—…๋ฐ์ดํŠธ ๋˜๋Š”๋ฐ, ์œ„ ํ…Œ์ด๋ธ”์— ๋ณด์ด๋Š” data(Hex)๊ฐ€ ์ˆ˜์ • ๋  ๋•Œ ๋งˆ๋‹ค dead tuple์ด ๊ณ„์† ์Œ“์ด๊ฒŒ ๋˜์–ด ์ˆ˜๋™์œผ๋กœ vaccum์„ ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด ์ ์  ์„ฑ๋Šฅ์ด ๋Š๋ ค์ง€๋Š” ์ด์Šˆ๊ฐ€ ์žˆ์—ˆ๋‹ค. ๐Ÿ’ฃ ์œ„์—๋„ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ Dead Tuple์ด ์Œ“์ด๋ฉด ๋ถˆํ•„์š”ํ•œ page๋ฅผ ์—„์ฒญ๋‚˜๊ฒŒ ์ฝ์–ด Disk I/O๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š”๊ฑด ๋ฌผ๋ก  ์‹คํ–‰๊ณ„ํš์ด ๋ฐ”๋€Œ์–ด ์ธ๋ฑ์Šค ์ž์ฒด๋ฅผ ์•ˆํƒ€๊ฒŒ ๋ณ€๊ฒฝ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๋ฌธ์ œํ•ด๊ฒฐ์€ ๊ฐ„๋‹จํ–ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์„ ํ†ตํ•ด oid ์™€ ๋งํฌ๋ฅผ ํ•ด์ œํ•ด์ฃผ๋ฉด auto-vaccum์ด ๋™์ž‘ํ•œ๋‹ค.

SELECT lo_unlink($oid๊ฐ’)

 

๋‹คํ–‰ํžˆ ์ด๋Š” ์•Œ๋ ค์ง„ ์ด์Šˆ๋ผ์„œ, Postgre github์— ์ด๋ฏธ ๋งŒ๋“ค์–ด๋‘” VaccumIO๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค. ์ด๋Š” ๋ชจ๋“  ํ…Œ์ด๋ธ”์— oid์™€ pg_largeobject์˜ oid๋ฅผ ๋น„๊ตํ•˜์—ฌ ์ง€์›Œ์ง„ oid๋ฅผ unlink ํ•˜๋„๋ก ๋™์ž‘ํ•œ๋‹ค.

 

๋‹ค๋งŒ ์ฃผ์˜ํ•ด์•ผํ•  ๊ฒƒ์€ lo_unlink ์ž์ฒด์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฌด๊ฒ๊ณ , lock์„ ๊ฑธ๊ธฐ์— ์šด์˜์ค‘์—๋Š” ์กฐ์‹ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ํ…Œ์ŠคํŠธํ•ด๋ณด๋‹ˆ ์•„์˜ˆ ์„œ๋น„์Šค๋ฅผ ์ค‘์ง€ํ•ด์•ผํ•  ์ •๋„๋Š” ์•„๋‹ˆ๋ผ์„œ ์ƒˆ๋ฒฝ ์‹œ๊ฐ„๋Œ€ ๋ฐฐ์น˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด VaccumIO๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•ด์„œ ํ•ด๊ฒฐํ–ˆ์—ˆ๋‹ค.

์•„๋ž˜ ๋‘ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋„์ปค ์ด๋ฏธ์ง€์— ๋ง์•„์„œ `docker run` ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด ์ƒˆ๋ฒฝ๋งˆ๋‹ค vaccumIo๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.

# vacuumioscript.sh

#!/bin/bash
echo "*:*:*:*:$DB_PW" > ~/.pgpass
chmod 600 ~/.pgpass
vacuumlo -h ${DB_URL} -p 5432 -U postgres -w ${DRY_RUN} -v lms -l ${LIMIT}
FROM postgres:14.3-alpine

ENV DB_URL=...
ENV DB_PW=...
ENV DRY_RUN="--dry-run" # vaccumlo --dry-run ์„ํ†ตํ•ด ํ˜„์žฌ DB๊ฐ€ large object๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธ๊ฐ€๋Šฅ
ENV LIMIT=500

COPY vacuumioscript.sh vacuumioscript.sh
RUN chmod 775 vacuumioscript.sh

ENTRYPOINT ["./vacuumioscript.sh"]

 

 

๊ทธ ๋‹น์‹œ์—๋Š” ๋ณ„ ์ƒ๊ฐ์—†์ด ํฐ๋ฐ์ดํ„ฐ? ๊ทธ๋Ÿผ LOB์— ์ €์žฅํ•˜๋ฉด ๋˜๊ฒ ์ง€ํ•˜๊ณ  ์„ ํƒํ–ˆ๊ณ  vaccum ๋™์ž‘์— ๋Œ€ํ•ด์„œ๋„ ๋ฌด์ง€ํ–ˆ๋Š”๋ฐ

 

์ดํ›„ ๋” ์ฐพ์•„๋ณด๋‹ˆ LargeObject(oid)๊ฐ€ ์•„๋‹Œ bytea ๋กœ ๋ฐ”๋กœ ์ €์žฅํ•˜๋ฉด auto-vaccum์ด ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋จ์„ ํ™•์ธํ•˜๊ณ  ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•ด์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค. ๋ฌผ๋ก  ์ผ๋ฐ˜์ ์ธ ํ…Œ์ด๋ธ”์— lob -> bytea ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด์„œ ์กฐํšŒ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•ด๋‹น ํ…Œ์ด๋ธ”์€ stateContext ์˜ ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜์–ด์žˆ๊ธฐ๋„ ํ•˜๊ณ  ์‚ฌ์šฉ์ž 1๋ช…์ด ๊ณ ์œ ํ•œ ID๋กœ ์ž์‹ ์˜ ๋ฐ์ดํ„ฐ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ๋ผ ๋ณ„ ๋ฌธ์ œ ์—†์—ˆ๋‹ค.

@Entity
@Table(name = "jiwon_state_machine")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
class LmsStateMachineEntity : RepositoryStateMachine() {

  @Id
  @Column(name = "machine_id")
  private var machineId: String? = null

  @Column(name = "state")
  private var state: String? = null

  // @Lob ์ œ๊ฑฐ, bytea ํƒ€์ž…์œผ๋กœ ๋ฐ”๋กœ ์ €์žฅ
  @Column(name = "state_machine_context", length = 10240)
  private var stateMachineContext: ByteArray? = null
}
create table jiwon_state_machine (
     machine_id varchar(255) not null,
     state varchar(255),
     state_machine_context bytea,
     primary key (machine_id)
);

 

 

๐Ÿ€ ๋‹ค๋ฅธ ์‚ฌ๋ก€

์—ฌ๋‹ด์œผ๋กœ Postgre๋ฅผ ๋”ฅํ•˜๊ฒŒ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ํ•œ๋ฒˆ์”ฉ ๊ฒช๋Š” ๋ฌธ์ œ๊ฐ€ Vaccum ์ด์Šˆ์ธ๋ฐ, ๋‚ด๊ฐ€ ๊ฒช์€ @Lob๊ณผ ๊ฐ™์€ ํŠน์ˆ˜ํ•œ ์ƒํ™ฉ์ด ์•„๋‹ˆ๋”๋ผ๋„ ๋ฐ์ดํ„ฐ๋Ÿ‰์ด ๋งŽ์•„์ง€๋ฉด auto-vaccum์ด ์ž˜ ๋˜์ง€์•Š์•„ Dead Tuple๋กœ ์ธํ•ด ๋น„์Šทํ•œ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ 29CM Auto-vaccum ์žฅ์•  ๋Œ€์‘๊ธฐ๋„ ๊ผญ ํ•œ๋ฒˆ ์ฝ์–ด๋ณด๊ธฐ๋ฅผ ์ถ”์ฒœํ•œ๋‹ค. 

 

PostgreSQL Autovacuum ์žฅ์•  ๋Œ€์‘๊ธฐ (1)

29CM์—์„œ๋Š” Amazon RDS for PostgreSQL๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ๊ทผ์— ๊ฒฝํ—˜ํ•œ PostgreSQL Autovacuum ์žฅ์• ์™€ Vaccum ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

medium.com

 

 

 

 

๐Ÿ“š ๋ ˆํผ๋Ÿฐ์Šค

ํ•œ๋ˆˆ์— ์‚ดํŽด๋ณด๋Š” PostgreSQL - https://d2.naver.com/helloworld/227936

 

PostgreSQL Vaccum์— ๋Œ€ํ•œ ๊ฑฐ์˜ ๋ชจ๋“  ๊ฒƒ https://techblog.woowahan.com/9478/

 

AWS Article 1ํŽธ- https://repost.aws/ko/articles/ARbMXOvsOvTeCuiuoxSZxuwA/amazon-aurora-postgre-sql-auto-vacuum-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-2

 

AWS Artice 2ํŽธ - https://repost.aws/ko/articles/ARdulMK-V2QJueMZ5SmKnk8Q/amazon-aurora-postgre-sql-auto-vacuum-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2-2

 

Postgre13 Docs - https://postgresql.kr/docs/13/routine-vacuuming.html

 

Vaccum์„ ์‹คํ–‰ํ•ด์•ผํ•˜๋Š” ์ด์œ , ์„ฑ๋Šฅํ–ฅ์ƒ - https://blog.gaerae.com/2015/09/postgresql-vacuum-fsm.html

 

Postgre Wiki - ๊ฐœ๋ฐœ์ฒ ํ•™ https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

'๐ŸŒฑBackend > DB(MySQL,PostgreSQL)' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

์ •๋ฆฌ์ค‘-6  (0) 2021.10.27
์ •๋ฆฌ์ค‘-5  (0) 2021.10.27
์ •๋ฆฌ์ค‘ - 4  (0) 2021.10.20
์ •๋ฆฌ์ค‘ - 3  (0) 2021.10.20
์ •๋ฆฌ์ค‘ -2  (0) 2021.10.20

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ