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๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ํŠน์ˆ˜ํ•œ ์ƒํ™ฉ์ด ์žˆ๋Š” ๊ฑด๊ฐ€ ์‹ถ์–ด์„œ ๊ณ ๋ฏผ์„ ์—„์ฒญ ํ•˜๋‹ค๊ฐ€ ๋†€๋ผ์šด ๊ธ€์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

 

default_batch_fetch_size ๊ด€๋ จ์งˆ๋ฌธ - ์ธํ”„๋Ÿฐ | ์งˆ๋ฌธ & ๋‹ต๋ณ€

์•ˆ๋…•ํ•˜์„ธ์š” ์„ ์ƒ๋‹˜ ์ตœ๊ทผ default_batch_fetch_size ๊ด€๋ จ ์งˆ๋ฌธ๊ณผ ๋น„์Šทํ•œ ์ƒํ™ฉ์ด์ง€๋งŒ ์กฐ๊ธˆ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํ˜„์žฌ A ํ…Œ์ด๋ธ”๊ณผ Bํ…Œ์ด๋ธ”์ด one to many ๋กœ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์žˆ๊ณ  ํ˜„์žฌ A ํ…Œ์ด๋ธ” ๊ธฐ์ค€์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฐ๋‹ค์Œ(ํ…Œ

www.inflearn.com

 

- ๋ณดํ†ต์˜ 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์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ์ตœ์ ํ™” ์˜ต์…˜์„ ๋„๊ฒŒ ๋œ๋‹ค!

- ๊ทธ๋ž˜๋„ ์›ฌ๋งŒํ•˜๋ฉด ์ด ์„ค์ •์€ ์•ˆ ๊ฑด๋“œ๋Š” ๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค...!

Comments