2009-03-05 2 views
43

대부분의 Hibernate 연관은 "가져 오기"매개 변수를 지원합니다 : "선택"이 기본값 인최대 절전 모드 가져 오기 전략 - 언제 "조인"을 사용하고 언제 "선택"을 사용합니까?

fetch="join|select" 

.

어떤 협회에 어떤 것을 사용할 지 결정하는 방법은 무엇입니까?

"select"에서 "join"응용 프로그램으로의 변환을 시도해 보았습니다. 생성 된 쿼리의 수는 아마도 10 배 정도 줄었지만 성능은 똑같이 유지되었습니다 (심지어 조금 더 나 빠지게되었습니다).

고마워.

+0

다른 경우에 당신은 lazy 페칭을 사용 불가능하게하지 않는 최대 절전 모드 게으른 = "false를 지정하여 관련 지을 수 있었던 콜렉션을 가져 오는을위한 두 번째 SELECT 문을 통과 할 것이다"선택 "= 가져 오는 경우 중에 하나를 선택 성명에서 모든 정보를 가져 오지 않습니다 가입 "당신이 여기 http://javawebtutorial.blogspot.in/2013/09/hibernate-fetching-strategies.html – user528050

답변

38

조인은 n + 1 문제를 해결하기로되어 있습니다. 부모가 10 명이고 자녀가 10 명인 경우 조인에 하나의 쿼리가 필요하며 선택하려면 11 명이 필요합니다 (부모는 부모가 하나, 부모는 자식이 하나). 데이터베이스가 응용 프로그램과 동일한 서버에 있거나 네트워크가 실제로 빠르지 만 큰 문제는 아니지만 각 데이터베이스 호출에 대기 시간이 있으면 더할 수 있습니다. 조인 방}은 모든 행에서 상위 컬럼을 복제하지만 데이터베이스에 대해 한 x 만 왕복하기 때.에 초기 조회에서 다소 덜 효율적입니다.

일반적으로 모든 부모의 자녀가 필요할 것이라는 것을 알고 있으면 가입해야합니다. 내가 몇 부모의 자식 만 필요하면 select를 사용합니다.

+7

흠 자세한 내용을 찾을 수 있습니다, 나는 생산 (우리는 노예 원격 DB 서버가) 그것을 시도하고 행동을 정확히 체재 같은 - - "선택"보다 더 작은 비트. n + 1 문제를 돕기 위해 "default_batch_fetch_size"를 사용하므로 한 번에 하나씩 일괄 적으로 선택 쿼리를 실행합니다. – serg

9

선택은 데이터베이스에 새 쿼리를 발행하여 하위 항목을 가져옵니다. Join은 하위 쿼리를 부모 쿼리에 추가하여 하위 항목을 가져옵니다. 그렇기 때문에 쿼리 수가 줄어들더라도 비슷한 성능을 볼 수 있습니다.

선택 :

SELECT * FROM parent WHERE id=(whatever) 
SELECT * FROM child WHERE id=(parent.child.id) 

가입 : 다른 ... 전체 확실하지 이상을 사용하는 경우에 관해서는

SELECT * 
FROM parent 
LEFT OUTER JOIN child ON parent.child.id=child.id 
WHERE parent.id=(whatever) 

. 그것은 아마도 데이터베이스 시스템에 의존합니다. 하나가 다른 것보다 항상 좋았다면, 나는 그들이 당신에게 옵션을 주려고 귀찮을 것입니다! 각각에 대해 비슷한 성능이 나타나면 걱정하지 않아도됩니다.

1

페칭 = "가입" 페치 = "가입"하면 하나의 select 문에 모든 정보가 검색됩니다. 당신은 당신이 "선택"= 가져 오기 사용하는 경우에 비해 관련 수집을 가져 오기 위해 두 번째 SELECT 문을 PaaS를하려는 경우

페칭 = "를 선택합니다."

소스 : Hibernate Fetching Strategies

0

사람들은 항상 은 =이 가입 인출 사용하여 성능 저하에 대해 이야기하고 있습니다. 그러나 우리가 가져 오는 부모/자식 레코드의 수를 이해하는 것이 중요합니다.

하나의 부모 레코드를 가져오고 그 자식이 많지 않을 것으로 기대한다면 나는 제안 할 것입니다 당신은 fetch = SELECT을 사용하십시오.

당신이 아이를 포함한 모든 부모 레코드를 가져 싶은 경우에,이

그냥 메모를 추가 할 수 = 가져 갈 가입하는 것이 좋습니다 것, 그 기록이 느리게 (아이를 가져 오는 경우 게으른 = true), 모든 부모 및 자식 레코드가 단일 샷으로로드되기 때문에 fetch = JOIN을 사용하는 것은 의미가 없습니다.

0

부모에게 많은 자식이 있고 그 차례로 다른 자식이 많으면이 경우 초기 '결합'으로 인해 네트워크가 중단 될 수 있습니다. 나의 제안은 선택을 나누기 위해이 경우에 '선택'을 사용하는 것이다.

0

JOIN이 일반적으로 성능상의 이유로 바람직합니다.

SELECT를 사용하는 이유 중 하나는 다 대다 관계가있는 페이징 결과 (오프셋과 제한 설정) 때문입니다. JOIN을 사용하면, 루트 엔티티가 여러 개의 다 대다 자식을 포함하고, "복사본"이 제한에 대해 계산되면 루트 엔티티가 여러 번 나타납니다 (심지어 Hibernate가 DISTINCT_ROOT_ENTITY를 사용하여 붕괴하더라도).

관련 문제