문제

이것은 "이 방법으로 일하는 이유"라는 질문에 더 가깝습니다.

그래서 당신이 사용할 것임을 알고있는 관련 기록을 뽑는 것에 대한 복음은 사용하는 것입니다. :include 가입을 받고 추가 쿼리를 피하기 때문입니다.

Post.all(:include => :comments)

그러나 로그를 보면 조인이 일어나지 않습니다.

Post Load (3.7ms)   SELECT * FROM "posts"
Comment Load (0.2ms)   SELECT "comments.*" FROM "comments" 
                       WHERE ("comments".post_id IN (1,2,3,4)) 
                       ORDER BY created_at asc) 

그것 ~이다 바로 가기를 가져 가면 모든 주석을 한 번에 가져 오지만 여전히 결합되지는 않습니다 (모든 문서가 말하는 것). 가입 할 수있는 유일한 방법은 사용하는 것입니다. :joins 대신에 :include:

Post.all(:joins => :comments)

그리고 로그 쇼 :

Post Load (6.0ms)  SELECT "posts".* FROM "posts" 
                   INNER JOIN "comments" ON "posts".id = "comments".post_id

내가 뭔가를 놓치고 있습니까? 나는 6 개의 연관성이있는 앱이 있고 하나의 화면에 모든 데이터를 표시합니다. 6 명의 개인 대신 하나의 조인 ED 쿼리를 갖는 것이 더 나을 것 같습니다. 성능면에서 개별 쿼리보다는 결합을하는 것이 항상 더 낫지는 않다는 것을 알고 있습니다 (실제로 시간이 지남에 따라 위의 두 개별 쿼리가 조인보다 빠릅니다). 나는 읽고 있었다. 나는보고 놀랐다 :include 광고대로 작동하지 않습니다.

아마도 레일 ~이다 성능 문제를 인식하고 특정 경우를 제외하고 가입하지 않습니까?

도움이 되었습니까?

해결책

그게 보인다 :include Rails 2.1로 기능이 변경되었습니다. 레일은 모든 경우에 조인을 수행하는 데 사용되었지만 성능의 이유로 일부 상황에서 여러 쿼리를 사용하도록 변경되었습니다. 이 블로그 게시물 Fabio Akita는 변경 사항에 대한 좋은 정보를 가지고 있습니다 ( "최적화 된 간절한 로딩"이라는 섹션 참조).

다른 팁

.joins 방금 테이블에 가입하고 대가로 선택한 필드를 가져옵니다. 조인 쿼리 결과에서 연결을 호출하면 데이터베이스 쿼리가 다시 시작됩니다.

:includes 포함 된 연관성을 열망하고 메모리에 추가 할 것입니다. :includes 포함 된 모든 테이블 속성을로드합니다. Query result includ에 연결을 호출하면 쿼리가 해제되지 않습니다.

결합과 포함의 차이점은 포함 명령문을 사용하면 다른 테이블의 모든 속성을 메모리에 메모리에로드하는 훨씬 더 큰 SQL 쿼리가 생성된다는 것입니다.

예를 들어, 주석으로 가득 찬 테이블이 있고 A : joins => 사용자를 사용하여 사용자 정보를 정렬하기 위해 모든 사용자 정보를 가져 오는 경우 다음과 같이 잘 작동하고 다음보다 시간이 걸리지 만 표시하려고합니다. 사용자 이름, 이메일 등과 함께 주석은 다음을 사용하여 정보를 얻으려면 결합을 사용하려면 각 사용자에 대해 별도의 SQL 쿼리를 만들어야하는 반면 사용하는 경우이 정보를 포함시켜야합니다.

좋은 예 : 예 :

http://railscasts.com/episodes/181-include-vs-joins

성능 고려 사항 외에도 기능적 차이도 있습니다. 댓글에 가입하면 주석이있는 게시물 (기본적으로 내부 조인)이있는 게시물을 묻습니다. 의견을 포함시킬 때는 모든 게시물 인 외부 조인을 요구합니다.

나는 최근에 차이점에 대해 더 많이 읽고있었습니다 :joins 그리고 :includes 레일에서. 다음은 내가 이해 한 것에 대한 설명입니다 (예와 함께 :))

이 시나리오를 고려하십시오.

  • 사용자는 has_many 댓글과 댓글이 사용자에게 속합니다.

  • 사용자 모델에는 다음 속성이 있습니다 : 이름 (문자열), 나이 (정수). 주석 모델에는 다음 속성이 있습니다. content, user_id. 댓글의 경우 user_id가 null 일 수 있습니다.

조인 :

: 조인은 a 내부 조인 두 테이블 사이. 따라서

Comment.joins(:user)

#=> <ActiveRecord::Relation [#<Comment id: 1, content: "Hi I am Aaditi.This is my first   comment!", user_id: 1, created_at: "2014-11-12 18:29:24", updated_at: "2014-11-12 18:29:24">, 
     #<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,    
     #<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">]>

가져올 것입니다 user_id (댓글 테이블)가 user.id (user table)와 동일한 모든 레코드. 따라서 그렇게한다면

Comment.joins(:user).where("comments.user_id is null")

#=> <ActiveRecord::Relation []>

표시된대로 빈 배열이 표시됩니다.

또한 결합은 메모리에 결합 된 테이블을로드하지 않습니다. 따라서 그렇게한다면

comment_1 = Comment.joins(:user).first

comment_1.user.age
#=>←[1m←[36mUser Load (0.0ms)←[0m  ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1←[0m  [["id", 1]]
#=> 24

보시다시피, comment_1.user.age 백그라운드에서 데이터베이스 쿼리를 다시 시작하여 결과를 얻을 수 있습니다.

포함 :

: 수행 포함 a 왼쪽 외부 조인 두 테이블 사이. 따라서

Comment.includes(:user)

#=><ActiveRecord::Relation [#<Comment id: 1, content: "Hi I am Aaditi.This is my first comment!", user_id: 1, created_at: "2014-11-12 18:29:24", updated_at: "2014-11-12 18:29:24">,
   #<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,
   #<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">,    
   #<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>

결과가 나옵니다 주석 테이블의 모든 레코드와 함께 결합 된 테이블. 따라서 그렇게한다면

Comment.includes(:user).where("comment.user_id is null")
#=> #<ActiveRecord::Relation [#<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>

댓글이 표시된 곳에서 레코드를 가져옵니다.

또한 메모리의 두 테이블을 모두 포함합니다. 따라서 그렇게한다면

comment_1 = Comment.includes(:user).first

comment_1.user.age
#=> 24

알 수 있듯이 주석 _1.user.age는 백그라운드에서 데이터베이스 쿼리를 발사하지 않고 메모리에서 결과를로드합니다.

tl; dr

두 가지 방법으로 대조합니다.

가입 - 조건부 레코드 선택.

포함 - 결과 세트의 각 멤버에 연관성을 사용할 때.

더 긴 버전

결합은 데이터베이스에서 나오는 결과 세트를 필터링하기위한 것입니다. 당신은 그것을 사용하여 테이블에서 작업을 설정합니다. 이것을 세트 이론을 수행하는 WHERE 절로 생각하십시오.

Post.joins(:comments)

와 같다

Post.where('id in (select post_id from comments)')

주석이 둘 이상인 경우 조인이있는 중복 게시물을 다시 얻게됩니다. 그러나 모든 게시물에는 의견이있는 게시물이 될 것입니다. 당신은 이것을 뚜렷하게 수정할 수 있습니다 :

Post.joins(:comments).count
=> 10
Post.joins(:comments).distinct.count
=> 2

계약에서 includes 메소드는 관계를 참조 할 때 추가 데이터베이스 쿼리가 없는지 확인합니다 (따라서 N + 1 쿼리를 만들지 않도록)

Post.includes(:comments).count
=> 4 # includes posts without comments so the count might be higher.

도덕은 사용입니다 joins 조건부 설정 작업 및 사용을 원할 때 includes 컬렉션의 각 멤버와 관계를 사용할 때.

.joins는 데이터베이스 조인으로 작동하며 둘 이상의 테이블에 가입하고 백엔드 (데이터베이스)에서 선택한 데이터를 가져옵니다.

포함 데이터베이스의 왼쪽 조인으로 작동합니다. 그것은 왼쪽의 모든 레코드를로드했으며 오른쪽 모델과 관련이 없습니다. 메모리에 관련된 모든 객체를로드하기 때문에 하중을 간절히 바릅니다. 포함 된 쿼리 결과로 연결을 호출하면 데이터베이스에서 쿼리를 실행하지 않으며 메모리에 이미 데이터를로드 했으므로 메모리에서 데이터를 반환합니다.

'Join' '은 방금 테이블에 가입하는 데 익숙해졌으며 조인 협회에서 연결을 불렀을 때 다시 쿼리를 발사합니다 (많은 쿼리가 발사 될 것입니다).

lets suppose you have tow model, User and Organisation
User has_many organisations
suppose you have 10 organisation for a user 
@records= User.joins(:organisations).where("organisations.user_id = 1")
QUERY will be 
 select * from users INNER JOIN organisations ON organisations.user_id = users.id where organisations.user_id = 1

it will return all records of organisation related to user
and @records.map{|u|u.organisation.name}
it run QUERY like 
select * from organisations where organisations.id = x then time(hwo many organisation you have)

이 경우 총 SQL 수는 11입니다

그러나 '포함'을 사용하면 포함 된 연관성을 열망하고 메모리에 추가하고 (첫 번째로드에 모든 연결을로드) 다시 불 쿼리가 아닙니다.

@records = user.includes (: 조직). 어디서 ( "organisations.user_id = 1")와 같은 포함 된 레코드를 받으면 쿼리가 다음과 같습니다.

select * from users INNER JOIN organisations ON organisations.user_id = users.id where organisations.user_id = 1
and 


 select * from organisations where organisations.id IN(IDS of organisation(1, to 10)) if 10 organisation
and when you run this 

@records.map {| u | u.organisation.name} 쿼리가 해제되지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top