내부 조인 대 위치


257

(오라클에서) 성능에 차이가 있습니까?

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?


1
단지 기록을 위해, 내가 본 쿼리는 조인 만에서 변경하여 다른 결과를 반환 할 where 절
BlackTigerX

12
@BlackTigerX : 다른 결과? 외부 조인이 있습니까? 절 inner join ... on에서 동등한 조인 기준을 적용하는 것과 비교할 때 어떻게 다른 결과가 발생하는지 알 수 없기 때문입니다 where.
섀넌 세브란스

오라클 데이터베이스의 이전 버전에는 존재하지 않음join
MajidTaheri

2
@MajidTaheri : 몇 가지 오라클 버전에 대해 이야기하고 있습니까? Oracle에서 지원하는 모든 버전은 JOIN 표기법을 지원합니다.
Jonathan Leffler

사소한 경우를 바탕으로 일반적인 답변이나 모범 사례를 찾으십시오. 여러 AND 조건을 포함하는 더 복잡한 where 절이있는 "재 일치"를보고 싶습니다. 적어도 SQL Server에는 크로스 오버 지점이 있습니다.
crokusek

답변:


195

아니! 동일한 실행 계획은 다음 두 테이블을보십시오.

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

내부 조인을 사용하는 쿼리의 실행 계획 :

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

WHERE 절을 사용한 쿼리 실행 계획.

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

4
오라클에 대한 공식 문서가 있는지 확인하고 싶습니다.
4 Leave Cover

68

쿼리 최적화 프로그램이 올바르게 작동하는 경우 해당 쿼리간에 차이가 없어야합니다. 동일한 원하는 결과를 지정하는 두 가지 방법 일뿐입니다.


22
예, 성능은 동일해야합니다. 그러나 SELECT * FROM Table1, Table2 WHERE ... 구문은 EVIL입니다!
Joel Coehoorn

2
FOR INNER JOINS를 이해하는 것이 SQL-92 구문보다 훨씬 쉽다는 것을 알았습니다. 귀하의 마일리지가 다를 수 있습니다.
Craig Trader

25
INNER JION보다 WHERE 구문을 쉽게 읽을 수 있습니다. Vegemite와 같습니다. 세계의 대부분의 사람들은 아마 역겨운 것을 알지만 아이들은 그것을 좋아하게되었습니다.
ScottCher

3
Vegemite는 실제로 불쾌하지만 다시 스크랩을 좋아합니다. 그림을 이동.
StingyJack

2
@Darryl JOIN테이블을 조인하는 조건이 WHERE절의 "어딘가"대신 바로 정의되기 때문에 s가 더 읽기 쉽다고 생각합니다 . 테이블이 서로 관련되는 방식을 정의하는 대신 WHERE데이터 세트를 제한 하는 조항 (예 :)을 예약하는 WHERE DATE > (SYSDATE - 1)것이 좋습니다 (예 :) WHERE T1.ID = T2.ID. 문제의 예와 같은 작은 테이블의 경우 거의 차이가 없지만 여러 테이블과 여러 조건이 관련된 큰 쿼리의 경우 쿼리를 이해하기가 훨씬 쉽다고 생각합니다.
ImaginaryHuman072889

61

그들은 정확히 같아야합니다. 그러나 코딩 연습으로 조인을 보았습니다. 그것은 분명히 당신의 의도를 분명히 보여줍니다.


8
나는 동의한다. 특히 여러 테이블에 조인하는 경우 명시 적 조인을 수행하는 경우 select 문을 구문 분석하는 것이 훨씬 쉽습니다.
Paul Morie

13
과연. 조인은 두 데이터 집합 간의 의미 론적 관계를 나타내지 만 필터링 된 집합을 나타내는 위치입니다. +1
EightyOne Unite

26

를 사용 JOIN하면 코드를 쉽게 이해할 수 있으므로 코드를보다 쉽게 ​​읽을 수 있습니다.

속도에는 차이가 없으며 ( 방금 테스트했습니다 ) 실행 계획은 동일합니다.


감사합니다. 이 두 방법 사이의 속도 압축을 찾고있었습니다.
Farhad Navayazdan

14

Oracle에 대해서는 모르지만 이전 구문은 SQL Server에서 더 이상 사용되지 않으며 결국 사라질 것입니다. 새 쿼리에서 이전 구문을 사용하기 전에 Oracle에서 수행하려는 작업을 확인했습니다.

조인 기준을 다른 필요한 위치 조건과 혼합하는 것보다 새로운 구문을 선호합니다. 새로운 구문에서는 조인을 만드는 것과 다른 조건이 적용되는 것이 훨씬 명확합니다. 이와 같은 짧은 쿼리에서 큰 문제는 아니지만 더 복잡한 쿼리를 사용하면 훨씬 혼란스러워집니다. 사람들은 기본 쿼리에 대해 배우기 때문에 복잡한 쿼리에 조인 구문을 사용하기 전에 조인 구문을 사용하는 것을 선호하는 경향이 있습니다.

다시 한 번 Oracle을 구체적으로 알지 못하지만 SQL Server 2000에서도 이전 스타일의 왼쪽 조인의 SQL Server 버전에 결함이 있으며 일관성이없는 결과 (때로는 왼쪽 조인이 때때로 교차 조인)를 제공한다는 것을 알고 있습니다. 익숙한. 바라건대 오라클은 같은 문제를 겪지 않지만 왼쪽과 오른쪽 조인은 이전 구문으로 올바르게 표현하기가 더 어려울 수 있습니다.

또한 ANSII 표준 조인을 사용하는 개발자가 조인의 의미와 그 의미가 무엇인지에 대해 더 잘 이해하는 경향이 있다는 것은 내 경험이었습니다 (물론 이것은 개인적으로 개인적인 견해이며 다른 경험 일 수 있습니다). 데이터베이스에서 데이터. 데이터베이스를 잘 이해하고있는 대부분의 사람들이 더 복잡한 쿼리를 작성하는 경향이 있기 때문에 이전 스타일보다 ANSII 표준을 사용하는 것이 훨씬 쉬운 것 같습니다.


1
아멘 형제. JOINERS와 함께 !!
ScottCher

14

[보너스 포인트 ...]

JOIN 구문을 사용하면 한 줄에 모두 포함 된 조인을보다 쉽게 ​​주석 처리 할 수 ​​있습니다. 이 는 복잡한 쿼리를 디버깅하는 경우 유용 할 수

다른 사람들이 말했듯이 기능적으로 동일하지만 JOIN은 의도에 대한 진술이 더 명확합니다. 따라서 는, 어떤 경우에는 현재의 오라클 버전 (나는 그것이 않는 경우 아무 생각이 없음)에서 두 쿼리 최적화를 도와 수 있습니다 오라클 (아무도 어떤 생각이 없다)의 향후 버전에서 쿼리 최적화를 도와, 또는 할 수 있다면 도움이 데이터베이스 공급 업체를 변경합니다.


2
또는 ... INNER JOINS를 LEFT JOINS로 쉽게 변경하면 예상되는 행을 놓치게 만드는 조인을 확인할 수 있습니다. 전체 쿼리를 한 번에 수행하기 때문에이 작업을 수행합니다. INNER JOINS를 주석 처리하면 제거 프로세스를 수행해야합니다. 시간이 더 걸립니다. 그러나 이것은 가독성을 제외하고 INNER JOINS에서 내가 가장 좋아하는 이유 중 하나이기 때문에 +1입니다!
Matthew McPeak

13

논리적으로 동일하지만 ANSI 구문을 채택한 이전 버전의 Oracle에서는 종종 더 복잡한 경우에 버그가 있었기 때문에 사용시 Oracle 개발자의 저항을받는 경우가 있습니다.


이전 버전의 Oracle에 버그가 있습니까? 얼마나 일찍? 어떤 버전입니까?
ScottCher

Metalink는 세부 사항을 가지고 있습니다 ... 그들은 모든 곳에서 팝업됩니다.
David Aldridge

7

성능은 동일해야하지만 외부 조인의 경우 명확성이 향상되어 조인 버전을 사용하는 것이 좋습니다.

또한 결합 버전을 사용하여 의도하지 않은 직교 곱을 피할 수 있습니다.

세 번째 효과는 더 간단한 WHERE 조건으로 SQL을보다 쉽게 ​​읽을 수 있다는 것입니다.


저는 그 기준이 모호한 경우 의도하지 않은 효과가 핵심이라고 생각합니다. 조인 유형을 지정하면 얻는 내용을 정확히 알 수 있습니다. 다른 데이터베이스와 동일한 데이터베이스 플랫폼의 다른 버전에서도 암시 적 조인에서 null 값을 다르게 처리한다는 것을 알았습니다. 왼쪽 / 오른쪽 내부 / 외부를 지정하면 어느 것이 올바른지 생각하는 데 시간이 걸립니다. 모호한 방법을 사용하면 원하는 방식으로 작동한다고 가정합니다.
Steve Kallestad

6

Oracle에서 조인 키 속성의 이름이 두 테이블에서 동일하게 지정되면 다음과 같이 작성할 수도 있습니다.

select *
from Table1 inner join Table2 using (ID);

물론 이것은 동일한 쿼리 계획을 가지고 있습니다.


이전 개정판이 답변의 의미를 변경했기 때문에 개정판을 롤백했습니다.
juan

5

테이블이 세 번째 정규 형식 인 시나리오에서는 테이블 간의 조인이 변경되지 않아야합니다. 즉, CUSTOMERS 및 PAYMENTS 가입은 항상 동일해야합니다.

그러나 조인필터를 구분해야 합니다 . 조인은 관계에 관한 것이고 필터는 전체 파티션에 관한 것입니다.

표준을 참조하는 일부 저자 (예 : Jim Melton; Alan R. Simon (1993). 새로운 SQL 이해 : 완전한 가이드. Morgan Kaufmann. 11-12 페이지. ISBN 978-1-55860-245-8) , FROM 절의 쉼표로 구분 된 테이블보다 JOIN 구문을 채택 할 경우의 이점에 대해 썼습니다.

나는이 관점에 전적으로 동의합니다.

SQL을 작성하고 동일한 결과를 얻는 방법에는 여러 가지가 있지만 팀워크를 수행하는 많은 사람들에게 소스 코드 가독성은 중요한 측면이며, 소스를 명확하게하기 위해 테이블을 특정 필터와 서로 관련시키는 방법을 분명히 구분했습니다. 암호.


내부 결합은 교차 결합을 의미합니다. 쉼표는 키워드 조인보다 우선 순위가 낮은 교차 조인입니다. 켜짐 대 "필터"는 내부 결합과 관련이 없습니다. NF는 쿼리와 관련이 없습니다. 표준의 어떤 것도 쉼표를 통해 키워드 조인을 홍보하지 않습니다. 사소한 최적화는 어디에서나 동일하게 취급합니다. 이 답변은 많은 오해입니다.
philipxy

1) @philipxy가 "FROM 절에서 쉼표로 구분 된 테이블은 CROSS JOINed 테이블과 같은 의미를 갖습니다"라고 말하려고합니다. 동의합니다. 물론, 구 구문을 고수 할 수 있으며 JOIN 절과 공존 할 수 있습니다. RDBMS 옵티마이 저는 두 경우를 동일하게 완벽하게 이해하고 (물론 동일한 경우) 동일한 계획을 구체화합니다.
abrittaf

4

PostgreSQL에는 분명히 차이가 없습니다. 둘 다 동일한 쿼리 계획과 동일합니다. 99 %도 Oracle의 경우라고 확신합니다.


2

둘 다 같은 일을하는 내부 조인입니다. 하나는 단순히 최신 ANSI 구문을 사용합니다.


2

기능적으로 그들은 말한 것과 같습니다. 조인을 수행하는 것이 원하는 것을 정확하게 설명하는 것이 더 낫다는 데 동의합니다. 여러 번 조인을 시작할 때까지 어떻게 쿼리하고 싶었는지 알고 내 머리 속의 원래 쿼리와 다른 쿼리를 원한다는 것을 깨달았습니다.


1

기능적으로 두 쿼리 모두 동일한 방식으로 처리되어야합니다. 그러나 새로운 조인 구문을 사용하는 뷰에서 선택하는 경우 쿼리를 사용하여 쿼리를 구성하는 것이 중요합니다. 뷰가 "join"문을 사용하는 경우 Oracle 옵티마이 저는 혼란 스러울 수 있지만 뷰에 액세스하는 쿼리는 "where"절에서 전통적인 조인 방법을 사용합니다.


조인보다 뷰에 문제가 더 많습니다.
존재하지 않는

0

두 쿼리의 정체성이 명백해 보이지만 때때로 이상한 일이 발생합니다. Oracle 10g에서 Join 술어를 JOIN에서 WHERE로 옮길 때 쿼리마다 실행 계획이 다르므로 쿼리가 더 훌륭하지만 (테이블이 더 나은 경우)이 문제를 재현 할 수는 없습니다. 내 데이터와 통계에 달려 있다고 생각합니다. 최적화 프로그램은 매우 복잡한 모듈이며 때로는 마술처럼 행동합니다.

그렇기 때문에 DB 내부에 의존하기 때문에 일반적 으로이 질문에 대답 할 수 없습니다. 그러나 우리는 답이 ' 차이가 없어야 한다'는 것을 알아야합니다 .


0

프로덕션에서 sp의 시간 초과 중 하나를 검사 할 때 오늘이 수수께끼를 겪었습니다 .xml 피드에서 빌드 된 테이블의 내부 조인을 대신 'where'절로 변경했습니다 ... 평균 실행 시간이 2.2 초가되기 전에 ... 실행 계획의 주요 차이점은 주요 조회가 사라지는 것입니다 ... 두 방법을 사용하여 테스트 할 때까지 알 수없는 메시지입니다.

건배.



0

kiewik이 말했듯이 실행 계획은 동일합니다.

JOIN 문은 읽기가 쉬워서 ON 조건을 잊어 버리지 않고 직교 곱을 얻는 것이 더 쉽습니다. 이러한 오류는 유형이 여러 개인 조인을 사용하여 긴 쿼리에서 감지하기가 매우 어려울 수 있습니다. SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

하나의 조인 조건 만 잊어 버리면 너무 많은 레코드를 반환하는 쿼리를 실행하는 데 시간이 오래 걸립니다. 일부 사람들은 DISTINCT를 사용하여 쿼리를 패치하지만 여전히 실행 시간이 너무 깁니다.

정확하게 JOIN 문을 사용하는 것이 가장 좋은 방법 인 유지 보수성 및 가독성이 좋은 이유입니다.

더 잘 기억한다면 JOIN은 메모리 사용과 관련하여 최적화됩니다.


0

나는 그 좋은 대답에 덧붙여 있습니다 :

그것은 각각 SQL92와 SQL89로 정의 된 것입니다 .INNER라는 단어를 생략 할 수는 있지만 성능 차이는 없습니다 (JIN 만 사용하면 충분하고 가장 간단한 쿼리에서는 5 개의 키보드 획을 저장합니다. 그들).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.