이것은 "나는 이걸하는 법을 모르겠다"라는 질문보다는 "이런 식으로 일하는 것이 왜"라는 질문에 더 가깝다.
그래서 당신이 사용하려고하는 관련 기록을 가져 오는 것에 관한 복음은: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 명의 개인이 아닌 하나의 조인 쿼리를 갖는 것이 더 나을 것 같습니다. 퍼포먼스 측면에서 볼 때, 개별 쿼리보다는 조인을하는 것이 항상 더 좋은 것은 아니라는 것을 알고 있습니다. (사실, 위의 두 개의 개별 쿼리가 조인보다 빠르다는 것을 알지만, 모든 문서 내가 읽은 적이있다. 나는보고 놀랐다.:include
광고 된대로 작동하지 않습니다.
어쩌면 레일즈~이다.성능 문제를 인식하고 어떤 경우를 제외하고는 참여하지 않습니까?
그것은:include
기능은 Rails 2.1에서 변경되었습니다. 레일즈는 모든 경우에 조인을하는 데 사용되었지만 성능상의 이유로 인해 일부 상황에서 여러 쿼리를 사용하도록 변경되었습니다.이 블로그 게시물Fabio Akita의 변화에 대한 좋은 정보가 있습니다 ( "최적화 된 Eager Loading"섹션 참조).
조인과 include의 차이점은 include 문을 사용하면 다른 테이블의 모든 특성을 메모리에로드하는 훨씬 더 큰 SQL 쿼리를 생성한다는 것입니다.
예를 들어, 주석으로 가득 찬 테이블이 있고 : joins => 사용자가 정렬 목적으로 모든 사용자 정보를 가져 오는 등의 작업을 수행하면 잘 작동하고 include보다 표시 시간이 적습니다. 그러나 표시하고 싶다고 말합니다 사용자 이름, 전자 메일 등과 함께 주석을 사용합니다. 조인을 사용하여 정보를 가져 오려면 가져 오는 각 사용자에 대해 별도의 SQL 쿼리를 작성해야하지만 사용한 경우 :이 정보를 사용할 준비가되었습니다.
좋은 예 :
성능 고려 사항 외에도 기능적 차이점이 있습니다. 주석에 참여할 때 주석이있는 게시물, 기본적으로 내부 조인을 요청합니다. 주석을 포함 할 때 모든 게시물 (외부 조인)을 요청합니다.
나는 최근에 차이점에 대해 더 많이 읽었습니다.:joins
과:includes
레일에. 여기에 내가 이해 한 것을 설명하고있다.
이 시나리오를 고려하십시오.
사용자는 has_many 개의 주석과 주석을 사용자에게 소유합니다.
User 모델에는 Name (문자열), Age (정수) 등의 특성이 있습니다. Comment 모델에는 Content, user_id 속성이 있습니다. 주석의 경우 user_id는 null 일 수 있습니다.
: 조인은내부 조인두 테이블 사이. 그러므로
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 (사용자 테이블)와 같은 모든 레코드.따라서 당신이한다면
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
백그라운드에서 데이터베이스 쿼리를 다시 실행하여 결과를 얻습니다.
: 포함하는 것은왼쪽 외부 조인두 테이블 사이. 그러므로
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">]>
comments.user_id가 표시된대로 nil 인 레코드를 가져옵니다.
또한 메모리에있는 테이블을 모두로드합니다. 따라서 당신이한다면
comment_1 = Comment.includes(:user).first
comment_1.user.age
#=> 24
comment_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
컬렉션의 각 구성원에 대한 관계를 사용할 때.
distinct
날 때마다 얻는다. 고맙습니다! - Beejamin
.joins는 데이터베이스 조인으로 작동하며 두 개 이상의 테이블을 조인하고 선택한 데이터를 백엔드 (데이터베이스)에서 가져옵니다.
.includes는 데이터베이스의 왼쪽 조인으로 작동합니다. 왼쪽면의 모든 레코드를로드했으며, 오른쪽면 모델과의 관련성이 없습니다. 메모리에 관련된 모든 객체를로드하기 때문에 열심히로드하는 데 사용됩니다. 포함 쿼리 결과에 대한 연관을 호출하면 데이터베이스에 대한 쿼리가 실행되지 않고 이미 데이터를 메모리에로드했기 때문에 메모리에서 데이터를 반환하기 만합니다.
'조인'은 테이블 조인에 사용되며 조인에 대한 연결을 호출하면 쿼리가 다시 실행됩니다 (많은 쿼리가 실행 됨)
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입니다.
하지만 함께 'includes'는 포함 된 연관을 열렬히로드하고 메모리에 추가합니다 (첫 번째로드에서 모든 연관을로드). 그리고 다시 쿼리를 실행하지 않습니다.
포함 된 레코드를 얻을 때 @ records = User.includes (: organizations) .where ( "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} 아무 쿼리도 실행되지 않습니다.
includes
(이것을 읽는 모든 사람에게) - onebree