명시 적 vs 암시 적 SQL 조인


399

명시 적 내부 암시 적 내부 조인에 효율성 차이가 있습니까? 예를 들면 다음과 같습니다.

SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;

vs.

SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;

11
좋은 질문. 명시 적 조인이 전혀 사용되지 않는 이유가 궁금합니다. 그것없이 모든 쿼리를 수행 할 수 있습니까?
Andrew

6
EXPLAIN 키워드를 사용하여 두 쿼리에 대한 차이점을 파악하십시오. JOIN을 사용하여 차이점을보십시오. 100k가 넘는 레코드를 테이블에서 시도하면 차이점을 볼 수 있습니다.
Jeyanth Kumar

@andrew 내 질문은 실제로 암시 적 조인이 "해킹"의 형태인지에 대한 것이었다 ( "조인을 사용하지 않는 테이블이 두 개 이상인 쿼리? 해킹이 아닌가?")
bobobobo

3
그것들은 다르고, 암시 적 조인은 null 값을 다룰 때 가끔씩 놀라게 할 것입니다. 명시적인 결합을 사용하고 "아무것도 변경되지 않았을 때 발생하는 버그를 피하십시오!"
BlackTigerX

1
다른 점이 없다. ,CROSS JOIN패자가 및 바인딩하는 INNER JOIN것이다 CROSS JOINON같은 WHERE그러나 단단한 결합. 중요한 것은 DBMS가 쿼리를 최적화하는 방법입니다.
philipxy

답변:


132

성능면에서, 그들은 적어도 동일합니다 (적어도 SQL Server에서는).

추신 : IMPLICIT OUTER JOINSQL Server 2005 이후로 구문이 더 이상 사용되지 않습니다. IMPLICIT INNER JOIN질문에 사용 된 구문은 여전히 ​​지원됩니다.

"이전 스타일"사용 중단 구문 : 부분적인 것만


4
@lomaxx, 단지 명확성을 위하여, 당신은 지정할 수 있는 사용되지 않습니다 질문의 2의 구문?
J Wynia

8
지원 문서를 제공 할 수 있습니까? 여러 수준에서 잘못 들립니다.
NotMe

21
SQL 표준을 어떻게 폐기합니까?
David Crawshaw

7
@david Crenshaw, 암시 적 참여는 더 이상 표준에 포함되지 않았으며 18 년 동안 지속되지 않았습니다.
HLGEM

11
'내부'또는 '교차'품종의 소위 "암시 적 조인"은 표준에 남아 있습니다. SQL Server는 "이전 스타일"외부 조인 구문 (예 : *==*)을 더 이상 사용하지 않습니다 .
1

129

개인적으로 나는 테이블이 조인되고 테이블이 조인되는 방법을 명확하게하기 때문에 조인 구문을 선호합니다. 8 개의 서로 다른 테이블에서 선택하고 어디에서 많은 필터링을 수행하는 더 큰 SQL 쿼리를 비교해보십시오. 조인 구문을 사용하여 테이블이 조인되는 부분과 행을 필터링하는 부분을 분리합니다.


4
나는 완전히 동의하지만 이것은 주제가 아닌 것입니다. OP는 효율성에 대해 물었다.
villasv

56

MySQL 5.1.51에서 두 쿼리 모두 동일한 실행 계획이 있습니다.

mysql> explain select * from table1 a inner join table2 b on a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.02 sec)

mysql> explain select * from table1 a, table2 b where a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.00 sec)

table1166208 개의 행이 있습니다. table2약 1000 개의 행이 있습니다.

이것은 매우 간단한 경우입니다. 쿼리 옵티마이 저가 혼란스러워하지 않고 더 복잡한 경우에 다른 계획을 생성한다는 것을 결코 증명하지 않습니다.


이것이 정답입니다. 이것은 정확합니다. 계획은 동일하거나 더 큰 진술과 비슷하지만 기록의 양이 급격하여 성능 차이가 발생합니다.
소련 프론티어

37

두 번째 구문에는 원하지 않는 크로스 조인 가능성이 있습니다. 해당 WHERE 절없이 FROM 부분에 테이블을 추가 할 수 있습니다. 이것은 해로운 것으로 간주됩니다.


from 절의 테이블 이름이 where 절에 사용 된 테이블에서 생성되면 어떻게됩니까?
Jus12

명시 적 JOIN 구문으로 크로스 조인을 수행 할 수도 있습니다 ( stackoverflow.com/a/44438026/929164 ) 덜 엄격하고 사용자 오류가 발생하기 쉽다는 의미 일 것입니다.
Daniel Dubovski

15

첫 번째 답변은 ANSI 조인 구문을 사용하고 다른 답변은 유효하며 모든 관계형 데이터베이스에서 작동합니다.

ANSI 조인 구문을 사용해야한다는 grom에 동의합니다. 그들이 말했듯이, 주된 이유는 명확성을 위해서입니다. 술어가 많은 where 절을 사용하는 대신 일부는 조인 테이블과 다른 일부는 ANSI 조인 구문으로 반환되는 행을 제한하므로 테이블을 조인하는 데 사용되는 조건과 결과.


5

성능면에서, 그들은 정확히 동일하지만 (적어도 SQL Server에서는)이 조인 구문을 더 이상 사용하지 않으며 sql server2005에서 기본적으로 지원하지 않습니다.

더 이상 사용되지 않는 * = 및 = * 연산자 대 "외부 조인"을 생각하고 있다고 생각합니다.

방금 주어진 두 가지 형식을 테스트했으며 SQL Server 2008 데이터베이스에서 제대로 작동합니다. 제 경우에는 동일한 실행 계획을 산출했지만 이것이 항상 사실이라고 확신 할 수 없었습니다.


5

@lomaxx : 명확히하기 위해 위의 구문이 모두 SQL Serv 2005에서 지원되는 것이 확실합니다. 그러나 아래 구문은 지원되지 않습니다.

select a.*, b.*  
from table a, table b  
where a.id *= b.id;

특히 외부 조인 (* =)은 지원되지 않습니다.


2
솔직히 SQL Server 2000에서도 사용하지 않을 것입니다. * = 구문은 종종 잘못된 답변을 제공합니다. 때때로 이들은 이것을 교차 조인으로 해석합니다.
HLGEM

2

일부 데이터베이스 (특히 Oracle)에서 조인 순서는 쿼리 성능에 큰 차이를 만들 수 있습니다 (테이블이 두 개 이상인 경우). 하나의 응용에서, 어떤 경우에는 문자 그대로 두 차수의 차이가있었습니다. 올바른 힌트 구문을 사용하는 경우 내부 조인 구문을 사용하면이를 제어 할 수 있습니다.

사용중인 데이터베이스를 지정하지 않았지만 실제로 차이가없는 SQL Server 또는 MySQL을 제안 할 가능성이 있습니다.


1
리, 암시 적 조인에서도 힌트를 사용할 수 있습니다.
SquareCog

1
Oracle에서는 조인 순서가 실행 계획에 의미있는 방식으로 영향을 미치는 경우는 매우 드 rare니다. 이에 대한 설명은 Jonathan Lewis 의이 기사 를 참조하십시오 .
Jon Heller

1

Leigh Caldwell이 말했듯이 쿼리 최적화 프로그램은 기능적으로 동일한 SQL 문 모양에 따라 다른 쿼리 계획을 생성 할 수 있습니다. 이에 대한 자세한 내용을 보려면 다음 두 블로그 게시물을 살펴보십시오.

Oracle Optimizer Team의 게시물 1 개

"구조화 된 데이터"블로그의 다른 게시물

나는 이것이 당신이 흥미로운 것을 알기를 바랍니다.


Mike의 차이점은 명시 적 조인을 지정 하면 필터가 아닌 조인 조건 을 조인 해야한다는 점 입니다. 의미 적으로 올바른 쿼리의 경우 실행 계획은 동일합니다.
SquareCog

1

현명한 성능으로 차이가 없어야합니다. 명시 적 조인 구문은 from 절에서 테이블 간의 관계를 명확하게 정의하고 where 절을 어지럽히 지 않기 때문에 더 깔끔해 보입니다.


0

기본적으로이 둘의 차이점은 하나는 옛날 방식으로 작성되고 다른 하나는 현대 방식으로 작성된다는 것입니다. 개인적으로, 내부, 왼쪽, 외부, 오른쪽 정의를 사용하는 현대적인 스크립트를 선호합니다.

내부 조인을 처리 할 때 가독성에 실제로 차이가 없지만 이전 방법에서와 같이 왼쪽 및 오른쪽 조인을 처리 할 때 다음과 같이 얻을 수 있습니다.

SELECT * 
FROM table a, table b
WHERE a.id = b.id (+);

위의 내용은 다음과 달리 왼쪽 조인이 작성되는 방식입니다.

SELECT * 
FROM table a 
LEFT JOIN table b ON a.id = b.id;

시각적으로 볼 수 있듯이 현대적인 스크립트 작성 방법은 쿼리를보다 읽기 쉽게 만듭니다. (오른쪽 조인의 경우와 동일하며 외부 조인의 경우 조금 더 복잡합니다).

보일러 플레이트로 돌아가서 동일한 방식으로 쿼리를 처리 할 때 쿼리가 작성되는 방식을 SQL 컴파일러와 다르지 않습니다. 나는 많은 사람들이 Oracle 데이터베이스와 더 오래된 데이터베이스에 글을 쓰는 Oracle 데이터베이스에서 둘의 혼합을 보았습니다. 다시 말하지만, 스크립트가 얼마나 읽기 쉽고 개발중인 팀으로 요약됩니다.


-1

필자의 경험에 따르면 교차 결합 구문을 사용하는 구문을 사용하면 특히 Microsoft SQL 제품을 사용하는 경우 두뇌 손상 실행 계획이 생성되는 경우가 많습니다. 예를 들어, SQL Server가 테이블 행 수를 추정하는 방식은 엄청나게 끔찍합니다. 내부 조인 구문을 사용하면 쿼리 실행 방법을 약간 제어 할 수 있습니다. 따라서 실용적인 관점에서 현재 데이터베이스 기술의 atavistic 특성을 고려할 때 내부 조인을 사용해야합니다.


5
이것에 대한 증거가 있습니까? 때문에 허용 대답은 그렇지 말한다.
cimmanon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.