Профілюючи базу даних, я натрапив на думку, яка посилається на деякі недетерміновані функції, які отримують доступ 1000-2500 разів на хвилину за кожне з'єднання в пулі цього додатка. Простий SELECT
з виду дає такий план виконання:
Це здається складним планом для подання, що містить менше тисячі рядків, у яких може з’являтися зміна ряду чи двох кожні кілька місяців. Але це погіршується при наступних спостереженнях:
- Вкладені представлення не детерміновані, тому ми не можемо їх індексувати
- Кожен перегляд посилається на декілька
UDF
s для створення рядків - Кожен UDF містить вкладені
UDF
s для отримання ISO-кодів для локалізованих мов - Перегляди в стеку використовують додаткові конструктори рядків, повернені з
UDF
s якJOIN
предикати - Кожен стек вид розглядаються як таблиці, а це означає , що є
INSERT
/UPDATE
/DELETE
тригера на кожному для запису в базових таблиці - Ці тригери для представлень використовують
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
Ось чому UDF
s використовується як JOIN
предикати. I18NID
Колона формується шляхом конкатенації:STRING + [ + ID + | + ID + ]
Під час тестування їх простий SELECT
з представлення повертає ~ 309 рядків і займає 900-1400 мс для виконання. Якщо я скидаю рядки в іншу таблицю і плескаю по ній індекс, той самий вибір повертається через 20-75 мс.
Отже, коротке оповідання (і я сподіваюся, що ви оцінили деяку цю глупоту), я хочу бути хорошим самарянином і переробляти та переробляти це для 99% клієнтів, які керують цим продуктом, які взагалі не використовують локалізацію - - Очікується, що користувачі користуватимуться [en-US]
мовою навіть тоді, коли англійська мова є другою та третьою мовами.
Оскільки це неофіційний злом, я думаю про наступне:
- Створіть нову таблицю String, заповнену чітко з’єднаним набором даних із вихідних базових таблиць
- Індексуйте таблицю.
- Створення заміни набору уявлень верхнього рівня в стеці , які включають в себе
NVARCHAR
іINT
шпальтахWKType
іWKIndex
стовпців. - Зміна декількох
UDF
секунд , які посилаються на ці погляди на перетворення типів уникнути в деяких предиката (наша найбільша таблиця аудиту 500-2,000M рядки і зберігаєINT
вNVARCHAR(4000)
колонці , яка використовується для з'єднання з відношенню доWKIndex
колонку (INT
).) - Схематично зв’яжіть погляди
- Додайте кілька покажчиків до переглядів
- Перебудуйте тригери на подання, використовуючи задану логіку замість курсорів
Тепер мої актуальні запитання:
- Чи є найкращий метод для обробки локалізованих рядків за допомогою перегляду?
- Які існують альтернативи для використання
UDF
заглушки? (Я можу написати конкретнийVIEW
для кожного власника схеми і жорсткого коду мови замість того, щоб покладатися на різніUDF
заглушки.) - Чи можна просто зробити ці погляди детермінованими, повністю визначивши вкладені
UDF
s, а потім схематично пов'язати стеки перегляду?
UDF
визначення. Також зверніться до визначених користувачем функцій T-SQL: доброго, поганого та потворного