계산 열의 Scalar UDF가 병렬 처리를 방해하지 못하게하는 방법이 있습니까? 곳이 있습니다. 예를 들어 :

SQL Server에서 Scalar UDF위험에 대해 많은 글을 썼습니다 . 임시 검색은 다양한 결과를 반환합니다.

그러나 Scalar UDF가 유일한 옵션 인 곳이 있습니다.

예를 들어 : XML을 다룰 때 : XQuery는 계산 열 정의로 사용할 수 없습니다. Microsoft가 문서화 한 옵션 중 하나는 Scalar UDF 를 사용하여 XQuery를 Scalar UDF 로 캡슐화 한 다음 계산 열에서 사용하는 것입니다.

이것은 다양한 효과와 일부 해결 방법이 있습니다.

  • 테이블을 쿼리 할 때 행 단위로 실행
  • 테이블에 대한 모든 쿼리가 연속적으로 실행되도록합니다.

함수를 스키마 바인딩하고 계산 열을 유지하거나 인덱싱하여 행별 실행을 해결할 수 있습니다. 스칼라 UDF가 참조되지 않더라도 이러한 방법 중 어느 것도 테이블에 충돌하는 쿼리의 강제 직렬화를 막을 수 없습니다.

알려진 방법이 있습니까?



답변

예인 경우 :

  • SQL Server 2014 이상을 실행 중입니다. 과
  • 추적 플래그 176이 활성화 된 상태 에서 쿼리를 실행할 수 있습니다 . 과
  • 계산 열은 PERSISTED

특히 다음 버전 이 필요합니다 .

  • SQL Server 2016 SP1 누적 업데이트 2
  • SQL Server 2016 RTM 누적 업데이트 4
  • SQL Server 2014 SP2 누적 업데이트 6

그러나 이러한 수정 사항에서 소개 된 버그 ( 20142016 및 2017 참조 )를 피하려면 다음을 적용하십시오.

추적 플래그는을 사용하는 –T전역 및 세션 범위 DBCC TRACEON에서 OPTION (QUERYTRACEON)또는 쿼리를 사용 하거나 계획 지침에 따라 시작 옵션 으로 유효 합니다.

추적 플래그 176은 지속적인 계산 열 확장을 방지합니다.

쿼리를 컴파일 할 때 수행되는 초기 메타 데이터로드는 직접 참조되는 열뿐만 아니라 모든 열을 가져옵니다. 이렇게하면 계산 된 모든 열 정의를 일치시킬 수있게되므로 일반적으로 좋습니다.

불행히도 부작용으로,로드 된 (계산 된) 열 중 하나가 스칼라 사용자 정의 함수를 사용하는 경우 계산 열이 실제로 사용되지 않더라도 해당 존재 가 전체 쿼리에 대해 병렬 처리비활성화합니다 .

추적 플래그 176은 열이 지속되면 정의를로드하지 않음으로써 (확장을 건너 뛰기 때문에)이를 지원합니다. 이런 식으로 스칼라 사용자 정의 함수는 컴파일 쿼리 트리에 존재하지 않으므로 병렬 처리가 비활성화되지 않습니다.

추적 플래그 176의 주요 단점 (약간 문서화는 제외)은 쿼리 표현식이 지속 계산 열과 일치하는 것을 방지한다는 것입니다. 쿼리에 지속 계산 열과 일치하는 표현식이 포함 된 경우 추적 플래그 176은 표현식이 다음으로 대체되는 것을 방지합니다. 계산 열에 대한 참조

자세한 내용은 SQLPerformance.com 기사 인 Persisted Computed Columns를 참조하십시오 .

이 질문에는 계산 열 및 스칼라 함수를 사용하여 값을 승격시키는 대안으로 XML이 언급되어 있으므로 선택적 XML 색인 : 전혀 나쁘지 않음 에서 언급 한 것처럼 선택적 XML 색인을 사용하는 방법을 살펴볼 수도 있습니다 .


답변

@Paul의 탁월한 # 1 외에도 실제로 # 2가 있습니다.

  • SQL Server 2005까지 거슬러 올라갑니다.
  • 추적 플래그를 설정할 필요가 없습니다.
  • 않습니다 하지 계산 된 열이 될 것을 요구 PERSISTED하고,
  • (추적 플래그 176이 필요하지 않기 때문에) 지속되는 계산 열과 일치하는 쿼리 식을 방지 하지 않습니다.

내가 알 수있는 한 유일한 단점은 다음과 같습니다.

  • Azure SQL Database에서는 작동하지 않습니다 (최소한은 아니지만 Linux의 경우 SQL Server뿐만 아니라 Amazon RDS SQL Server에서도 작동하지만).
  • 많은 DBA의 안락 지대에서 약간 벗어납니다.

이 옵션은 SQLCLR입니다.

맞습니다. SQLCLR 스칼라 UDF를 하나 개의 멋진 측면은 즉, 경우에 그들이하지 않는 모든 데이터 액세스 (사용자 나 시스템도)를, 그 때 병렬 처리를 금지하지 않습니다. 그리고 그것은 단지 이론이나 마케팅이 아닙니다. 완전히 자세한 글쓰기를 할 시간이 없지만 (현재)이를 테스트하고 증명했습니다.

다음 블로그 게시물의 초기 설정을 사용했습니다 (OP는 이것을 신뢰할 수없는 출처라고 생각하지 않습니다).

나쁜 아이디어 청바지 : 여러 인덱스 힌트

그리고 다음 테스트를 수행했습니다.

  1. 병렬 쿼리 (예상대로)
  2. ([c2] * [c3])─⇾ Parallelism (예상대로)으로 정의 된 비 지속적 계산 열 추가
  3. 계산 열을 제거하고 ─⇾ NO Parallelism (예상대로)으로 SCHEMABINDING정의 된 T-SQL Scalar UDF (로 생성 ) 를 참조하는 비 지속 계산 열을 추가했습니다.RETURN (@First * @Second);
  4. 티 – SQL UDF 열을 제거하고 추가 계산 비 유지 SQLCLR 스칼라 UDF (모두 참조하는 것을 시도 계산 열 IsDeterministic = true= false정의) return SqlInt32.Multiply(First, Second);─⇾ 평행도 (HOO 우!)

따라서 SQLCLR은 모든 사람에게 적합하지는 않지만 사람들 / 상황 / 환경에 적합한 이점이 있습니다. 그리고이 특정 질문 (XQuery 사용과 관련하여 주어진 예)과 관련이 있기 때문에 특정 작업이 필요합니다 (특히 수행중인 작업에 따라 조금 더 빠를 수도 있습니다).