본문 바로가기

Ruby On Rails/Model(ORM)

find_in_batches vs each_slice

모든 ids값을 가지고 오면 쿼리 오류가 발생할 수 있다. 그 이유에 대해서는

https://dexlee.tistory.com/109?category=1031550

여기에 에러 메시지와 함께 설명을 해놓았다.

 

그래서 이런 경우, 배치 함수를 사용해서 데이터를 가져와야 속도도 빠르고 안전하다.

 

1. find_in_batches(), in_batches()

두 함수의 약간의 차이점에 대해서는 다루지 않고 공통점에 대해서 다루고, 문제점을 정의하겠다.

이 두 함수는 실무에서 사용이 제한적이어야만 한다. 왜냐하면 모든 ids값을 가지고 limit을 사용해 데이터를 자른다.  

 

1) 예시

BATCH_SIZE = 4
ids = (1..10).to_a
sheets = []
Sheet.where(id: ids).find_in_batches(batch_size: BATCH_SIZE) do |group|
  aa += group
end

ids.size = 10, batch_size = 4라고 가정하고 코드를 실행해보면,

Sheet Load (18.2ms)  SELECT `sheet`.* FROM `sheet` WHERE `sheet`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) ORDER BY `sheet`.`id` ASC LIMIT 4
  Sheet Load (28.0ms)  SELECT `sheet`.* FROM `sheet` WHERE `sheet`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `sheet`.`id` > 4 ORDER BY `sheet`.`id` ASC LIMIT 4
  Sheet Load (32.7ms)  SELECT `sheet`.* FROM `sheet` WHERE `sheet`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `sheet`.`id` > 10 ORDER BY `sheet`.`id` ASC LIMIT 4

ids의 size만큼 검색하고 limit으로 데이터를 가져온다. 즉, ids의 크기가 크면 클수록 속도가 엄청나게 느려지고, 안정성도 떨어진다. 이러한 문제점을 해결하기 위해 사용하는 메서드가 있다. each_slice()이다.

 

2. each_slice()

이 함수를 사용해 데이터를 가져오면 모든 ids를 검색하지 않고, batch_size 만큼 ids를 검색해서 데이터를 가져온다. 그래서 속도도 빠르고 안정성도 매우 높다.

 

1) 예시

BATCH_SIZE = 4
ids = (1..10).to_a
sheets = []
ids.each_slice(BATCH_SIZE) { |is| sheets += Sheet.where(id: is) }

ids.size = 10, batch_size = 4라고 가정하고 코드를 실행해보면,

Sheet Load (19.8ms)  SELECT `sheet`.* FROM `sheet` WHERE `sheet`.`id` IN (1, 2, 3, 4)
  Sheet Load (25.5ms)  SELECT `sheet`.* FROM `sheet` WHERE `sheet`.`id` IN (5, 6, 7, 8)
  Sheet Load (47.8ms)  SELECT `sheet`.* FROM `sheet` WHERE `sheet`.`id` IN (9, 10)

이렇게 배치 크기만큼 데이터를 검색해서 리턴해준다. 그래서 안정성도 높고 속도도 빠르게 데이터를 가져올 수 있다.

 

3. 실무에서는

실무에서는 each_slice 방식을 공부한 후부터는 항상 이 방식을 사용해서 데이터를 처리했다. 그 이유는 위에 충분히 설명했다.

 

'Ruby On Rails > Model(ORM)' 카테고리의 다른 글

batches를 사용하는 이유  (0) 2021.12.25
preload vs includes vs eager_load vs joins  (0) 2021.12.24
Model 정리  (0) 2021.12.24