При профилировании базы данных я столкнулся с представлением, которое ссылается на некоторые недетерминированные функции, к которым обращаются 1000-2500 раз в минуту для каждого соединения в пуле этого приложения. Простое SELECTпредставление дает следующий план выполнения:
Это выглядит как сложный план для представления, в котором менее тысячи строк, в которых один или два ряда могут меняться каждые несколько месяцев. Но это ухудшается со следующими другими соблюдениями:
- Вложенные представления являются недетерминированными, поэтому мы не можем их индексировать
- Каждое представление ссылается на несколько
UDFs для построения строк - Каждый UDF содержит вложенные
UDFs для получения ISO-кодов для локализованных языков. - Представления в стеке используют дополнительные строители строк, возвращаемые из
UDFs в качествеJOINпредикатов - Каждый стек представлений обрабатывается как таблица, что означает наличие
INSERT/UPDATE/DELETEтриггеров на каждом для записи в базовые таблицы - Эти триггеры взглядов использовать ,
CURSORSчтоEXECхранимые процедуры , которые ссылаются на более из этих строк зданияUDFs.
Мне это кажется довольно гнилым, но у меня всего несколько лет опыта работы с 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-1400 мс для выполнения. Если я помещаю строки в другую таблицу и добавляю к ней индекс, тот же выбор возвращается через 20-75 мс.
Итак, короткая история (и я надеюсь, что вы оценили эту глупость), я хочу быть добрым самаритянином, перепроектировать и переписать это для 99% клиентов, использующих этот продукт, которые вообще не используют какую-либо локализацию. Ожидается, что конечные пользователи будут использовать [en-US]локаль, даже если английский является вторым / третьим языком.
Поскольку это неофициальный взлом, я думаю о следующем:
- Создайте новую таблицу String, заполненную четко объединенным набором данных из исходных базовых таблиц.
- Индексируйте таблицу.
- Создание замены набора представлений верхнего уровня в стеке , которые включают в себя
NVARCHARиINTстолбцах дляWKTypeиWKIndexстолбцов. - Измените несколько
UDFs, которые ссылаются на эти представления, чтобы избежать преобразований типов в некоторых предикатах соединения (наша самая большая таблица аудита - 500-2000M строк и хранитINTвNVARCHAR(4000)столбце, который используется для объединения соWKIndexстолбцом (INT).) - Схема привязки взглядов
- Добавьте несколько индексов к представлениям
- Перестройте триггеры в представлениях, используя заданную логику вместо курсоров.
Теперь мои актуальные вопросы:
- Есть ли лучший метод для обработки локализованных строк через представление?
- Какие существуют альтернативы для использования
UDFв качестве заглушки? (Я могу написать конкретныйVIEWдля каждого владельца схемы и жестко закодировать язык, не полагаясь на различныеUDFзаглушки.) - Можно ли просто сделать эти представления детерминированными, полностью квалифицируя вложенные
UDFs и затем связывая схемы стеками представления?




UDFопределение. Также обратитесь к пользовательским функциям T-SQL: хорошее, плохое и безобразное