2017-03-14 2 views
0

을 파괴 나는 다음과 같은 관계형 DB가 :낮은 메모리는 작업

class Search 
    has_many :items , dependent: :destroy 
end 
class Item 
    has_many :sub_items , dependent: :destroy 
end 
class SubItem 
end 

항목은 100에서 10,000까지 다양 할 수 있습니다. SumItems는 평균 약 100입니다. 내 기억 낮게 유지하려고

내가 사용하는 다음

클래스 검색

before_destroy :destroy_items_in_batches 
    def destroy_items_in_batches 
    self.try(:items).try(:in_batches, { of: 300 }).try(:destroy_all) 
    end 

클래스 그것은 아직 충분하지

before_destroy :destroy_transactions_in_batches 
    def destroy_transactions_in_batches 
    self.try(:sub_items).try(:in_batches, { of: 100 }).try(:destroy_all) 
    end 

항목, 그래서 쿼리를 select 추가하여로드 된 메모리를 줄이기 때문에 나는 그것을 파괴하고 있습니다. nyway는 데이터베이스에서 제거해야하는 ID입니다.

self.try(:items).try(:select,:id).try(:in_batches, { of: 300 }).try(:destroy_all) 
self.try(:sub_items).try(:select,:id).try(:in_batches, { of: 100 }).try(:destroy_all) 

다른 방법으로 메모리 사용을 제거 할 수 있습니까? (배치 크기를 줄이는 명백한 해결 방법 외에)

답변

1

delete_all으로 바꿀 것을 제안합니다. delete_all은 메모리에로드하거나 전혀 읽지 않고 데이터베이스에서 개체 (레코드)를 직접 삭제합니다.

하나의 경고는 ActiveRecord 콜백이 실행되지 않으므로 필요에 따라 처리해야합니다.

+0

감사합니다. 여기에 제안 된 것처럼 파괴 콜백에 대한 의존성을 구현할 것입니다. –

1

destroy_all을 사용하면 실제로 각 객체를 메모리로 인스턴스화 한 다음 각 항목의 콜백을 실행 한 다음 데이터베이스에서 해당 행 하나만 삭제합니다. 매우 비효율적이다. 마크에 의해 제안

대신,이 순서 delete_all를 사용해야합니다

SubItem.where(conditions).delete_all 
Item.where(conditions).delete_all 
Search.where(conditions).delete_all 

DELETE FROM sub_items WHERE conditions... 같은 SQL 문을 실행합니다. 수백 또는 수천 개의 (잠재적으로) 대신 세 개의 SQL 문. 훨씬 빨라야합니다.

+0

그래, 내가 가질거야. delete_all을 관련 외래 키 입력과 함께 사용했다 : 나는 최근에 레일스에 너무 집착하는 것이 나쁘다는 것을 이해하기 시작했고 플립 (flips)을하는 대신 네이티브/세미 - 네이티브 SQL/HTML/JS를 구현해야한다. 방법" –