programing

SQL 또는 MySQL에서 JOIN 키워드를 사용하지 않는 조인에 문제가 있습니까?

iphone6s 2023. 7. 26. 21:41
반응형

SQL 또는 MySQL에서 JOIN 키워드를 사용하지 않는 조인에 문제가 있습니까?

데이터베이스 쿼리를 작성하기 시작할 때는 JOIN 키워드를 아직 몰랐고 자연스럽게 이미 알고 있는 것을 확장하고 다음과 같은 쿼리를 작성했습니다.

SELECT a.someRow, b.someRow 
FROM tableA AS a, tableB AS b 
WHERE a.ID=b.ID AND b.ID= $someVar

이제 이것이 내부 조인과 동일하다는 것을 알았으므로 코드에서 이러한 모든 쿼리를 찾아 다시 작성해야 하는지 자문합니다.그들에게 뭔가 냄새나는 것이 있나요, 아니면 그냥 괜찮은 건가요?


답변 요약:이 쿼리에는 아무런 문제가 없지만 키워드를 사용하면 코드를 보다 쉽게 읽을 수/유지 관리할 수 있습니다.

결론은:이전 쿼리를 변경하지 않고 앞으로 작성 스타일을 수정하고 키워드를 사용하겠습니다.

사용만링을 하여 조인 WHERE일부 일반적인 시나리오에서는 매우 비효율적일 수 있습니다.예:

SELECT * FROM people p, companies c 
    WHERE p.companyID = c.id AND p.firstName = 'Daniel'

대부분의 데이터베이스는 이 쿼리를 문자 그대로 실행합니다. 먼저 Decartian 제품을 사용합니다.people그리고.companies테이블을 선택한 다음 일치하는 테이블을 기준으로 필터링companyID그리고.id이 없는 외에는 하지 않고 하는 데는 .완전한 제약이 없는 제품은 메모리 외에는 아무 곳에도 존재하지 않고 잠시 동안만 존재하지만 계산에는 시간이 걸립니다.

은 제약 을 더나접제조그것입다니는룹으로 묶는 입니다.JOIN관련된 경우 s.이것은 주관적으로 읽기 쉬울 뿐만 아니라 훨씬 더 효율적입니다.따라서:

SELECT * FROM people p JOIN companies c ON p.companyID = c.id
    WHERE p.firstName = 'Daniel'

, 는 금더길지만그, ▁the▁at▁is▁it▁look▁to▁able를 볼 수 있습니다.ON절을 사용하여 완전히 구속된 것을 계산합니다.JOIN모든 에서 시작해서 제한하기보다는 직접적으로.이는 컴퓨팅 속도가 더 빠르며(특히 대규모 데이터 세트 및/또는 많은 테이블 조인) 메모리가 더 적게 필요합니다.

"comma"를 합니다.JOIN간결함입니다.내 생각에, 그것의 존재의 유일한 목적은 간결함입니다.성능에 미치는 영향을 고려할 때 이것이 강제적인 이유는 아니라고 생각합니다.

INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN는 가입을 위한 ANSI SQL/92 구문에서 가져온 것입니다.이러한 장황함은 개발자/DBA에게 조인의 의도가 무엇인지 보다 명확하게 알려줍니다.

SQL Server에는 항상 확인할 쿼리 계획이 있으며 다음과 같이 텍스트 출력을 수행할 수 있습니다.

SET SHOWPLAN_ALL ON
GO

DECLARE @TABLE_A TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_A
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

DECLARE @TABLE_B TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_B
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A, @TABLE_B AS B
WHERE
    A.ID = B.ID

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A
    INNER JOIN @TABLE_B AS B ON A.ID = B.ID

이제 테이블 변수가 생성하는 계획을 생략하겠습니다. 두 쿼리의 계획은 동일하지만 다음과 같습니다.

 SELECT A.Data, B.Data  FROM   @TABLE_A AS A, @TABLE_B AS B  WHERE   A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)
 SELECT A.Data, B.Data  FROM   @TABLE_A AS A   INNER JOIN @TABLE_B AS B ON A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)

그래서, 짧은 대답 - 여러분이 그것들을 유지할 때마다 그것들을 읽으려고 오랜 시간을 보내지 않는 한, 다시 쓸 필요가 없습니까?

구문 선택에 더 가깝습니다.조인 조건을 조인으로 그룹화하는 것을 선호하므로 INNER JOIN 구문을 사용합니다.

SELECT a.someRow, b.someRow
FROM tableA AS a
INNER JOIN tableB AS b
  ON a.ID = b.ID
WHERE b.ID = ?

(? 자리 표시자가 됨

예제의 구문에는 아무런 문제가 없습니다.'INNER JOIN' 구문은 일반적으로 'ANSI' 구문으로 불리며 예제에 나와 있는 스타일 뒤에 왔습니다.조인의 유형/방향/구성요소를 명확히 하기 위해 존재하지만 일반적으로 사용자가 가지고 있는 것과 기능적으로 다르지 않습니다.

'ANSI' 가입은 데이터베이스 플랫폼별로 지원되지만, 요즘은 보편화되어 있습니다.

참고로 'ANSI' 구문에 추가된 한 가지는 'FULL OUTER JOIN' 또는 'FULL JOIN'이었습니다.

이게 도움이 되길 바랍니다.

일반적으로:

JOIN 키워드를 사용하여 링크합니다(예:기본 키 및 외부 키를 사용할 수 있습니다.

WHERE 절을 사용하여 결과 집합을 관심 있는 레코드로만 제한합니다.

한 가지 문제가 발생할 수 있는 것은 동일한 쿼리에서 기존의 "콤마 스타일" 조인을 SQL-92 조인과 혼합하려고 할 때입니다. 예를 들어 하나의 내부 조인과 다른 외부 조인이 필요한 경우입니다.

SELECT *
FROM table1 AS a, table2 AS b
 LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1
WHERE a.column2 = b.column2;

문제는 최근 SQL 표준에서 쉼표 조인 전에 JOIN을 평가한다고 되어 있다는 것입니다.따라서 ON 절의 "a"에 대한 참조는 오류를 발생시킵니다. 왜냐하면 그 ON 절이 평가되고 있기 때문에 상관 이름이 아직 정의되지 않았기 때문입니다.이것은 매우 혼란스러운 오류입니다.

해결책은 두 스타일의 조인을 혼합하지 않는 것입니다.이전 코드에서 쉼표 스타일을 계속 사용할 수 있지만, 새 쿼리를 작성하는 경우 모든 조인을 SQL-92 스타일로 변환합니다.

SELECT *
FROM table1 AS a
 INNER JOIN table2 AS b ON a.column2 = b.column2
 LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1;

이전 조인 구문에서 고려해야 할 또 다른 사항은 on 절이 없기 때문에 실수로 카테션 조인을 얻기가 매우 쉽다는 것입니다.조회에 Distinct 키워드가 있고 이전 스타일 조인을 사용하는 경우, 이를 ANSI 표준 조인으로 변환하고 여전히 고유한 조인이 필요한지 확인합니다.이러한 방식으로 우발적인 카데이션 조인을 수정하는 경우 조인 및 조인 필드를 지정하도록 다시 작성하여 성능을 크게 향상시킬 수 있습니다.

저는 암묵적인 조인을 피합니다. 쿼리가 정말 크면 코드를 해독하기가 어렵습니다.

명시적인 조인과 좋은 포맷을 통해 코드는 주석 없이도 더 읽기 쉽고 이해할 수 있습니다.

또한 이 방법으로 내부 조인만 하는지 외부 조인도 수행하는지에 따라 달라집니다.예를 들어 WHERE 절(=* 및 *=)의 외부 조인에 대한 MS SQL Server 구문은 OUTER JOIN 구문과 다른 결과를 제공할 수 있으며 더 이상 지원되지 않습니다(SQL Server 2005의 http://msdn.microsoft.com/en-us/library/ms178653(SQL.90).aspx) ).

그리고 공연은?

사실, 성능은 RDBMS에서 매우 중요한 문제입니다.

그래서 문제는 무엇이 가장 효과적인가 하는 입니다. JOIN을 사용하거나 WHERE 절에서 테이블에 가입했습니까?

옵티마이저(또는 PG에서 말한 것처럼 평면기) 일반적인 작업이 잘 수행되기 때문에 두 실행 계획이 동일하므로 쿼리를 실행하는 동안의 성능은 동일하게 됩니다.

하지만 악마는 몇 가지 세부 사항에 숨겨져 있습니다.

모든 옵티마이저는 최적의 계획을 찾기 위해 제한된 시간 또는 제한된 양의 작업을 수행합니다.그리고 한계에 도달했을 때, 결과는 모든 계산된 계획 중에서 가장 좋은 계획이며, 가능한 모든 계획 중에서 더 나은 것은 아닙니다!

이제 문제는 테이블 조인을 위해 JOIN 대신 WHERE 절을 사용할 때 시간이 부족한가요?

그리고 정답은 YES입니다!

예, 관계형 엔진은 WHERE 절에 만들어진 유사 조인이 아니라 JOIN 연산자만 아는 관계형 대수를 사용하기 때문입니다.따라서 최적화 도구(사실 파서 또는 알그레브라이저)가 수행하는 첫 번째 작업은 쿼리를 다시 작성하는 것입니다.그리고 이것은 모든 계획 중에서 최고의 기회를 가질 수 있는 느슨한 기회입니다!

저는 오랜 RDBMS 경력(40년...) 동안 이 문제를 두 번 보았습니다.

언급URL : https://stackoverflow.com/questions/128965/is-there-something-wrong-with-joins-that-dont-use-the-join-keyword-in-sql-or-my

반응형