본문 바로가기
Ruby

rails ActiveRecord 메모리, 성능 개선

by yunexus 2022. 12. 30.

공통

  1. DB SQL발행 횟수를 줄이기

 

Select

  1. N+1을 예방하기
    includes, preload, eager_load를 사용해서 쿼리를 캐시하기
    includes : 테이블 별로 SQL로 검색해서 캐시, 조건에 따라 SQL 1개만 발행
    preload : 테이블 별로 SQL로 검색해서 캐시, 관련테이블은 조건 지정 불가능
    eager_load : 관련된 테이블을 left join으로 검색해서 캐시, SQL 1개만 발행
    @user = User.includes(:UserDetail)

  2. 검색시 불필요한 join이나 eagal_load를 줄이기
    단순 Copy & Paste 혹은 코드 수정으로 인해 사용하지 않는 테이블을 지우기

  3. 건수 검색할때는 length를 사용하기
    count : 실행할 때 마다 SQL발행
    size : 실행할 때 마다 SQL발행, length 실행 후에는 메모리에서 load
    length : 2번째 이후 SQL발행안함, 메모리에 cache

  4. 검색해서 반복문 처리할때, 전체 검색이 아닌 일정건수 끊어서 검색하기
    User.find_in_batches(batch_size: 1000) do |user|
    1000건씩 끊어서 검색해서 반복처리

  5. 검색시 select로 Colums 지정하기
    검색결과 : ActiveRecord

  6. 검색시 pluck로 Column 지정하기
    검색결과 : Array<String>, Array<Array<String>>
    pluck에 적은 Column순서대로 정렬됨
    Array<String> → Array<Hash> 로 만들어 이용하기
    레코드가 많고 컬럼이 많은경우에 pluck사용하는 것 만으로도 1GB 이상의 메모리를 줄일 수 있음

     User.all.map(&:name) → User.pluck(:name)

  7. 검색 후 루프 처리하는경우에 ActiveRecord 참조하는 것 만으로도 메모리가 계속 증가하므로
    위 8. 처럼 hash로 만들어서 처리하기

  8. 똑같은 검색을 여러번 하는 경우에는 결과를 메모리화 하기
전
def user
  @user = User.where(id: ids)
end

후
def user
  @user ||= User.where(id: ids)
end

 

INSERT, UPDATE, UPSERT

  1. 처리 속도 순서
    처리에 따라 batch_size, validtion, callback 등 지원하는 기능이 다름.
    1 INSERT SQL직접 실행 : connection.execute sql
    2 insert_all
    3 import
    4 create

  2. INSERT, UPDATE 복수건 묶어서 처리하기
    1만건 처리할때, SQL을 1만건 발행하지 않기(create를 1만건 반복)
    insert_all, update_all, bulk_import를 이용해서 묶어서 처리하기
    https://github.com/zdennis/activerecord-import

  3. activerecord-import이용시, INSERT, UPDATE를 Hash로 하기
    메모리도 줄고, 처리속도도 빨라짐

  4. 처리 건수를 제한하기
    몇만, 몇십만건을 한번에 처리하지 않기
    each_slice로 건수를 나눠서 처리하기
    ※ Postgresql에서 복수건 검색하고, 갱신할때 최대 파라미터는 65535건.
       예 ) model.where(id: ids).update_all(・・・) 할때 ids.length > 65535 인 경우 error

 

 

'Ruby' 카테고리의 다른 글

unicode normalizeのform  (0) 2024.06.10
rsepc mock 메소드 내부 확인  (0) 2023.10.23