DevLog ๐ถ
[JPA] @BatchSize๋ฅผ ์ง์ ํ์ผ๋ ์ฟผ๋ฆฌ๊ฐ ์ด์ํ๊ฒ ๋๊ฐ ๋ ๋ณธ๋ฌธ
[JPA] @BatchSize๋ฅผ ์ง์ ํ์ผ๋ ์ฟผ๋ฆฌ๊ฐ ์ด์ํ๊ฒ ๋๊ฐ ๋
dolmeng2 2022. 10. 22. 03:43- ์ง๋ 9์์, ํ์ฌ์์ ์ฌ์ด๋ ํ๋ก์ ํธ๋ก JPA๋ฅผ ํ์ฉํ ๊ฒ์ํ ์๋น์ค ๊ฐ๋ฐ์ ์งํํ์๋๋ฐ, ์ฟผ๋ฆฌ ํ๋์ ์งํํ๋ค๊ฐ ๋ด ๋ง์๋๋ก ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ์ง ์๋ ๊ฑธ ๋ณผ ์ ์์๋ค.
- ๋น์ ๋ชจ๋ธ์ ๊ตฌ์กฐ๋ ๋๋ต์ ์ผ๋ก ์ด๋ ๋ค. ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ํ ์ํฐํฐ์ด๋ค.
@Table(name = "tb_board")
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board extends BaseEntity {
@Schema(description = "๊ฒ์๊ธ ๋ฒํธ", required = true)
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long boardNo;
@Schema(description = "๊ฒ์๊ธ์ ๋ํ ๋๊ธ ๋ฆฌ์คํธ", required = false)
@BatchSize(size = 100)
@OneToMany(mappedBy = "board", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Comment> commentList = new ArrayList<>();
@Schema(description = "๊ฒ์๊ธ ํ๊ทธ", required = false)
@BatchSize(size = 100)
@OneToMany(mappedBy = "board", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<BoardTag> boardTagList = new ArrayList<>();
@Schema(description = "๊ฒ์๊ธ ์ด๋ชจ์ง", required = false)
@BatchSize(size = 100)
@OneToMany(mappedBy = "board", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Emoji> emojiList = new ArrayList<>();
@Schema(description = "๊ฒ์๊ธ ํ์ผ", required = false)
@BatchSize(size = 100)
@OneToMany(mappedBy = "board", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<File> fileList = new ArrayList<>();
}
- ์ด ์ธ์๋ ์ฌ๋ฌ ํ๋๊ฐ ์์์ง๋ง, ๋์ถฉ ํ์ํ ํ๋๋ง ์์ฑํด๋์๋ฉด ์ด๋ ๋ค.
- ์ฌ๊ธฐ์ Comment, BoardTag, Emoji, File์ Board๋ฅผ ์ฐ๊ด์ํฌ ๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํด๋์๋ค.
@Schema(description = "๊ฒ์๊ธ ์ํฐํฐ", required = false)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_no")
private Board board;
- JPA ๊ฐ์๋ฅผ ์๊ฐํ๋ฉด์, ์์์น ๋ชปํ ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ์ง ์๋๋ก ํ๊ธฐ ์ํด ์ฌ๋งํ๋ฉด fetch ์ ๋ต์ LAZY๋ก ์ค์ ํด์ผ ๋๋ค๋ ๊ฑธ ์ ๋ง ์๋ ์์ด ๋ค์๊ธฐ ๋๋ฌธ์, ๋น์ฐํ๊ฒ๋ Lazy๋ก ๋ก๋ฉํ๋๋ก ์ค์ ํ์๋ค.
- ๋์ , ์ํฐํฐ ์ ๊ทผ ์ ๊ฐ๊ฐ ์ฟผ๋ฆฌ๊ฐ ๋ ๋ผ๊ฐ๋ ๊ฑธ ๋ฐฉ์งํ๊ธฐ ์ํด, ๋ฐฐ์น ์ฌ์ด์ฆ๋งํผ ํ ๋ฒ์ ๊ฐ์ ธ์ค๊ฒ ํ๊ธฐ ์ํด์ @BatchSize์ ์ฌ์ฉํ์๋ค.
- ์ด๋ ๊ฒ ๋๋ฉด in์ ์ ํตํด 100๊ฐ๋ฅผ ๋ฌถ์ด์ ๊ฐ์ ธ์ฌ ๊ฒ์ด๋ผ๊ณ ์์ํ์๋ค.
๊ทธ๋ฐ๋ฐ, ๋ง์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค๋ณด๋ ๋ค์๊ณผ ๊ฐ์ ์ํฉ์ด ๋ฐ์ํ์๋ค.
- ๋์ถฉ ์ด๋ฐ ์์ผ๋ก 100๊ฐ๊ฐ ์๋๋ผ ๋ณธ์ธ ๋ฉ๋๋ก ๋๊ฐ๋ ์ํฉ์ธ ๊ฒ์ด๋ค.
- ์ ์ธ์ด๋ณด๋ฉด 12๊ฐ, 8๊ฐ์ฉ ๋๊ฐ ๊ฒ์ ํ์ธํ ์ ์๋ค.
- ์ด๊ฑฐ์ ๋ํด์ @Batchsize๊ฐ ์ ์ฉ๋์ง ์๋ ํน์ํ ์ํฉ์ด ์๋ ๊ฑด๊ฐ ์ถ์ด์ ๊ณ ๋ฏผ์ ์์ฒญ ํ๋ค๊ฐ ๋๋ผ์ด ๊ธ์ ๋ฐ๊ฒฌํ๋ค.
- ๋ณดํต์ RDB๋ค์ select * from x where in (?) ์ ๊ฐ์ preparedstatement๋ ๋ฏธ๋ฆฌ ๋ฌธ๋ฒ์ ํ์ฑํด์ ์ต๋ํ ์บ์ฑ์ ํด๋๋ค.
- ์ด๋, ๋ฐ์ดํฐ๊ฐ ๋ด๊ฐ @BatchSize=100์ผ๋ก ์ค์ ์ ํด๋์๋ค๋ฉด 1~100๊น์ง ๋ชจ๋ ๊ฒฝ์ฐ์ preparedstatement๋ฅผ ๋ง๋ค์ด๋๋ค.
select * from x where in (?)
select * from x where in (?, ?)
select * from x where in (?, ?, ?)
select * from x where in (?, ?, ? ...)
- ํ์ง๋ง, ์ด๋ ๊ฒ ๋๋ฉด DB ์ ์ฅ์์ ๋๋ฌด ๋ง์ preparedstatement ์ฟผ๋ฆฌ๋ฅผ ์บ์ฑํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ด ๋จ์ด์ง๋ค.
- ๊ทธ๋์! ํ์ด๋ฒ๋ค์ดํธ๋ ๋ด๋ถ์์ ์ต์ ํ๋ฅผ ์งํํ๊ธฐ ์ํด 1~10๊ฐ๋ ๊ธฐ๋ณธ์ผ๋ก ๋ง๋ค๊ณ , ์ค์ ๊ฐ์์ 2๋ก ๋๋์ด๊ฐ๋ฉฐ ์ก์๋๋ค. (100 > 50 > 25 > 12...)
- ์ด๋ฌ๋ฉด ๊ธฐ์กด์๋ 100๊ฐ๋ฅผ ๋ง๋ค์์ด์ผ ํ์ง๋ง, ์ต์ ํ๋ฅผ ํตํด 1~10, 12, 25, 50, 100 ==> ์ด 14๊ฐ๋ง ๋ง๋ค์ด๋๋ฉด ๋๋ค.
- ๊ทธ๋์ ๋ง์ฝ 20๊ฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด, 12๊ฐ์๋ค๊ฐ 8๊ฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ํฉ์ด ๋ฐ์ํ๋ ๊ฒ์ด๋ค.
-> ์ค๋น๋ ๊ฐ (1~10 /12 / 25/ 50 / 100) ์ค์์ ๊ฐ์ฅ ์ต๋์น๋ก ๋์ด์ฌ ์ ์์๋งํผ ๋์ด์ค๊ณ , ๋๋จธ์ง๋ฅผ ๋์ด์ค๋ ๊ฒ!
- ํ์ง๋ง, ์ด๋ฐ ๊ฒ ์ซ๋ค๋ฉด application.yml์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฉํด์ฃผ๋ฉด ๋๋ค.
- ๋ฐ๋ก, ์ต์ ํ ์ต์ ์ ๋๋ ๊ฒ! (jpa.properties.hibernate.batch_fetch_style: dynamic)
- ๊ธฐ๋ณธ ์ค์ ์ legacy์ง๋ง, dynamic์ผ๋ก ์ค์ ํ๋ฉด ์ต์ ํ ์ต์ ์ ๋๊ฒ ๋๋ค!
- ๊ทธ๋๋ ์ฌ๋งํ๋ฉด ์ด ์ค์ ์ ์ ๊ฑด๋๋ ๊ฒ ์ข์ ๊ฒ ๊ฐ๋ค...!