2017-02-03 7 views
1

나는 ca가있는 테이블 (T1)을 가지고 있습니다. 500000 개 비 중복 기록 :두 개의 MySQL 테이블에서 최적 조인

나는이 두 테이블을 조인 할
ID Entity  
4  Ent4  
5  Ent5 
13 Ent13 
16 Ent16 

(ID를 기반으로 : 4) 효율적인 방법으로 다음과 같이

ID1 Relation ID2 
4  Rel4  13 
5  Rel5  4 
13  Rel13  16 
16  Rel16  5 

나는 속성 테이블 T1_Prop이

Entity Relation Entity 
Ent4  Rel4  Ent13 
Ent5  Rel5  EntEnt4 

잘 작동하는 JOIN을 포함하여이 선택문을 디자인했습니다. 그러나 이것이 최선의 방법인지 확실하지 않습니다.

select 
    a.entity, 
    r.relation, 
    b.entity 
from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 AND (r.ID1=4 OR r.ID2=4) 
INNER JOIN T1_Prop as b ON b.ID=r.ID2; 
+1

최적화 질문은 http://codereview.stackexchange.com/에 속합니다. – Sirko

+0

무엇이 가장 좋습니까? – Shadow

+0

효율면에서.난 그냥 MySQL을 사용하고 싶습니다 그리고 일부 external 라이브러리 또는 그것을 개선하기 위해 노력하고 있지 않다면 – StaOver

답변

0

이것은 SQL을 잘 사용합니다. 이런 종류의 쿼리를 위해 만들어졌습니다.

T1에 속도를 올리려면 두 가지 색인이 필요합니다. 그들은 :

(ID1, ID2, relation) 

(ID2, ID1, relation) 

두 개의 인덱스

OR 절을 처리하기위한 것입니다. 그것은 내가 볼 수있는 유일한 잠재적 인 성능 문제이며, 이는 단지 OR 작업으로 인해 쿼리 계획자가 너무 많은 테이블 검색을 수행하는 경우가 있기 때문입니다.

ID 값을 더 쉽게 선택할 수 있도록 쿼리를 리팩터링 해보십시오. 성능에 문제가있는 경우

select a.entity, r.relation, b.entity 
    from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 
INNER JOIN T1_Prop as b ON b.ID=r.ID2 
WHERE (r.ID1=4 OR r.ID2=4) 

그런 다음, 당신은 커버 인덱스를 만든 후,

select a.entity, r.relation, b.entity 
    from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 
INNER JOIN T1_Prop as b ON b.ID=r.ID2 
WHERE r.ID1=4 
UNION 
select a.entity, r.relation, b.entity 
    from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 
INNER JOIN T1_Prop as b ON b.ID=r.ID2 
WHERE r.ID2=4 
+0

'UNION ALL'을 만드십시오. 불필요한 기본 불필요한 중복 제거보다 효율적입니다. –

0

조회에서 처음 ON 절을 제외하고 좋은 모습으로 다시 리팩토링. 조건 (r.ID1=4 OR r.ID2=4)T1_Prop의 레코드가 T1 레코드에 참여하는 규칙이 아닙니다. 오히려 그것은 T1 레코드를 고려해야하며 따라서 WHERE 절에 속하는 조건입니다.

select 
    a.entity AS entity1, 
    r.relation, 
    b.entity AS entity2 
FROM t1 AS r 
INNER JOIN t1_prop AS a ON a.id = r.id1 
INNER JOIN t1_prop AS b ON b.id = r.id2 
WHERE r.id1 = 4 OR r.id2 = 4; 

이것은 실행 계획을 변경하지 않습니다. DBMS는 이것을 똑같이 실행합니다. 그러나 실제 의도를 보여주기 때문에 더 읽기 쉽습니다 : ID 중 하나가 4 인 관계를 가져 와서 해당 관계에 엔티티를 참여시킵니다.

이 의도를 보여주는 또 다른 옵션은 다음과 같습니다

select 
    a.entity AS entity1, 
    r.relation, 
    b.entity AS entity2 
FROM (SELECT * FROM t1 WHERE r.id1 = 4 OR r.id2 = 4) AS r 
INNER JOIN t1_prop AS a ON a.id = r.id1 
INNER JOIN t1_prop AS b ON b.id = r.id2; 

일부는 물론, 다른 사람들이하지 않는, 덜 읽을에서 하위 쿼리는 생각하지만. 또한 쿼리가 더욱 복잡해지고 서로 다른 테이블의 집계를 처리한다고해도 클린 쿼리를 작성하고 만드는 방법이 종종 있습니다.

위의 쿼리는 실제로 다른 쿼리보다 좋거나 나쁘지 않습니다.

+0

하위 쿼리는 불필요한 노력을 필요로합니다. –

+0

@ 릭 제임스 : 어느 쪽 이요? DBMS는 옵티 마이저가 잘 작동한다면 두 쿼리에 대해 동일한 실행 계획을 세워야합니다. MySQL이 아직 없다면, 그것은 모두 첫 번째 또는 두 번째 쿼리를 더 잘 지원할 수있는 현재 구현에 달려있다. MySQL은 현재 버전의 파생 테이블에 문제가있을 수 있습니다. 나는 모른다. 그러나 그 경우에도 다음 버전에서 이미 다를 수 있습니다 :-) –

+0

'EXPLAIN SELECT ... '두 사람은 옵티 마이저가 더 똑똑 해졌는지 여부를 말해야합니다. 이 부분은 5.7 정도 개선 된 것 같습니다. –