레일:포함 대 :조인트
이것은 "어떻게 해야 할지 모르겠다"는 질문이라기 보다는 "왜 일이 이런 식으로 진행되는가"라는 질문에 더 가깝습니다.
할 것으로 있는 것에 는 그서당신사것용알을있고는관기련끌록것것다입니대사에용복는하음한은래어는내을이할▁on▁so▁use▁that▁gospel▁to것다▁pulling니입▁the▁associated▁records▁is▁know사그용▁you를 사용하는 것입니다.: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명이 아닌 1명이 참여하는 것이 좋을 것 같습니다.성능 측면에서 개별 쿼리보다 조인을 수행하는 것이 항상 더 좋은 것은 아니라는 것을 알고 있습니다(실제로 사용한 시간을 기준으로 한다면 위의 두 개의 개별 쿼리가 조인보다 더 빠른 것처럼 보입니다). 하지만 제가 읽은 모든 문서를 보고 놀랐습니다.:include
광고대로 작동하지 않습니다.
Rails는 성능 문제를 인지하고 특정한 경우를 제외하고는 참여하지 않는 것이 아닐까요?
다음과 같은 것으로 보입니다.:include
기능은 Rails 2.1과 함께 변경되었습니다. Rails는 모든 경우에 조인을 수행했지만 성능상의 이유로 일부 상황에서는 여러 쿼리를 사용하도록 변경되었습니다.Fabio Akita의 이 블로그 게시물에는 변경에 대한 몇 가지 좋은 정보가 있습니다("최적화된 애저 로딩" 섹션 참조).
.joins
테이블을 조인하고 선택한 필드를 반환합니다.조인 쿼리 결과에 대한 연결을 호출하면 데이터베이스 쿼리가 다시 실행됩니다.
:includes
포함된 연결을 즉시 로드하여 메모리에 추가합니다. :includes
포함된 모든 테이블 특성을 로드합니다.result에 .
join과 include의 차이점은 include 문을 사용하면 다른 테이블의 모든 속성을 메모리로 로드하는 SQL 쿼리가 훨씬 더 많이 생성된다는 것입니다.
예를 들어, 당신이 코멘트로 가득 찬 테이블을 가지고 있고, 당신이 :dll => 사용자들을 사용하여 정렬 목적으로 모든 사용자 정보를 끌어오는 등의 경우, 그것은 정상적으로 작동하고, :dll보다 시간이 덜 걸리지만, 당신이 코멘트를 사용자 이름, 이메일 등과 함께 표시하기를 원한다고 말합니다.:joins를 사용하여 정보를 가져오려면 가져온 각 사용자에 대해 별도의 SQL 쿼리를 만들어야 하지만, 사용한 경우 :include 이 정보를 사용할 준비가 되었습니다.
좋은 예:
http://railscasts.com/episodes/181-include-vs-joins
나는 최근에 사이의 차이점에 대해 더 많이 읽고 있었습니다.:joins
그리고.:includes
ㅠㅠㅠㅠ 에 대한 입니다 (여기 제가 이해한 것에 대한 설명이 있습니다(예문 포함).
이 시나리오를 고려해 보십시오.
사용자는 _많은 주석을 가지고 있으며 주석은 _사용자에게 속합니다.
사용자 모델에는 다음과 같은 속성이 있습니다.이름(문자열), 나이(정수).Comment 모델의 속성은 다음과 같습니다.내용, user_id.주석의 경우 user_id는 null일 수 있습니다.
조인:
:sys는 두 테이블 사이에서 내부 조인을 수행합니다.따라서
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(comments 테이블의)가 user.id (users 테이블)과 동일한 모든 레코드를 가져옵니다.그러므로 만약 당신이 한다면,
Comment.joins(:user).where("comments.user_id is null")
#=> <ActiveRecord::Relation []>
그림과 같이 빈 배열이 표시됩니다.
또한 조인은 조인된 테이블을 메모리에 로드하지 않습니다.그러므로 만약 당신이 한다면,
comment_1 = Comment.joins(:user).first
comment_1.user.age
#=> User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["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가 0인 레코드를 가져옵니다.
또한 메모리에 있는 두 테이블 모두 로드를 포함합니다.그러므로 만약 당신이 한다면,
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
컬렉션의 각 구성원에 대한 관계를 사용할 시기.
.vmx는 데이터베이스 조인으로 작동하며 두 개 이상의 테이블을 조인하고 백엔드(백엔드)에서 선택한 데이터를 가져옵니다.
데이터베이스의 왼쪽 조인으로 작동합니다.왼쪽의 모든 레코드를 로드했으며 오른쪽 모델과 관련이 없습니다.메모리에 연결된 모든 개체를 로드하기 때문에 즉시 로드하는 데 사용됩니다.include 쿼리 결과에 대한 연결을 호출하면 데이터베이스에서 쿼리를 실행하지 않습니다. 메모리에 이미 데이터를 로드했기 때문에 메모리에서 데이터를 반환합니다.
방금 테이블을 조인하는 데 사용된 'filename'은 조인 시 연결을 호출하면 쿼리를 다시 실행합니다(많은 쿼리가 실행됨을 의미함).
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개입니다.
그러나 '포함'을 사용하면 포함된 연결을 즉시 로드하고 메모리에 추가합니다(첫 번째 로드에서 모든 연결을 로드). 다시 쿼리를 실행하지 않습니다.
@filename=User.includes(: organizations)와 같은 레코드를 얻을 수 있습니다.여기서 queryorganizations.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
@filename.map{|u|u.organisation.name } 쿼리가 실행되지 않음
언급URL : https://stackoverflow.com/questions/1208636/rails-include-vs-joins
'programing' 카테고리의 다른 글
루비에서 문자열이나 정수를 이진수로 변환하는 방법은 무엇입니까? (0) | 2023.06.02 |
---|---|
SSL 인증서를 신뢰할 수 없음 - 모바일에서만 (0) | 2023.06.02 |
파일 및 폴더를 포함하여 커밋되지 않은 변경 사항을 되돌리는 방법은 무엇입니까? (0) | 2023.06.02 |
YesNoCancel이 있는 MessageBox - No & Cancel이 동일한 이벤트를 트리거함 (0) | 2023.06.02 |
Response.redirect에서 "스레드가 중단되었습니다."를 발생시킵니다. (0) | 2023.06.02 |