2013-08-28 2 views
16

에 루비에서 첫 공연 대 걸릴 : (매개 변수가 제공되는 경우 또는 첫 번째 N 레코드)이는 액티브 쿼리 방법에 관한 질문입니다 레일

  • first가 첫 번째 레코드를 찾습니다. 주문이 정의되지 않으면 기본 키로 주문합니다.
  • take 묵시적 순서없이 레코드 (또는 매개 변수가 제공된 경우 N 레코드)를 제공합니다. 순서는 데이터베이스 구현에 따라 다릅니다. 주문이 제공되면이를 존중할 것입니다.

usecase : 고유 한 속성을 기반으로 데이터베이스에서 레코드를 검색합니다. 여기

User.where(email: '[email protected]') 

, first

SELECT "users".* FROM "users" WHERE "users"."email" = '[email protected]' ORDER BY "users"."id"` ASC LIMIT 1 

take

SELECT "users".* FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1 

그래서 first 위에서와 같이 추가 주문 절을 추가

를 생성 생성합니다. takefirst 사이의 성능 차이가 있는지 궁금합니다.

takefirst보다 빠르거나 그 반대입니까?

+0

주문이 필요합니까? – apneadiving

+0

아니요, 성능에 대해 더 신경이 쓰였습니다. 그러나 둘 다 성능이 동일하다면, 나는 기억하기 쉽기 때문에 주문이 필요한 곳이나 없을 수도있는 곳 어디에서나 .first를 사용할 것입니다. 그 이유는이 질문 – CuriousMind

+0

Take는 order 절을 포함하고 있지 않기 때문에 더 빠를 것입니다. 그러나 그 차이는 무시할 수 있다고 가정합니다. 찾아내는 한 가지 방법은 벤치 마크입니다. –

답변

25

일반적으로 데이터베이스는 조건을 충족하는 모든 행을 식별하고이를 정렬하여 최저 정렬 행을 찾을 필요가 없기 때문에 더 빠릅니다. "take"를 사용하면 데이터베이스가 단일 행을 찾자 마자 바로 중지 할 수 있습니다.

정도

는보다 빠르고 것은에 따라 달라질 것입니다하기 :

  1. 얼마나 많은 시간을 둘 이상의 행에 대해보고 할 필요가 없습니다에 저장됩니다. 최악의 경우는 큰 테이블의 전체 스캔이 필요한 곳이지만 일치하는 행은 스캔 초기에 발견됩니다. "take"는 스캔이 중지되도록합니다.

  2. 가장 낮은 ID를 가진 행을 찾으려면 여러 행을 정렬해야합니다. 최악의 경우는 테이블의 모든 행이 기준과 일치하고 정렬에 포함되어야하는 경우입니다.

고려해야 할 몇 가지 다른 요인이있다 - 예를 들어 대한은 "첫 번째"옵티마이는 기본 키 인덱스의 스캔을 통해 테이블에 액세스 할 수 있습니다 쿼리가 일치하는지 확인하기 위해 각 행을 확인 조건. 그럴 가능성이 매우 높다면 쿼리 최적화 프로그램이 충분히 정교하면 데이터의 완전한 스캔과 정렬을 피할 수 있습니다.

일치하는 레코드와 인덱스 기반 액세스가 거의없는 곳에서는 많은 경우에 그 차이가 사소한 것입니다 (예제에서 "전자 메일"에 고유 한 인덱스가있는 경우). 그러나, 나는 여전히 "take"를 우선적으로 선호합니다.

편집 : 그것은 당신의 예제에서 당신은뿐만 아니라 사용할 수있는, 주제에서 벗어난 약간 비록 난 그냥, 추가 할 것입니다 :

User.find_by(email: '[email protected]') 

생성 된 쿼리가 걸릴 경우와 동일해야하지만, 의미론은 좀 더 분명하다고 생각합니다.