Parallel Scalar UDF 지원이 합리적인 기능 요청입니까?


10

스칼라 UDF가 전체 직렬 계획을 강제한다는 것은 상당히 잘 문서화되어 있습니다.

병렬로 기능 실행

파이프 라인에서 UDF를 계산해야하는 지점에 많은 수의 행이 주어지면 엔진이 프로세서간에 행을 분산시킬 수없는 이유는 무엇입니까? UDF 내에 상태가 없으면 순서는 중요하지 않습니다.

블랙 박스가 커서를 사용해야한다는 UDF에 대한 주장이 있습니다. 반복 사이에 일부 상태가 유지되지만 그렇지 않으면 병렬화되어야하는 것처럼 보이는 경우 SP 내에서 사용자 커서를 병렬화 할 수 없음을 알 수 있습니다.

엔진이 UDF 계산 단계 대신 전체 계획을 직렬화하는 이유를 설명하기위한 추가 사항.

병렬 UDF 지원이 요청하기에 적합한 기능입니까?


1
Scalar 사용자 정의 함수 를 단일 열 인라인 테이블 반환 함수 로 다시 작성하는 것이 적절한 반응 입니다. 이들은 뷰와 동일한 방식으로 확장되므로 완전히 최적화됩니다. 이런 관점에서, 당신의 질문은 여전히 ​​가치가 있습니까?
Pieter Geerkens

1
TVF 해결 방법으로 성공했습니다. 그런 자연스러운 구성을 사용하지 않는 것이 잘못된 것 같아서 물었습니다. 또한 새로운 SQL 개발자가 UDF 내부를 배울 것을 기대하는 것은 비현실적인 것 같습니다.
crokusek

설명을 명확하게합니다. 다중 문 TVF가 아닌 ITVF 성공
crokusek

답변:


17

UDF가 전체 직렬 계획을 강제한다는 것은 상당히 잘 문서화되어 있습니다.

잘 문서화 된 것이 확실하지 않습니다.

  • 스칼라 T-SQL 함수는 계획의 어느 곳에서나 병렬 처리를 방지합니다.
  • 스칼라 CLR 함수는 데이터베이스에 액세스하지 않는 한 병렬로 실행될 수 있습니다.
  • 다중 문 테이블 반환 T-SQL 함수는 다른 곳에서 병렬 처리를 사용할 수있는 계획에서 직렬 영역을 강제 실행합니다.
  • 인라인 테이블 반환 T-SQL 함수는 뷰처럼 확장되므로 직접적인 영향은 없습니다.

참조 병렬 실행 계획 강제 및 / 또는 크레이그 프리드먼의 병렬 실행 프레젠테이션을 .

블랙 박스가 커서를 사용해야한다는 UDF에 대한 주장이 있습니다.

이 주장은 정확하지 않습니다.

엔진이 UDF 계산 단계 대신 전체 계획을 직렬화하는 이유를 설명하기위한 추가 사항.

내 이해는 현재 제한 사항이 순전히 특정 구현 세부 사항의 결과라는 것입니다. 병렬 처리를 사용하여 함수를 실행할 수없는 근본적인 이유는 없습니다.

특히, T-SQL 스칼라 함수는 별도의 T-SQL 컨텍스트 내에서 실행되므로 올바른 조작, 조정 및 종료 (특히 오류의 경우)가 상당히 복잡합니다.

마찬가지로 테이블 변수는 일반적으로 병렬 읽기 (쓰기는 아님)를 지원하지만 테이블 반환 함수에 의해 노출되는 테이블 변수는 구현 별 이유로 병렬 읽기를 지원할 수 없습니다. 신뢰할만한 답변을 제공하기 위해 소스 코드에 액세스 할 수있는 사람 (및 세부 정보를 공유 할 수있는 자유가있는 사람)이 필요합니다.

병렬 UDF 지원이 요청하기에 적합한 기능입니까?

물론, 충분히 강력한 사례를 만들 수 있다면. 내 자신의 느낌은 관련된 작업이 광범위 할 것이므로 귀하의 제안은 극도로 높은 기준 을 충족해야한다는 것 입니다. 예를 들어, 인라인 스칼라 함수를 제공하기위한 관련 (그리고 훨씬 간단한) 요청 은 큰 지원을 제공하지만 수년간 구현되지 않은 문제를 해결했습니다.


Microsoft 논문을 읽고 싶을 수도 있습니다.

... SQL Server 2017 이후 릴리스에서 Microsoft가 T-SQL 스칼라 함수 성능 문제를 해결하기 위해 취하는 접근법을 간략하게 설명합니다.

Froid의 목표는 개발자가 성능 저하없이 UDF 및 절차의 추상화를 사용할 수 있도록하는 것입니다. Froid는 가능할 때마다 명령형 프로그램을 동등한 관계형 대수 형태로 자동 변환하는 새로운 기술을 사용하여이 목표를 달성합니다. Froid는 명령형 코드 블록을 관계형 표현식으로 모델링하고 Apply 연산자를 사용하여이를 단일 표현식으로 체계적으로 결합하여 쿼리 최적화 프로그램이 효율적인 세트 지향 병렬 쿼리 계획 을 선택할 수 있도록합니다 .

(강조 광산)


인라인 스칼라 T-SQL 함수는 이제 SQL Server 2019에서 구현됩니다 .


11

Paul이 그의 대답에서 올바로 언급했듯이 스칼라 UDF를 병렬 처리를 사용하여 실행할 수없는 근본적인 이유는 없습니다. 그러나 구현 문제와는 별도로 일련의 문제가 발생해야하는 또 다른 이유가 있습니다. 루아 바울이 인용 한 논문이에 대한 자세한 정보를 제공합니다.

논문에서 인용 (섹션 2.3) :

현재 SQL Server는 UDF를 호출하는 쿼리에서 쿼리 내 병렬 처리를 사용하지 않습니다. 이러한 제한을 완화하기 위해 방법을 설계 할 수 있지만 UDF를 호출 할 때마다 적절한 수준의 병렬 처리를 선택하는 등의 추가 문제가 발생합니다.

예를 들어, 그림 1과 같은 다른 SQL 쿼리를 호출하는 UDF를 고려하십시오. 이러한 각 쿼리 자체는 병렬 처리를 사용할 수 있으므로 옵티마이 저는 스레드를 공유하지 않는 한 스레드를 공유하는 방법을 알 수 없습니다. UDF는 각 쿼리의 병렬 처리 수준을 결정합니다 (한 호출에서 다른 호출로 변경 될 수 있음). 중첩 및 재귀 UDF를 사용하면이 문제를 관리하기가 더욱 어려워집니다.

본 문서에 설명 된 Froid의 접근 방식은 병렬 계획뿐만 아니라 UDF 쿼리에 더 많은 이점을 제공합니다. 본질적으로 UDF의 병렬 실행 요청을 가정합니다.

업데이트 : Froid는 이제 SQL Server 2019 미리보기 기능으로 사용할 수 있습니다. 이 기능을 "스칼라 UDF 인라이닝"이라고합니다. 자세한 내용은 https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[공개 : 저는 Froid 논문의 공동 저자입니다.]


아주 좋아요! 내가 UDF를 효과적으로 내부적으로 ITVF로 자동 변환한다는 것을 올바르게 이해하면. 우리는 이것을 몇 번 (선언 / if / else)하고 좋은 혼란을 만들었습니다. 우리는 디버그 "열"도 가지고있었습니다.
crokusek

1
실제로 UDF를 ITVF로 변환하지는 않지만 직감은 정확합니다. SQL 쿼리 수준에서이 작업을 수동으로 수행하는 것은 복잡한 UDF에있어 매우 지저분합니다. 루아는 엉망 :) 피할 관계 대수 나무에이 변환, 수행
KARTHIK

@Karthik 당신은 한 번 봐 걸릴 수 dba.stackexchange.com/questions/202211/...을 . 나는 설명 루아는 경우에 수행하는 것입니다 방법을 알고 정말 싶습니다
로마 Pekar을

@Roman 나는 당신의 질문에 댓글을 달았습니다.
Karthik

1
감사합니다, @Karthik, 당신은 루아 종이에했던 작업과 :-) 스칼라 UDF에의 유용성 향상에 (그리고 그룹의) 노력에
솔로몬 Rutzky을
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.