[sql] SQL 조인 대 SQL 하위 쿼리 (성능)?

다음과 같은 조인 쿼리 가 있는지 알고 싶습니다.

Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id

다음과 같은 하위 쿼리

Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)

성능 을 고려할 때 두 쿼리 중 어느 것이 더 빠르며 그 이유는 무엇입니까?

또한 내가 다른 것보다 하나를 선호해야 할 때가 있습니까?

이것이 너무 사소하고 전에 물어 보면 미안하지만 혼란 스럽습니다. 또한 두 쿼리의 성능을 측정하는 데 사용해야하는 도구를 제안 해 주시면 좋을 것 입니다. 감사합니다!



답변

주로 동등성과 명시 적 JOIN이 있기 때문에 첫 번째 쿼리가 더 빠를 것으로 예상합니다. 내 경험상 IN매우 느린 연산자입니다. SQL은 일반적으로 WHERE“OR”( WHERE x=Y OR x=Z OR...)로 구분 된 일련의 절로 평가하기 때문 입니다.

그러나 ALL THINGS SQL과 마찬가지로 마일리지는 다를 수 있습니다. 속도는 무엇보다도 인덱스에 따라 크게 달라집니다 (두 ID 열에 인덱스가 있습니까? 많은 도움이 될 것입니다 …).

더 빠른 것을 100 % 확실하게 알 수있는 유일한 방법은 성능 추적을 켜고 (IO 통계가 특히 유용함) 둘 다 실행하는 것입니다. 실행 사이에 캐시를 지우십시오!


답변

글쎄, 나는 그것이 “오래되었지만 금”질문이라고 믿는다. 대답은 “상황에 따라 다릅니다!”입니다. 공연은 너무 섬세해서 “서브 쿼리를 사용하지 말고 항상 참여하라”고 말하기에는 너무 어리석은 주제입니다. 다음 링크에서 내가 매우 유용하다고 판단한 몇 가지 기본 모범 사례를 찾을 수 있습니다.

50000 개의 요소가있는 테이블이 있는데, 내가 찾고 있던 결과는 739 개의 요소였습니다.

처음에 내 질문은 다음과 같습니다.

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND p.anno = (
    SELECT MAX(p2.anno) 
    FROM prodotto p2 
    WHERE p2.fixedId = p.fixedId 
)

실행하는 데 7.9 초가 걸렸습니다.

마침내 내 질문은 다음과 같습니다.

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN
(
    SELECT p2.fixedId, MAX(p2.anno)
    FROM prodotto p2
    WHERE p.azienda_id = p2.azienda_id
    GROUP BY p2.fixedId
)

0.0256 초가 걸렸습니다.

좋은 SQL, 좋아요.


답변

실행 계획을 살펴보고 SQl 서버가이를 해석하는 방법의 차이점을 확인하십시오. Profiler를 사용하여 실제로 쿼리를 여러 번 실행하고 차이점을 얻을 수 있습니다.

상호 관련된 하위 쿼리를 사용할 때 하위 쿼리 대신 조인을 사용하여 실제 큰 성능 향상을 얻을 수있는 경우 이러한 항목이 그렇게 끔찍하게 다를 것이라고 기대하지 않습니다.

EXISTS는 종종이 두 가지 중 하나보다 낫고 왼쪽 조인 테이블에없는 모든 레코드를 원하는 왼쪽 조인을 말할 때 NOT EXISTS가 종종 훨씬 더 나은 선택입니다.


답변

성능은 실행중인 데이터의 양을 기반으로합니다.

20k 정도의 데이터가 적다면. JOIN이 더 잘 작동합니다.

데이터가 100k +와 비슷하면 IN이 더 잘 작동합니다.

다른 테이블의 데이터가 필요하지 않으면 IN이 좋지만 EXISTS로 이동하는 것이 좋습니다.

이 모든 기준을 테스트했으며 테이블에는 적절한 색인이 있습니다.


답변

성능은 동일해야합니다. 테이블에 올바른 인덱스와 클러스터링을 적용하는 것이 훨씬 더 중요합니다 ( 해당 주제에 대한 좋은 리소스 가 있습니다 ).

(업데이트 된 질문을 반영하도록 수정 됨)


답변

두 쿼리는 의미 상 동일하지 않을 수 있습니다. 직원이 둘 이상의 부서에서 일하는 경우 (제가 일하는 기업에서 가능합니다. 물론 이것은 테이블이 완전히 정규화되지 않았 음을 의미합니다) 첫 번째 쿼리는 중복 행을 반환하지만 두 번째 쿼리는 그렇지 않습니다. 이 경우 쿼리를 동등하게 만들려면 DISTINCT키워드를 SELECT절에 추가해야하므로 성능에 영향을 미칠 수 있습니다.

테이블이 엔터티 / 클래스 또는 엔터티 / 클래스 간의 관계를 모델링해야하지만 둘다는 아니어야한다는 설계 규칙이 있습니다. 따라서 OrgChart직원과 부서 간의 관계를 모델링하기 위해 세 번째 테이블 (예 :)을 만드는 것이 좋습니다 .


답변

나는 이것이 오래된 게시물이라는 것을 알고 있지만 이것은 매우 중요한 주제라고 생각합니다. 특히 오늘날 우리는 1 천만 이상의 레코드를 가지고 있고 테라 바이트의 데이터에 대해 이야기하고 있습니다.

나는 또한 다음과 같은 관찰에 무게를 둘 것이다. 내 테이블 ([data])에는 약 4,500 만 개의 레코드가 있고 [cats] 테이블에는 약 300 개의 레코드가 있습니다. 내가 이야기하려는 모든 쿼리에 대해 광범위한 인덱싱이 있습니다.

예 1을 고려하십시오.

UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid

대 예 2 :

UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d

예제 1은 실행하는 데 약 23 분이 걸렸습니다. 예제 2는 약 5 분이 걸렸습니다.

따라서이 경우 하위 쿼리가 훨씬 빠르다는 결론을 내릴 수 있습니다. 물론 1GB / sec에서 i / o가 가능한 M.2 SSD 드라이브 (비트가 아닌 바이트)를 사용하고 있으므로 인덱스도 정말 빠릅니다. 따라서 이것은 당신의 상황에서도 속도에 영향을 미칠 수 있습니다

일회성 데이터 정리 인 경우 실행하고 종료하는 것이 가장 좋습니다. 나는 TOP (10000)을 사용하고 얼마나 오래 걸리는지 확인하고 큰 쿼리에 도달하기 전에 레코드 수를 곱합니다.

프로덕션 데이터베이스를 최적화하는 경우 실시간 액세스가 정적 데이터를 검색하도록 트리거 또는 작업 브로커를 사용하여 레코드를 비 동기화하는 등 데이터 전처리를 강력히 제안합니다.