База данных: SQL Server 2005
Я использую функцию, которая создает список через запятую, используя функцию COALESCE.
ALTER FUNCTION [dbo].[func_Codes](@CustID int, @GroupID int)
returns varchar(1000) as
BEGIN
DECLARE @List varchar(1000)
SELECT @List = COALESCE(@List + ',', '') + Code
FROM dbo.vw_CustBillingInfo
WHERE dbo.vw_CustBillingInfo.CustID = @CustID
AND dbo.vw_CustBillingInfo.GroupID = @GroupID
RETURN @List
END
Представление, которое он вызывает, использует следующую настройку:
SELECT <columns>
FROM (SELECT <columns>
FROM Customer
INNER JOIN Codes ON dbo.GetRootCode(Customer.Code) = Codes.SpecialCode
OR (IsNumeric(Customer.Code) = 0 AND Substring(Customer.Code,2,3) = Codes.SpecialCode)
UNION
SELECT <columns>
FROM Customer
INNER JOIN Codes ON dbo.GetRootCode(Customer.Code2) = Codes.SpecialCode
OR (IsNumeric(Customer.Code2) = 0 AND Substring(Customer.Code2,2,3) = Codes.SpecialCode)
UNION
<Repeat a few more similar unions>
Скалярная функция dbo.GetRootCode(code)
выполняет некоторые операции с подстрокой над столбцом, чтобы извлечь специальную часть varchar
column.
Если я уберу запрос из представления, я смогу повысить производительность, создав временную таблицу и сохранив значения GetRootCode(Customer.Code), IsNumeric(Customer.Code), Substring(Customer.Code,2,3),
и т. д. для каждого используемого кода.Это не самый лучший подход, но он показывает, что можно провести оптимизацию.Также представление все равно не может использовать временную таблицу.
Вместо функции создания списка, разделенного запятыми, я попробовал вариант xml, который видел несколько мест в сети.
STUFF((
SELECT ','+Code FROM dbo.vw_CustBillingInfo WHERE dbo.vw_CustBillingInfo.CustID = C.CustID AND dbo.vw_CustBillingInfo.GroupID = C.GroupID FOR XML PATH('')
), 1, 1, '')
Однако, хотя это работало, производительность была довольно ужасной.Время выполнения запроса увеличилось на 20–30 секунд
. Это возвращает меня к попыткам оптимизировать представление напрямую для повышения производительности.Статистика ввода-вывода показывает, что первым выбором представления будет:
(20 row(s) affected)
Table 'Worktable'. Scan count 1, logical reads 42920, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customer'. Scan count 1, logical reads 269, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Codes'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Для выполнения требуется более секунды.Добавьте это ко всем объединениям, и затем это представление вызывается дважды по пути выполнения, и время значительно увеличивается.
Я застрял на наилучшем способе оптимизации ВНУТРЕННЕГО СОЕДИНЕНИЯ представления, чтобы увеличитьскорость и уменьшить IO требуется.Любые предложения будут с благодарностью.