좋음, 나쁨 또는 무관심 : 1 = 1


14

reddit에 대한이 질문이 주어지면 쿼리에서 문제가 발생한 위치를 지적하기 위해 쿼리를 정리했습니다. 먼저 쉼표를 사용하고 WHERE 1=1쿼리를 쉽게 수정하기 위해 쿼리는 일반적으로 다음과 같이 끝납니다.

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

어떤 사람은 기본적으로 1 = 1이 일반적으로 게으르고 성능이 좋지 않다고 말했습니다 .

"조기 최적화"하고 싶지 않다는 점을 감안할 때 좋은 방법을 따르고 싶습니다. 이전에 쿼리 계획을 살펴 봤지만 일반적으로 쿼리 실행 속도를 높이기 위해 추가하거나 조정할 수있는 인덱스 만 찾아야합니다.

그러면 질문은 정말 ... Where 1=1나쁜 일이 발생합니까? 그렇다면 어떻게 알 수 있습니까?

사소한 편집 : 나는 항상 1=1최적화되어 있거나 최악의 경우 무시할 수 있다고 가정합니다. "Goto 's are Evil"또는 "Premature Optimization ..."또는 기타 가정 된 사실과 같은 진언에 의문을 제기하지 마십시오. 1=1 AND쿼리 계획에 실제로 영향을 미치는지 확실 하지 않았습니다. 하위 쿼리는 어떻습니까? CTE? 절차?

필요한 경우가 아니라면 최적화 할 사람은 아니지만 ... 실제로 "나쁜"일을하는 경우 효과를 최소화하거나 적용 가능한 경우 변경하고 싶습니다.


2
아뇨. 옵티마이 저가 중복 조건을 제거하는 데 몇 마이크로 초를 제외하고. 모호하지 않은 데이트 리터럴에 집중하는 것이 좋습니다.
ypercubeᵀᴹ

@ypercube가 말했듯이 아무런 차이가 없습니다. 쿼리 옵티마이 저는 그러한 차이를 만들려면 ****의 일부 여야합니다.)
Philᵀᴹ

4
레딧에서 읽은 모든 것을 믿지 마십시오. 부디.
Aaron Bertrand

1
@AaronBertrand 나는 그것을 직접 경험할 때까지 모든 것을 소금 알갱이로 가져갑니다. 나는 여전히 그럴듯하게 들리는 질문을하고 특히 그것이 매일 매일의 업무에 영향을 미칠 때 진실이 있는지 알아볼 것입니다.
WernerCD

4
소금 알갱이가 있습니다. 그러면 사무실 건물 위에 버려진 바다 전체의 소금 함량이 있습니다. : P
Philᵀᴹ

답변:


13

SQL Server 파서 옵티 마이저에는 "Constantfolding"이라는 기능이있어 쿼리에서 팽팽한 표현을 제거합니다.
실행 계획을 보면 술어의 어느 곳에도 해당 표현식이 나타나지 않습니다. 이는 컴파일 타임에 이러한 이유와 다른 이유로 일정한 폴딩이 수행되며 쿼리 성능에 영향을 미치지 않음을 의미합니다.

자세한 내용은 카디널리티 추정 중 지속적인 폴딩 및 식 평가 를 참조하십시오.


필드를 연결하는 알려진 패턴이기 때문에 아마 컴파일되었을 것입니다.
jcolebrand

아니요, 그것은 타우 톨 로지이기 때문에 정리됩니다. 2736 = 2736과 동일한 방식으로 작동하며 이는 1 = 1만큼 평범하지 않습니다. 모순에도 동일하게 적용됩니다. 이 경우이 기능을 "모순 감지"라고합니다.
spaghettidba

"알려진 패턴"의 어느 부분이 "1 = 1이어야 함"을 의미 했습니까?
jcolebrand

9

중복 조건자를 추가하면 SQL Server에서 차이가 생길 수 있습니다.

아래의 실행 계획 @1에서 첫 번째 계획 'foo'의 두 번째 계획 의 리터럴 을 확인하십시오.

여기에 이미지 설명을 입력하십시오

이는 SQL Server가 실행 계획 재사용을 촉진하기 위해 간단한 매개 변수화 를위한 첫 번째 쿼리로 간주했음을 나타냅니다. 그러나 두 상수를 비교하면 두 번째 경우에는 이것이 발생하지 않습니다.

간단한 매개 변수화 (이전의 자동 매개 변수화)를 방지하는 조건 목록은 Microsoft 기술 문서 캐싱 계획의 부록 A에서 찾을 수 있습니다.

간단한 매개 변수화는 일반적으로 어쨌든 의존 해야하는 것이 아닙니다. 쿼리를 명시 적으로 매개 변수화하는 것이 훨씬 좋습니다.


4

최신 RDBMS (Oracle, Microsoft SQL Server 및 PostgreSQL 포함)에 대해서는 성능에 영향을 미치지 않습니다.

누군가 언급했듯이 이는 쿼리 계획 단계에만 영향을 미칩니다. 따라서 다음과 같이 데이터를 반환하지 않는 간단한 쿼리를 수천 번 반복 실행하는 경우에만 차이가 나타납니다.

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

나에게 PostgreSQL 9.0에서는 10000 회 반복으로 볼 수 있습니다.

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms

0

이것은 데이터베이스 매개 변수 cursor_sharing을 사용할 때 Oracle에 "문제"가 될 수 있습니다. 이것이 "force"로 설정되면 모든 SQL 문이 수정됩니다. 쿼리의 모든 "상수"는 바인드 변수 (예 : 1 => : SYS_0)로 바뀝니다.

이 옵션은 일부 게으른 개발자를 처리하기 위해 도입되었습니다. 반면에 다른 게으른 개발자들에게도 해를 끼칠 수 있습니다. 그러나 위험은 그리 높지 않습니다. 11g부터 바인드 변수 엿보기 기능이 있습니다.


무엇을 명확히 할 수 있습니까 "11g 이후로는 바인드 변수 기능을 엿있다." 방법?
ypercubeᵀᴹ

@ypercube "바인드 변수 엿보기"는 옵티마이 저가 바인드 변수의 실제 값을 관찰하고 데이터 통계를 사용하여 쿼리 실행 계획을 다시 평가하고 재생성 할 것임을 의미합니다. 엿보기가 데이터 통계에 의존하지 않기 때문에 논의중인 구문에 어떤 영향을 미칠지 의심 스럽습니다.
mustaccio
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.