SQL 쿼리와 같은 여러 열을 최적화하기위한 모범 사례는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/473218

문제

상속 받고 최적화하려는 검색 쿼리가 있습니다. 누구나 모범 사례와 권장 사항이 있는지 궁금합니다. 프로덕션 서버는 여전히 SQL Server 2000입니다.

쿼리는 5 백만 레코드 테이블을 검색하기 위해 5 개의 다른 검색 기준 매개 변수 (예 : 이름, 성, 주소, 전화 등)를 수용하는 고급 고객 검색 저장 프로 시저입니다. WHERE 절에 결합 된 모든 열 및 열에 인덱스가 있습니다. 또한 초기 쿼리는 레코드를 페이징 용량을위한 테이블 변수로 덤프합니다.

INSERT INTO   @tempCustTable (CustomerID, FirstName, LastName, City, StateProvince, Zip, PhoneNumber)
SELECT  DISTINCT cu.CustomerID, cu.FirstName, cu.LastName, a.City,
a.StateProvince, a.Zip, p.PhoneNumber
FROM Customer cu WITH(NOLOCK)
LEFT OUTER JOIN Address a WITH(NOLOCK) ON cu.CustomerID = a.CustomerID
LEFT OUTER JOIN Phone p WITH(NOLOCK) ON cu.CustomerID = p.CustomerID
WHERE  (cu.LastName = @LastName OR cu.LastName LIKE @LastName + '%') 
AND (@FirstName IS NULL OR cu.FirstName = @FirstName OR cu.FirstName LIKE @FirstName + '%')
AND (@StateProvince = '' OR a.StateProvince LIKE @StateProvince)
AND (@City = '' OR a.City LIKE @City + '%')
AND (@Zip = '' OR a.Zip = @Zip OR a.Zip LIKE @Zip + '%')
ORDER BY cu.LastName, cu.FirstName

쿼리의 성능을 향상시킬 수있는 방법에 대한 권장 사항이 있습니까?

도움이 되었습니까?

해결책

이 전체 라인이 아닙니다

AND (@Zip = '' OR a.Zip = @Zip OR a.Zip LIKE @Zip + '%')

이와 동일합니다

AND (a.Zip LIKE @Zip + '%')

확실히

AND (a.Zip LIKE @Zip + '%')

그것은 동일합니다

a.Zip = @Zip OR a.Zip LIKE @Zip + '%'

다른 팁

SQLMenace가 시작으로 지적한 것처럼 코드에서 많은 중복성을 확실히 정리할 수 있습니다.

또 다른 것은 삽입 된 ..Select와 함께 사용해서는 안된다는 것입니다. 이 맥락에서 주문은 의미가 없습니다. 사람들은 때때로 그것을 사용하여 신원 칼럼이 특정 방식으로 행동하도록 강요하지만, 그것은 나쁜 습관 IMO입니다.

이것이 당신의 상황에서 도움이 될지 모르겠지만, 최근에 나온 한 가지는 저장 프로 시저에서 SQL Server (2005 년을 사용하지만 2000 년에도 사실)가 OR을 단락하지 않을 것이라는 점이었습니다. 많은 경우 상태. 예를 들어, 사용할 때 :

@my_parameter IS NULL OR my_column = @my_parameter

@my_parameter의 널 값을 전달하더라도 후반을 여전히 평가합니다. 저장 절차를 다시 컴파일하도록 설정했을 때도 발생했습니다 (및 SELECT). 속임수는 사례 명세서를 사용하여 단락을 강요하는 것이 었습니다. 그 트릭을 사용하고 (중복성을 제거) 당신의 진술은 다음과 같습니다.

INSERT INTO @tempCustTable
(
     CustomerID,
     FirstName,
     LastName,
     City,
     StateProvince,
     Zip,
     PhoneNumber
)
SELECT DISTINCT
     cu.CustomerID,
     cu.FirstName,
     cu.LastName,
     a.City,
     a.StateProvince,
     a.Zip,
     p.PhoneNumber
FROM Customer cu WITH(NOLOCK)
LEFT OUTER JOIN Address a WITH(NOLOCK) ON cu.CustomerID = a.CustomerID
LEFT OUTER JOIN Phone p WITH(NOLOCK) ON cu.CustomerID = p.CustomerID
WHERE
     (cu.LastName LIKE @LastName + '%') AND
     (1 =
          CASE
               WHEN @FirstName IS NULL THEN 1
               WHEN cu.FirstName LIKE @FirstName + '%' THEN 1
               ELSE 0
          END
     ) AND
     (1 =
          CASE
               WHEN @StateProvince = '' THEN 1
               WHEN a.StateProvince = @StateProvince THEN 1
               ELSE 0
          END
     ) AND
     (1 = CASE
               WHEN @City = '' THEN 1
               WHEN a.City LIKE @City + '%' THEN 1
               ELSE 0
          END
     ) AND
     (1 = CASE
               WHEN @Zip = '' THEN 1
               WHEN a.Zip LIKE @Zip + '%' THEN 1
               ELSE 0
          END
     )

쿼리를 더 길고 조금 더 복잡하게 만들지 만 더 나은 성능을 위해 가치가있을 수 있습니다. 이것은 특히 당신의 기준에 단락 될 수있는 하위 쿼리가 포함되어있는 경우 true.

드디어... 일관성을 유지하십시오 매개 변수로. @firstName의 경우 NULL 값을 확인하여 사용되었는지 여부를 확인하지만 다른 사람들은 빈 줄을 확인하고 있습니다. 기본 코딩 101 여기에주의를 기울여야합니다.

내 SQL 코드가 '%'를 추가하지 않으려 고 노력하지만 대신 매개 변수에 이미 가지고있을 것으로 기대합니다. 물론 응용 프로그램에서 검증 한 후에는 이렇게합니다! 그런 다음 '='비교를 포함하지 말고 항상 사용하십시오.

여기서 (cu.lastname like @lastname)

대신에:

여기서 (cu.lastname = @lastname 또는 cu.lastname like @lastname + '%')

  • 피하는 "또는"S- 일반적으로 인덱스 사용을 방지합니다.
  • 왼쪽에 "%"를 넣지 마십시오. - 같은 이유.

동적 SQL로 쿼리를 구축 할 수 있습니다. 그것은 대부분의 OR을 제거하고 사용자가 실제로 입력 한 매개 변수에 대한 WHERE 문선에만 포함해야한다는 것을 의미합니다.

이 작업을 수행하면 EXEC 대신 SP_EXECUTESQL을 사용하여 동적 SQL을 매개 변수화하여 쿼리 계획을 캐시 할 수 있습니다.

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