[sql-server] SQL 문을 sargable로 만드는 것은 무엇입니까?

sargable은 정의에 의해 (적어도 내가 본 것에서) 쿼리 엔진이 쿼리가 사용하는 실행 계획을 최적화하도록 할 수 있음을 의미합니다. 나는 답을 찾으려고 노력했지만 주제에 대해서는별로없는 것 같습니다. 따라서 질문은 SQL 쿼리를 Sargable로 만들거나 만들지 않는 것입니다. 모든 문서는 대단히 감사하겠습니다.

참고 : SARGable



답변

쿼리를 처리 불가능 하게 만드는 가장 일반적인 것은 where 절의 함수 내에 필드를 포함시키는 것입니다 .

SELECT ... FROM ...
WHERE Year(myDate) = 2008

SQL 옵티마이 저는 myDate에 인덱스가 존재하더라도이를 사용할 수 없습니다. 문자 그대로 테이블의 모든 행에 대해이 함수를 평가해야합니다. 사용하는 것이 훨씬 낫습니다.

WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'

다른 예 :

Bad: Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Fixed: Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))

Bad: Select ... WHERE SUBSTRING(DealerName,4) = 'Ford'
Fixed: Select ... WHERE DealerName Like 'Ford%'

Bad: Select ... WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
Fixed: Select ... WHERE OrderDate < DateAdd(mm,-30,GetDate()) 


답변

이 작업을 수행하지 마십시오 :

WHERE Field LIKE '%blah%'

LIKE 값은 와일드 카드 문자로 시작하기 때문에 테이블 / 인덱스 스캔이 발생합니다.

이 작업을 수행하지 마십시오 :

WHERE FUNCTION(Field) = 'BLAH'

테이블 / 인덱스 스캔이 발생합니다.

데이터베이스 서버는 테이블의 모든 행에 대해 FUNCTION ()을 평가 한 후 ‘BLAH’와 비교해야합니다.

가능하면 반대로 수행하십시오.

WHERE Field = INVERSE_FUNCTION('BLAH')

이 매개 변수에 대해 INVERSE_FUNCTION ()을 한 번 실행하고 인덱스 사용을 계속 허용합니다.


답변

이 답변에서는 데이터베이스에 충분한 커버링 인덱스가 있다고 가정합니다. 이 주제 에 대해 충분한 질문 있습니다.

쿼리의 sargability는 많은 경우 관련 인덱스의 티핑 포인트에 의해 결정됩니다. 티핑 포인트는 한 테이블이나 결과 집합을 다른 테이블이나 조인하는 동안 인덱스 검색과 검색의 차이를 정의합니다. 한 번의 탐색은 전체 테이블을 스캔하는 것보다 훨씬 빠르지 만 많은 행을 탐색해야 할 경우 스캔이 더 의미가 있습니다.

따라서 옵티마이 저가 한 테이블의 결과 행 수가 다음 테이블에서 가능한 인덱스의 팁 포인트보다 적을 것으로 예상 할 때 SQL 문을보다 잘 이해할 수 있습니다.

자세한 게시물과 예제는 여기에서 찾을 수 있습니다 .


답변

작업을 sargable로 간주하려면 기존 인덱스를 사용하는 것만으로는 충분하지 않습니다. 위의 예에서 where 절의 색인화 된 열에 대해 함수 호출을 추가하면 정의 된 색인을 활용할 가능성이 높습니다. 해당 열 (인덱스)에서 모든 값을 “스캔”한 다음 제공된 필터 값과 일치하지 않는 값을 제거합니다. 행 수가 많은 테이블에는 여전히 효율적이지 않습니다. sargability를 실제로 정의하는 것은 정렬 된 항목 배열에 대한 반 집합 제거에 의존하는 이진 검색 방법을 사용하여 b-tree 인덱스를 순회하는 쿼리 기능입니다. SQL에서는 실행 계획에 “인덱스 찾기”로 표시됩니다.


답변