모든 대가를 아끼지 않고 WHERE 문장에서 SQL Server 스칼라 함수를 사용하지 마십시오!
7125 단어 sql5days5blogposts
우선, 표량 값의 작용을 이해해야 합니다. 이것은 하나의 값을 되돌려줍니다.그것은 INT, 한 사람, 심지어 수백 글자를 포함하는 완전한 NVARCHAR일 수 있지만, 하나의 전체 값만 되돌려주고, 하나의 전체 값은 되돌려주지 않는다.값 세트가 필요하면 테이블 함수를 사용합니다.
둘째, SQL 질의의 특정 순서를 알아야 합니다.이 순서 및 예외 사항에 대한 자세한 내용은 here를 참조하십시오. 그러나 SELECT from WHERE 질의가 있는 경우 작업 순서는 다음과 같습니다.
세 번째도 마지막으로 정보 표량치 함수를 소개하는데 그 중에서 문장은 줄마다 한 번씩 작동한다.
그들은 소대마다 한 번씩 일한다.이런 생각을 사람들의 마음속에 깊이 파고들어 그 뜻을 이해하게 하다.
FROM 문에서 200개의 레코드를 캡처하면 함수가 200번 실행됩니다.만약 그것이 5만 개의 기록을 캡처할 수 있다면, 캡처한 줄마다 함수가 몇 번씩 실행될지.기억해라. 네가 선택한 것이 아니라 가능한 모든 단원이다.
"하지만 내 함수는 1밀리초만 운행했어!"라고 말할 수 있다.너는 심지어 옳을 수도 있다.그러나 500000회는 1밀리초가 500초이기 때문에 8분을 주거나 쓴다.
이 일을 일으키게 합시다.
나의 건의?모든 대가를 아끼지 않고 그것들을 피하다.그러나 WHERE 문에서 스칼라 값 함수를 사용해야 한다면?그게 없으면 못 살 것 같아?예를 들어 사용자가 테이블의 일부 기록만 볼 수 있고 다른 기록은 인터페이스에 나타나지 말아야 하며, 기능은Has permission (사용자 Id, 프로젝트 Id) 의 요구에 부합된다고 가정하십시오.
--Assume that @User_Id is declared eariler, as a procedure argument or variable
SELECT
Item_Id,
Item_Name
Item_Description
FROM
Items
WHERE
Has_Permission(@User_Id, Item_Id) = 1
그리고요?나는 적어도 두 가지 가능한 해결 방안을 확정했다.첫째: 함수 내용을 검색에 내연한다
이것은 결코 직관적이지는 않지만, 만약 당신이 이렇게 한다면, 당신의 기록이 대량으로 처리될 것을 확보할 것이다.
SELECT
Item_Id,
Item_Name
Item_Description
FROM
Items AS I
WHERE
EXISTS
(
SELECT TOP 1 1
FROM
ItemCategoryPermissions AS ICP
JOIN Permissions AS P ON P.Id = ICP.Permission_Id
JOIN UserPermissions AS UP ON UP.Permission_Id = P.Id
WHERE
ICP.Category_Id = I.Category_Id
AND UP.User_Id = @User_Id
)
우리 여기서 잠시 멈추고 이 조회를 분석합시다.검사의 각 항목\u Id에\u 권한이 있는 것은 아닙니다. 항목의 수에 따라 시간이 오래 걸릴 수 있으며 대량 질의에서 각 항목을 한 번에 검사할 수 있습니다.
프로그래밍에서 함수를 사용하는 기본적인 사상인 코드의 중복을 피하기 때문에, 나는 왜 이런 상황을 피해야 하는지 알게 되었다.그러나 SQL에서는 때때로 성능이라는 이름으로 이런 코드를 작성하는 것이 가장 좋다.물론 이것은 구체적인 상황에 달려 있다. 만약 그것이 매일 한 번 실행되는 작업의 일부분이라면, 당신은 성능에 그다지 관심이 없고, 더 좋고 유지보수할 수 있는 코드에 더 관심이 있을 것이다.그러나 사용자를 대상으로 하는 인터페이스에서 저장 프로세스를 직접 실행하고 누군가에게 데이터가 가득한 시계를 보여주면 성능이 가장 큰 일이다. 이것이 바로 사용자가 그것을 실현할 수 있는 방식이다.
둘째, 함수 처리를 통한 기록 수를 최대한 줄인다.
너는 여러 가지 방식으로 이 점을 실현할 수 있지만, 나는 두 가지 주요 방식에 경향이 있다.
우선, 내가 더 좋아하는 것은 공공 표 표현식, 약칭 CTE를 사용하여 이 특정한 검색과 관련된 기록만 얻는 것이다.예를 들어, 검색 창에서 특정 범주의 항목만 찾을 경우 항목 수를 다음과 같이 제한할 수 있습니다.
;WITH ExampleCte AS
(
SELECT
Id,
Name,
Description
FROM
Items
WHERE
Category = @Category_Id
)
SELECT
ID,
Name,
Description
FROM
ExampleCte
WHERE
Has_Permission(@User_Id, Id)
이렇게 하면 Has 권한 함수에 들어간 기록은 특정 종류의 항목에 한정되어 여러 번 호출되지 않습니다.이 검색의 다른 버전은tempdb 테이블을 사용하지만, 이것은 실현과 첫 번째 선택일 뿐입니다.
내 경험에 따르면, 만약 성능이 필요하다면, 첫 번째 선택은 항상 좋다. 왜냐하면 기록을 대량으로 처리하는 것이지, 기록을 하나하나 처리하는 것이 아니기 때문이다.너는 여전히 너의 구체적인 상황에서 가장 좋은 선택이 무엇인지 분석해야 한다.즉, 표량치 함수를 조심해야 한다. 가장 최적화된 코드를 찾으려고 노력하면, 그것들은 일을 엉망으로 만들 수 있기 때문이다.
SQL Server 2019 사용자 정의 함수 인라인
철저히 보기 위해서 나는 이 문제를 이야기해야 한다.
UDF 내연은 무엇입니까?Microsoft는 쿼리의 스칼라 함수로 인한 성능 문제를 제거하기 위해 SQL Server 2019에 이를 추가했습니다.그것은 우리의 해결 방안을 실행해야 한다. 첫째, 함수 체내를 주 조회에 연결하고 전체 과정을 더욱 잘 실행해야 한다.그러나 큰 문제가 하나 있다.
그것은 효과가 매우 적다.
나는 it에서 보았는데, 그것은 새로운 이전 프로젝트의 대부분 저장 과정을 파괴했다.그것은 당신의 프로젝트 중 일부를 파괴할 수도 있고, 그렇지 않을 수도 있지만, 주의하십시오. 그것은 일을 엉망으로 만들 수도 있습니다.
요약
Reference
이 문제에 관하여(모든 대가를 아끼지 않고 WHERE 문장에서 SQL Server 스칼라 함수를 사용하지 마십시오!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hanewali/avoid-scalar-valued-functions-in-where-statements-at-all-cost-4klh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)