모든 대가를 아끼지 않고 WHERE 문장에서 SQL Server 스칼라 함수를 사용하지 마십시오!

7125 단어 sql5days5blogposts
이것은 약간의 소개가 필요하다.
우선, 표량 값의 작용을 이해해야 합니다. 이것은 하나의 값을 되돌려줍니다.그것은 INT, 한 사람, 심지어 수백 글자를 포함하는 완전한 NVARCHAR일 수 있지만, 하나의 전체 값만 되돌려주고, 하나의 전체 값은 되돌려주지 않는다.값 세트가 필요하면 테이블 함수를 사용합니다.
둘째, SQL 질의의 특정 순서를 알아야 합니다.이 순서 및 예외 사항에 대한 자세한 내용은 here를 참조하십시오. 그러나 SELECT from WHERE 질의가 있는 경우 작업 순서는 다음과 같습니다.
  • 출처
  • 여기서
  • 선택
  • 즉, SQL Server는 먼저 선택한 테이블에서 가능한 모든 레코드를 검색한 다음 기준을 사용하여 해당 레코드를 필터링한 다음 결과를 표시합니다.
    세 번째도 마지막으로 정보 표량치 함수를 소개하는데 그 중에서 문장은 줄마다 한 번씩 작동한다.
    그들은 소대마다 한 번씩 일한다.이런 생각을 사람들의 마음속에 깊이 파고들어 그 뜻을 이해하게 하다.
    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에서 보았는데, 그것은 새로운 이전 프로젝트의 대부분 저장 과정을 파괴했다.그것은 당신의 프로젝트 중 일부를 파괴할 수도 있고, 그렇지 않을 수도 있지만, 주의하십시오. 그것은 일을 엉망으로 만들 수도 있습니다.

    요약
  • WHERE 문의 스칼라 값 함수는 성능에 큰 영향을 미칩니다
  • 이 함수들을 수동으로 쉽게 연결하거나 이 함수들이 처리하는 데이터의 양을 제한함으로써 문제를 최소화할 수 있습니다
  • SQL Server 2019에서 UDF 인라인 연결을 시도할 수 있지만 데이터베이스의 모든 저장 프로세스를 파괴할 수 있습니다.
  • SQL Server에서 스칼라 함수를 사용한 경험이 있습니까?당신은 그것을 최적화시킬 어떤 방법이 있습니까?댓글 공유해주세요!

    좋은 웹페이지 즐겨찾기