문제

다음 세 SQL 문의 성능에 차이가 있습니까?

SELECT * FROM tableA WHERE EXISTS (SELECT * FROM tableB WHERE tableA.x = tableB.y)

SELECT * FROM tableA WHERE EXISTS (SELECT y FROM tableB WHERE tableA.x = tableB.y)

SELECT * FROM tableA WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.x = tableB.y)

그들은 모두 작동하고 동일한 결과 세트를 반환해야합니다. 그러나 내부 선택이 TABLB, 하나의 필드 또는 상수의 모든 필드를 선택하는 경우가 중요합니까?

모든 진술이 동일하게 행동 할 때 모범 사례가 있습니까?

도움이 되었습니까?

해결책

Enists Clause에 대한 진실은 SELECT 절이 ENISS CLAUSE에서 평가하지 않는다는 것입니다. 시도 할 수 있습니다.

SELECT * 
  FROM tableA 
 WHERE EXISTS (SELECT 1/0 
                 FROM tableB 
                WHERE tableA.x = tableB.y)

... 그리고 제로 오류로 나뉘어져야하지만 평가되지 않기 때문에 그렇지 않습니다. 이것이 내 습관이 SELECT를 무시할 수 있음을 증명하기 위해 존재에 NULL을 지정하는 이유입니다.

SELECT * 
  FROM tableA 
 WHERE EXISTS (SELECT NULL
                 FROM tableB 
                WHERE tableA.x = tableB.y)

절에서 중요한 모든 조항은 클로스에서 출발하는 것입니다.

이 질문은 데이터베이스를 염두에두고 표시되지 않았으므로 공급 업체가 다른 것을 다르게 처리하기 때문에 테스트하고 설명/실행 계획을 확인하여 확인해야합니다. 버전간에 동작이 변할 수 있습니다 ...

다른 팁

확실히 #1. 그것은 무섭지 만, 최적화가 옳은 일을하고 의도를 표현한다는 것을 깨닫습니다. 또한 실수로 생각하지만 입력해야한다고 생각 해야하는 약간의 오타 보너스가 있습니다. #2는 허용되지만 표현력이 없습니다. 세 번째 옵션은 내 겸손하지 않은 의견에 악취가납니다. 편안함을 위해 " '가치 없음'이 존재한다면"말에 너무 가깝습니다.

일반적으로 다른 이점을 제공하고 실제로 성능에 영향을 미치지 않으면 비효율적으로 보이는 코드를 작성하는 것이 무서워하지 않는 것이 중요합니다.

즉, Optimizer는 거의 항상 복잡한 Join/Select/Grouping Wizardry를 실행하여 간단한 존재/하위 쿼리를 동일한 방식으로 저장합니다.

자신을 준 후 명성 불쾌한 또는 앙상술에서 영리하게 다시 쓰기 위해 결국 Optimizer는 여전히 동일한 엉터리 실행 계획을 사용하여 내장 또는 어쨌든 쿼리를 훨씬 쉽게 이해하기 쉽습니다.

이야기의 도덕은 플랫폼 최적화를 아는 것입니다. 'Decorative'쿼리 최적화에 관한 만연한 무릎 멍청이 가정은 거의 항상 부정확하고 내 경험과 관련이 없기 때문에 다른 일을 시도하고 실제로 무엇이 수행되는지 확인하십시오.

나는 이것이 오래된 게시물이라는 것을 알고 있지만 명확성을 더하는 것이 중요하다고 생각했습니다. 하나는 다른 형식을 다른 형식보다 선택할 수 있습니다.

첫째, 다른 사람들이 지적했듯이 데이터베이스 엔진은 추정된 선택 절을 무시합니다. SQL Server의 모든 버전에는 Oracle이 있으므로 MySQL 등이 있습니다. 많은 데이터베이스 개발 달의 많은 달리에서, 나는 Select 절을 제대로 무시하지 않는 DBM을 하나만 접했다 : Microsoft Access. 구체적으로, 이전 버전의 MS 액세스 (현재 버전으로 말할 수 없음).

이 "기능"을 발견하기 전에 사용했습니다. Exists( Select *.... 그러나 MS Access가 하위 퀘스트의 모든 열에서 스트리밍 할 것이라는 것을 발견 한 다음 버려집니다 (Select 1/0 또한 작동하지 않습니다). 그것은 내가 전환했다고 확신했다 Select 1. 하나의 DBM조차 어리석은 경우 다른 DBM이 존재할 수 있습니다.

글쓰기 Exists( Select 1... 의도를 전달하는 데 풍부하게 분명합니다 (솔직히 ""가치가 없다면 "안락함을 위해"가치가 없다면 "말하는 데 너무 가깝습니다." Select Null 같은 목적을 달성하지만 단순히 쓸 캐릭터입니다.

나는 전환했다 Exists( Select 1 DBMS가 어리석지 못할 수 없는지 확인하는 것입니다. 그러나 그것은 많은 달이었고 오늘은 대부분의 개발자들이 Exists( Select * 정확히 동일하게 작동합니다.

즉, 나는 피하는 한 가지 좋은 이유를 제공 할 수 있습니다. Exists(Select * DBMS가 올바르게 평가하더라도. 모든 용도를 찾아서 삼는 것이 훨씬 쉽습니다. Select * ENSISS 절에서 사용하는 모든 인스턴스를 건너 뛸 필요가없는 경우.

적어도 SQL Server에서

디스크에서 읽을 수있는 가장 적은 양의 데이터는 디스크 공간의 단일 "페이지"입니다. 프로세서가 하위 퀘스트를 만족시키는 한 레코드를 읽으면 중지 할 수 있습니다. 하위 쿼리는 마치 자체적으로 서있는 것처럼 실행되지 않은 다음 외부 쿼리에 포함되며 모든 것에 대한 완전한 쿼리 계획의 일부로 실행됩니다. 따라서 하위 쿼리로 사용될 때, 선택 조항의 내용은 실제로 중요하지 않으며, 단일 레코드가 발견되었는지 여부를 나타내는 부울을 제외하고는 외부 쿼리에 아무것도 반환되지 않습니다 ...

세 가지 모두 정확히 동일한 실행 계획을 사용합니다

나는 항상 [select * from ...]를 사용합니다. 특히 하위 퀘스트에서 무언가를 원한다는 것을 암시하지 않기 때문에 더 잘 읽습니다.

편집 : Dave Costa Comment에서 ... Oracle도 세 가지 옵션 모두에 동일한 실행 계획을 사용합니다.

이것은 일종의 거룩한 전쟁을 시작하는 데 어려움을 겪는 질문 중 하나입니다.

그것에 대해 상당히 좋은 토론이 있습니다 여기.

대답은 아마도 세 번째 옵션을 사용하는 것이라고 생각하지만 속도 증가는 너무 무한이므로 걱정할 가치가 없습니다. SQL Server가 어쨌든 내부적으로 최적화 할 수있는 쿼리 종류이므로 모든 옵션이 동일하다는 것을 알 수 있습니다.

그만큼 EXISTS 반환 a 부울 실제 데이터는 아니며 모범 사례는 #3을 사용하는 것입니다.

실행 계획. 그것을 배우고, 사용하고, 사랑하십시오

실제로 추측 할 수있는 방법은 없습니다.

다른 사람들이 말한 것 외에도 사용하는 관행 SELECT 1 Old Microsoft SQL Server (Prior 2005)에서 시작 - 쿼리 최적화기 SELECT *. 내 아는 한 다른 DBM은 이러한 결함이 없습니다.

이 테스트가 존재하지 않고 행의 존재에 대한 테스트가 존재하므로 위와 비슷한 일부 최적화기를 제외하고는 선택 목록에 무엇이 있는지는 중요하지 않습니다.

그만큼 SELECT * 가장 평소 인 것 같지만 다른 사람들도 받아 들일 수 있습니다.

#3은 반환 된 데이터가 필요하지 않으므로 최고가되어야합니다. 필드를 가져 오면 추가 오버 헤드가 추가됩니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top