모든 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 |