SQL Server - iç içe deterministik olmayan görünüm yığınlarında dizeleri yerelleştirme işleme


20

Bir veritabanının profilini oluştururken , bu uygulamanın havuzundaki her bağlantı için dakikada 1000-2500 kez erişilen belirleyici olmayan bazı işlevlere gönderme yapan bir görünümle karşılaştım . Görünümden bir basit aşağıdaki yürütme planını verir:SELECT

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin

Bu, birkaç ayda bir veya iki satır görebilecek binden fazla satır içeren bir görünüm için karmaşık bir plan gibi görünüyor. Ancak aşağıdaki diğer gözlemlerle daha da kötüleşir:

  1. İç içe görünümler belirleyici değildir, bu nedenle bunları dizine ekleyemeyiz
  2. Her görünüm UDF, dizeleri oluşturmak için birden fazla s'ye başvurur
  3. Her UDF, UDFyerelleştirilmiş diller için ISO kodlarını almak üzere iç içe geçmiş s içerir
  4. Yığındaki Gösterim ilave kullanan dönen dize güçlendiriciler UDFolarak s JOINyüklemleri
  5. Her görünüm yığını tablo olarak kabul edilir, yani her birinde temel tablolara yazmak için INSERT/ UPDATE/ DELETEtetikleyicileri vardır
  6. Görünümlerde Bu tetikleyiciler kullanan CURSORSbu EXEColan daha bu dizi yapı referans saklı yordamlar UDFs.

Bu benim için oldukça çürük görünüyor, ama TSQL ile sadece birkaç yıllık tecrübem var. Daha da iyi oluyor!

Bunun harika bir fikir olduğuna karar veren geliştirici, tüm bunları yaptı, böylece depolanan birkaç yüz dizenin UDFşemaya özgü bir dizeden dönen bir çeviriye sahip olabileceği anlaşılıyor.

İşte yığındaki görünümlerden biri, ama hepsi aynı derecede kötü:

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

İşte bu yüzden UDFs JOINtahmin olarak kullanılıyor . I18NIDKolon birleştirilmesiyle oluşturulur:STRING + [ + ID + | + ID + ]

Bunları test SELECTederken, görünümden bir basit ~ 309 satır döndürür ve yürütülmesi 900-1400ms alır. Dizeleri başka bir tabloya döküp üzerine bir dizin eklersem, aynı seçim 20-75 ms içinde döner.

Yani, uzun lafın kısası ben bir iyiliksever ve olmak istiyorum (ve ben bu sillyness bazılarını takdir umut) yeniden tasarımı ve do bu ürünü çalıştıran müşterilerin% 99 için yeniden yazma bu değil all herhangi yerelleştirme kullanmak -end kullanıcıların [en-US]İngilizce 2. / 3. dil olsa bile yerel ayarları kullanmaları beklenir .

Bu gayri resmi bir saldırı olduğu için aşağıdakileri düşünüyorum:

  1. Orijinal temel tablolardan temiz bir şekilde birleştirilmiş veri kümesiyle doldurulmuş yeni bir Dize tablosu oluşturun
  2. Tabloyu indeksleyin.
  3. Üst düzey içerir yığınında kez bir yedek kümesi oluşturma NVARCHARve INTsütunların WKTypeve WKIndexsütunlar.
  4. UDFBazı birleşim öngörülerinde tür dönüşümlerini önlemek için bu görünümlere başvuran bir avuç değişiklik yapın (en büyük denetim tablomuz 500-2.000 milyon satırdır ve sütunu ( ) birleştirmek için kullanılan INTbir NVARCHAR(4000)sütunda depolar .)WKIndexINT
  5. Görüşler
  6. Görünümlere birkaç dizin ekleyin
  7. İmleçler yerine set mantığı kullanarak görünümlerdeki tetikleyicileri yeniden oluşturma

Şimdi, asıl sorularım:

  1. Bir görünüm aracılığıyla yerelleştirilmiş dizeleri işlemek için en iyi uygulama yöntemi var mı?
  2. UDFBir saplama olarak kullanmak için hangi alternatifler var ? ( VIEWHer şema sahibi için belirli bir yazı yazabilir ve çeşitli UDFsaplamalara güvenmek yerine dili sabit kodlayabilirim .)
  3. Bu görünümler iç içe UDFgeçmişleri tam olarak niteleyip sonra görünüm yığınlarını şematik olarak belirleyerek basitçe deterministik hale getirilebilir mi?


Bu size herhangi bir şekilde yardımcı oluyor mu? stackoverflow.com/questions/316780/…
stacylaray

Yanıtlar:


1

Verilen koda bakarak şöyle diyebiliriz:

  • Birincisi, bu bir görünüm olmamalı, ancak sadece bir tablodan okumak değil, aynı zamanda UDF'leri kullandığı için saklı bir prosedür olmalıdır.
  • İkinci olarak, UDF aynı sütun için sık sık çağrılmamalıdır. Burada, seçimde bir kez denir

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

    ve katılmak için ikinci kez

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

Geçici bir tabloda değerler üretilebilir veya birleştirme gerçekleşmeden önce bu değerleri ilk etapta almak için bir CTE (Ortak Tablo İfadesi) kullanılabilir.

Bazı iyileştirmeler sağlayacak örnek bir USP oluşturduk:

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

Lütfen bunu dene


Merhaba MarmiK, bu yazıyı incelemek için zaman ayırdığınız için teşekkür ederiz. Bu maalesef bir görünümdür (iç içe görünümlerde bir dizi), bu yüzden onu saklı bir prosedüre taşımak söz konusu değildi.
beeks

Bu durumda Görünüm'de geçici tablolar önerilmediğinden CTE'yi görünümde kullanabiliriz. VEYA geçici tablo satırları bazı saklı yordamlar tarafından oluşturulabilir ve görünümde çağrılabilir.
MarmiK
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.