SQL Server-중첩 된 비 결정적 뷰 스택에서 문자열 지역화 처리


20

데이터베이스 프로파일 동안 나는 액세스 얻을 약간의 비 결정적 함수를 참조하는 뷰 건너 온 분당 1000-2500 번 에 대한 이 응용 프로그램의 풀에서 연결을. SELECT보기에서 단순 하면 다음과 같은 실행 계획이 생성됩니다.

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

이는 몇 개월마다 한두 행씩 바뀌는 행이 수천 개 미만인 뷰에 대한 복잡한 계획처럼 보입니다. 그러나 다음과 같은 다른 준수로 인해 악화됩니다.

  1. 중첩 된 뷰는 비 결정적이므로 인덱스 할 수 없습니다.
  2. 각 뷰는 여러 UDF개의을 참조 하여 문자열을 만듭니다.
  3. 각 UDF에는 UDF현지화 된 언어에 대한 ISO 코드를 얻기 위해 중첩 된 s가 포함되어 있습니다.
  4. 스택의 뷰는 s 에서 리턴 된 추가 문자열 빌더 UDFJOIN술부로 사용합니다.
  5. 각 뷰 스택이 있다는 것을 의미하는 테이블로 취급 INSERT/ UPDATE/ DELETE기본 테이블에 기입하는 각 트리거
  6. 뷰의 이러한 트리거 는 이러한 문자열 작성을 더 참조 CURSORS하는 EXEC저장 프로 시저를 사용 합니다 UDF.

이것은 나에게 썩은 것처럼 보이지만 TSQL에 대한 경험은 몇 년 밖에 없습니다. 나아진다!

이것이 좋은 아이디어라고 결정한 개발자는이 모든 것을 수행하여 저장된 수백 개의 문자열 UDF이 스키마별로 반환 된 문자열을 기반으로 번역 할 수 있도록했습니다 .

스택의 뷰 중 하나는 다음과 같습니다.

CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType, b.WKIndex
    , CASE
       WHEN ISNULL(il.I18NID, N'') = N''
       THEN id.I18NString
       ELSE il.I18nString
       END AS WKString
    ,CASE
       WHEN ISNULL(il.I18NID, N'') = N''
       THEN id.IETFLangCode
       ELSE il.IETFLangCode
       END AS IETFLangCode
    ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
    ,dbo.UserI18N_Session_Locale_Key()  AS IETFSessionLangCode
    ,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
FROM   UserWKStringBASE b
LEFT OUTER JOIN User3StringI18N il
ON    (
il.I18NID       = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')
AND il.IETFLangCode = dbo.UserI18N_Session_Locale_Key()
)
LEFT OUTER JOIN User3StringI18N id
ON    (
id.I18NID       = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex,N'WKS')
AND id.IETFLangCode = dbo.UserI18N_Database_Locale_Key()
)
GO

UDFs가 JOIN술어 로 사용되는 이유는 다음과 같습니다 . I18NID칼럼을 연결함으로써 형성된다 :STRING + [ + ID + | + ID + ]

이것들을 테스트하는 동안 SELECT뷰에서 간단한 것은 ~ 309 행을 반환하고 실행하는 데 900-1400ms가 걸립니다. 문자열을 다른 테이블에 덤프하고 인덱스를 때리면 동일한 선택이 20-75ms에 반환됩니다.

그래서, 긴 이야기의 짧은 내가 선한 사마리아인과가되고 싶어요 (나는 당신이 sillyness의 일부를 감사 바랍니다) 재 설계 및 않습니다이 제품을 실행하는 클라이언트의 99 %에 대한 다시 쓰기이 없는 모든 -에서 지역화를 사용 -최종 사용자는 [en-US]영어가 제 2/3 언어 인 경우에도 로케일 을 사용해야합니다 .

이것은 비공식적 인 해킹이므로 다음을 생각하고 있습니다.

  1. 원래 기본 테이블에서 완전히 조인 된 데이터 집합으로 채워진 새 문자열 테이블을 만듭니다.
  2. 테이블을 인덱싱하십시오.
  3. 최상위 스택을 포함 조회수의 여분의 세트 작성 NVARCHARINT용 컬럼 WKTypeWKIndex컬럼.
  4. 소수의 수정 UDF일부 Join 술어 피하기 형식 변환에 이러한 뷰를 참조들 (우리의 가장 큰 감사 테이블은 500-2,000M 행과 저장한다 인 INTA의 NVARCHAR(4000)에 참여하는 데 사용되는 열 WKIndex(열 INT).)
  5. 뷰 스키마 화
  6. 뷰에 몇 가지 인덱스 추가
  7. 커서 대신 세트 로직을 사용하여 뷰에서 트리거를 다시 작성하십시오.

이제 내 실제 질문 :

  1. 뷰를 통해 지역화 된 문자열을 처리하는 가장 좋은 방법이 있습니까?
  2. UDF스텁으로 사용하기위한 대안 은 무엇입니까? ( VIEW각 스키마 소유자마다 고유 한 내용 을 작성 하고 다양한 UDF스텁 에 의존하는 대신 언어를 하드 코딩 할 수 있습니다 .)
  3. 중첩 뷰를 정규화 UDF한 다음 뷰 스택을 스키마 바인딩하여 이러한 뷰를 간단하게 결정 론적으로 만들 수 있습니까 ?

5
Scalar UDF를 인라인 테이블 값 UDF 로 변환하십시오 . UDF정의도 게시하십시오 . 또한 T-SQL 사용자 정의 함수를
Kin Shah

어떤 식 으로든 도움이 되나요? stackoverflow.com/questions/316780/…
stacylaray 2013 년

답변:


1

주어진 코드를 보면 다음과 같이 말할 수 있습니다.

  • 첫째, 이것은 뷰가 아니라 테이블에서 읽는 것이 아니라 UDF를 사용하므로 저장 프로 시저 여야합니다.
  • 둘째, 동일한 열에 대해 UDF를 자주 호출해서는 안됩니다. 여기서는 선택에서 한 번 호출됩니다.

    ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID 

    가입을위한 두 번째 시간

    .IETFLangCode = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')

임시 테이블에서 값을 생성하거나 CTE (공통 테이블 표현식)를 사용하여 조인이 발생하기 전에 먼저 해당 값을 얻을 수 있습니다.

몇 가지 개선 사항을 제공하는 샘플 USP를 생성했습니다.

CREATE PROCEDURE usp_UserWKStringI18N
AS
BEGIN
    -- Do operation using UDF 
    SELECT b.WKType
        ,b.WKIndex
        ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
        ,dbo.UserI18N_Session_Locale_Key() AS IETFSessionLangCode
        ,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
    INTO #tempTable
    FROM UserWKStringBASE b;

    -- Now final Select
    SELECT b.WKType
        ,b.WKIndex
        ,CASE 
            WHEN ISNULL(il.I18NID, N'') = N''
                THEN id.I18NString
            ELSE il.I18nString
            END AS WKString
        ,CASE 
            WHEN ISNULL(il.I18NID, N'') = N''
                THEN id.IETFLangCode
            ELSE il.IETFLangCode
            END AS IETFLangCode
        ,b.I18NID
        ,b.IETFSessionLangCode
        ,b.IETFDatabaseLangCode
    FROM #tempTable b
    LEFT OUTER JOIN User3StringI18N il
        ON il.I18NID = b.I18NID
            AND il.IETFLangCode = b.IETFSessionLangCode
    LEFT OUTER JOIN User3StringI18N id
        ON id.I18NID = b.I18NID
            AND id.IETFLangCode = b.IETFDatabaseLangCode
END

이것을 시도하십시오


안녕하세요, MarmiK 님,이 게시물을 살펴보기 위해 시간을 내 주셔서 감사합니다. 불행히도 뷰 (일련의 중첩 된 뷰)이므로 저장 프로 시저로 옮기는 것은 의문의 여지가 없습니다.
beeks

이 경우 뷰에서 임시 테이블이 권장되지 않으므로 CTE를 뷰에서 사용할 수 있습니다. 또는 임시 테이블의 행은 일부 저장 프로 시저에 의해 생성되어 뷰에서 호출 될 수 있습니다.
MarmiK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.