2011-08-12 7 views
1

rails/ruby ​​(레일즈 3 및 루비 1.9.2 사용)를 처음 접했고 불필요한 쿼리를 제거하려고합니다.레일/활성 레코드 .save! 효율성 질문

것은 내가 각각 어떻게 실행 해요 때 :

apples.to_a.each do |apple| 
    new_apple = apple.clone 
    new_apple.save! 
end 

와 나는 SQL 로그를 확인, 나는 하나의 INSERT 문 다음 세 가지 선택 문을 참조하십시오. select 문은 완전히 불필요한 것처럼 보입니다. 예를 들어, 그들은 다음과 같습니다 :

SELECT 과일 *에서 과일 Fruit.ID = 5 LIMIT 1;
색상 선택 *. 색상에서 Color.ID = 6 LIMIT 1;
SELECT TreeType. * from TreeType 여기서 TreeType.ID = 7 LIMIT 1;
사과 (Fruit_id, color_id, treetype_id)에 삽입 (6, 7, 8) 값 "id"를 반환합니다.

겉으로보기에는,이 작업을 수행하는 데는 많은 시간이 걸리지 만, 70k 인서트를 실행하면 각 인서트에 대해 3 가지 선택 항목에 상당한 시간이 걸릴 것입니다.

  • 는 액티브의 전형적인/레일이 .save :

    그래서 나는이 다음 궁금하네요! 메서드를 사용하거나 이전 개발자가 사용자 정의 코드를 추가 했습니까?

  • 각 항목에 대해 실행되는 세 개의 select 문을 사용하면 상당한 시간이 추가 될 수 있습니까?
  • 레일스/액티브 레코드에 내장되어있는 경우보다 효율적으로 실행하려면 쉽게 바이 패스 되겠습니까?

답변

3
당신이 발생하는 그런 일이 같은 뭔가를 저장에 연결을 검증해야

:

유효성을 검사하기 위해
class Apple < ActiveRecord::Base 
    validates :fruit, 
    :presence => true 
end 

의 관계에 있다는 기록을로드 할 수 있어야하며,이에 필요 차례로 각 레코드에 대해 각 유효성 검사마다 개별적으로 발생합니다.

apples.to_a.each do |apple| 
    new_apple = apple.clone 
    new_apple.save(:validate => false) 
end 

더 나은 접근 방식은 당신의 RDBMS가 지원하는 경우 대량 삽입을 수행하여 SQL에 직접 기록을 조작하는 것입니다 즉, 위험 생활처럼 느낀다면 당신은 검증하지 않고 절약 할 수 save!

의 표준 동작입니다 . 예를 들어, MySQL은 한 번의 INSERT 호출로 수천 개의 행을 삽입 할 수 있습니다. 일반적으로 Apple.connection 액세스 레이어를 사용하여 임의의 SQL 호출을 허용하는 액세스 레이어를 만들 수 있습니다. execute

0

나는 before_save EDIT : (또는 위에 제안 된대로 유효성 검사) 메소드가 있다는 것을 알고 있습니다. 과일의 색깔과 유형을 찾고 과일이 저장 될 때 나머지 속성과 함께 저장하는 것입니다.이 경우에는이 조회가 필요합니다 ...

일반적으로 나는 액티브 레코드를 기대하지 않습니다. 불필요한 조회 - 비록 그것이 항상 효율적임을 의미하지는 않지만 ...

+0

공정하게 말하자면, ActiveRecord는 때로는 수행한다고해도 무엇을 말합니까? 네가하는 말을 깨닫지 못한다. – tadman