Rails의 Map vs Pluck

사승준·2022년 3월 5일
2
post-thumbnail

Active Record 모델에서 특정 컬럼의 데이터만 가져오는 방법으로 pluck과 map을 사용한다. 두 개의 메서드를 비교하고 어떤 상황에서 써야 하는지 알아보도록 한다.

User.pluck(:name)
  # => (0.1ms) SELECT "users"."name" FROM "users"
User.all.map(&:name)
  # => User Load (0.1ms) SELECT "users".* FROM "users" 

결과를 보니 메서드를 실행할 때 쿼리가 다르다. pluck은 필요한 컬럼에 대해서만 데이터를 조회하지만, map의 경우에는 전체 데이터를 조회한다.

map은 db 쿼리 결과를 Active Record 객체로 만들어 배열에 전부 로드한 후 반복해서 특정 컬럼의 값을 반환한다. 하지만 pluck의 경우에는 Active Record 객체를 생성하지 않고 값을 반환한다. pluck을 사용하면 메서드 체인을 끊기 때문에 pluck 뒤에 Active Record 메서드 체인을 사용할 수가 없다. pluck과 같이 필요한 컬럼에 대해서만 쿼리를 날리지만 Active Record 객체를 원한다면 select를 사용한다.

결국 map의 경우 쿼리 결과를 Active Record 객체로 만들어야 하고 필요하지 않은 컬럼의 데이터까지 로드하기 때문에 메모리 낭비와 속도가 느리다.

map이 무조건 빠른가?

앞에 설명만 들었을 때 pluck이 무조건 빠르다는 생각이 들겠지만. 예외의 경우가 있다. 인스턴스화 된 객체에서 반복처리 하는 경우다. 이 경우 pluck을 사용하면 아래 사진과 같이 n+1 쿼리가 나가기 때문에 map을 사용하는 게 좋다.(개인적으로 인스턴스화 된 객체에서 반복문 안에 pluck을 사용하는 경우가 많지는 않을 것 같아서 일반적으로는 pluck을 사용하는 게 좋아 보인다.)

users = User.all
200.times { users.pluck(:name) }
200.times { users.map(&:name) }

rails5 이후부터는 레코드가 메모리에 로드되어있으면 pluck 쿼리의 중복 실행을 방지하도록 되어있는 것 같다. (링크)

요약

  • 특정 컬럼의 데이터만 가져오는 방법으로는 pluck을 사용하는 게 메모리나 속도 면에서 유리하다.

참고 링크

profile
Ruby on Rails 개발하고 있는 서버 개발자입니다.

0개의 댓글