Kotlin + Spring Boot
๋ก ์์ฃผ ๊ฐ๋ฐํ๊ฒ ๋๋ฉด์ JPA๋ฅผ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋์์ต๋๋ค.
๋ง์ ์ฅ์ ์ ๊ฐ์ง๊ณ ์๋ JPA์ด์ง๋ง ๋น์ฐํ ๋จ์ ๋ ์กด์ฌํฉ๋๋ค. ๋จ์ ์ค์์๋ ์ ๊ฐ ์ ์ผ ๊ทนํํ๋ ๋จ์ ์ ์ธ๋ฐ์์ด ์ฟผ๋ฆฌ๋ฅผ ๋ง์ด ๋ ๋ฆฌ๋ ๋ฌธ์ ์
๋๋ค.
JPA
๋ฅผ ์ด์ฉํ์ฌ 1000๊ฐ์ ๋ฐ์ดํฐ๋ฅผ PostgreSQL
์ insertํ๋ ํ
์คํธ๋ฅผ ์งํํ์์ต๋๋ค.
1000๊ฐ์ ๋ฐ์ดํฐ๋ฅผ insert ํด๋ณธ ๊ฒฐ๊ณผ ์ด๋ง์ด๋งํ๊ฒ ๋๋ฆฐ ์๋๊ฐ ๋์์ต๋๋ค.
๋ฌด๋ ค 40์ด... ๋ผ๋ ์๊ฐ์ด ๊ฑธ๋ ธ์ต๋๋ค.
์ฐ๋ฆฌ ๊ฐ์ด ์ด ์๋๋ฅผ ๋จ์ถ ์์ผ๋ด ์๋ค.
application.yaml ํ์ผ์
spring:
jpa:
properties:
jakarta:
persistence:
sharedCache:
mode: UNSPECIFIED
hibernate:
jdbc:
order_inserts: true
batch_size: 1000
์์ฒ๋ผ `hibernate.order_inserts=true`์ `hibernate.batch_size=1000`์ด๋ผ๊ณ ๋ฃ์ด์ฃผ๋ฉด 1000๊ฐ์ฉ ๋ฌถ์ด์ insert๋ฅผ ์์ผ์ค๋๋ค. ๋จ DB์ autoincrement id ์์ด์ผ batch insert๋ฅผ ์์ผ์ค ์ ์์ต๋๋ค. id๊ฐ autoincrement๋ผ๋ฉด ๋ค์ id๊ฐ์ ์์๋ด๊ธฐ ์ํด JPA๋ insertํ๊ธฐ ์ ์ ๋ง์ง๋ง ์์ด๋๋ฅผ select ํ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๊ฒ ๋์ด batch insert๋ฅผ ํ ์ ์๋ ์ํ๊ฐ ๋ฉ๋๋ค.
์ ์์ฒ๋ผ ์ค์ ์ ์๋ฃํ๋ฉด ์ผ๋ง๋ ๋จ์ถ์ด ๋์์๊น์? ์ง๊ธ ๋ฐ๋ก ํ์ธํด๋ณด์์ฃ .
20์ด ์ ๋ ๊ฑธ๋ฆฝ๋๋ค. ๊ธฐ์กด ๋๋น 20์ด ์ ๋ ๊ฐ์ ๋์์ง๋ง ๋ง์กฑํ์ง ๋ชปํ๊ฒ ๋ค์.
์ฐ์ 20์ด๊ฐ ์ ๋๊ฐ ๊ฑธ๋ฆฌ๋ ์ด์ ๋ฅผ ์์์ผ ๋ฉ๋๋ค. JPA ๋ด์ฅํจ์์ธ saveAll์ ํ๊ฒ ๋๋ฉด select๋ฌธ์ด 1000๊ฐ ๋ฐ์์ด ๋๊ณ ๊ทธ๋ค์ insert๋ฅผ ์์ผ์ฃผ๋๊ฑธ ํ์ธ ํ ์ ์์ต๋๋ค. ์ ๊ทธ๋ฐ์ง ์ด์ ๋ฅผ ์๊ธฐ ์ํด JPA ๋ด์ฅํจ์์ ์๋ saveAll ํจ์๋ฅผ ํ์ธํด๋ณด๋ insertํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ก์ด ๋ฐ์ดํฐ์ธ์ง ํ์ธํ๊ณ ์๋ก์ด ๋ฐ์ดํฐ๋ผ๋ฉด ๊ทธ๋ฅ insert๋ฅผ ์์ผ์ฃผ๊ณ ์๋๋ผ๋ฉด ํ์ธ ํ ์ ๋ฐ์ดํธ ํด์ฃผ๋ ๊ธฐ๋ฅ์ด ํฌํจ๋์ด ์์์ต๋๋ค. ๊ทธ๋์ insert์ update๋ฅผ ๊ฐ์ saveํจ์๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค๋ ์ฌ์ค์ ์๊ฒ ๋ฉ๋๋ค.
์ด๊ฑธ ํด๊ฒฐํ๊ธฐ ์ํด์๋ Entity ํ์ผ์ ์์ ํ์ฌ์ผ ํฉ๋๋ค.
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DynamicUpdate
@Table(name = "test_table")
data class TestEntity(
@Id
@Column(name = "key")
var key: UUID? = null,
@Column(name = "first_name")
var firstName: String? = null,
@Column(name = "last_name")
var lastName: String? = null,
@Column(name = "email")
var email: String? = null,
@Column(name = "phone")
var phone: String? = null,
)
์ด ์ฝ๋๋ ์ฐ๋ฆฌ๊ฐ ํํ ๋ณด๋ Entity ํ์ผ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ฌ๊ธฐ์ insertํ๋ ๋ฐ์ดํฐ๊ฐ ํญ์ ์๋ก์ด ๋ฐ์ดํฐ๋ผ๊ณ ์ธ์์ ์์ผ์ฃผ๋ ์ฝ๋๋ฅผ ๋ฃ์ด์ฃผ์ด์ผ ํฉ๋๋ค.
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DynamicUpdate
@Table(name = "test_table")
data class TestEntity(
@Id
@Column(name = "key")
var key: UUID? = null,
@Column(name = "first_name")
var firstName: String? = null,
@Column(name = "last_name")
var lastName: String? = null,
@Column(name = "email")
var email: String? = null,
@Column(name = "phone")
var phone: String? = null,
): Persistable<UUID> {
override fun isNew(): Boolean {
return true
}
override fun getId(): UUID? {
return this.id
}
}
TestEntity ํ์ผ์ ์ ์ฝ๋์ฒ๋ผ ์์ ์ ํ์ฌ ํญ์ ์๋ก์ด ๋ฐ์ดํฐ๋ผ๊ณ ์ธ์์ ์์ผ์ฃผ๊ฒ ๋ฉ๋๋ค.
๐จ ๋จ ์ฃผ์ํ์ค ์ ์ ์ด๋ ๊ฒ ํ๋ฉด Save ๋๋ SaveAll ํจ์๋ก ์ ๋ฐ์ดํธ๋ฅผ ํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ํญ์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ Entityํ์ผ์๋ง ์ ์ฉํ์ฌ์ผ ํฉ๋๋ค.
์ ๊ทธ๋ผ ์ผ๋ง๋ ๋จ์ถ์ด ๋์๋ ํ์ธํด๋ด
์๋ค.
2๊ฐ์ ๋ฐฉ๋ฒ์ ์ ์ฉํด๋ณด๋ 1.6์ด ์ ๋ ๊ฑธ๋ฆฌ๋๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.๐