Tsql - выполнение объединения в столбце с разделителями - проблема производительности и оптимизации - PullRequest
0 голосов
/ 11 мая 2011

У меня есть следующий (слегка упрощенный в возвращаемых столбцах) запрос.

select Products.Product, Products.ID, Products.Customers
from Products
where Products.orderCompleteDate is null

В качестве примера будет возвращено

productA  1  Bob
productA  1  Jane
productB  2  John,Dave

Обратите внимание, что клиенты могут быть разделены запятойсписок.То, что я хочу добавить, это столбец «Расположение клиентов», так что выше становится

productA  1  Bob        Ireland
productA  1  Jane       Wales
productB  2  John,Dave  Scotland,England

Я создал функцию ниже, где fn_split возвращает одну строку для каждого элемента с разделителями.

create FUNCTION [dbo].[GetLocations]  (@CustomerNames Varchar(256) )   

RETURNS @TempLocations table (CustomerLocations varchar(256)) AS begin
declare @NameStr varchar(256)  
declare @temp table(singleLoc varchar(256))

insert into @temp
select CustomerLocation.Location from CustomerLocation
INNER JOIN Customers ON Customers.ID = CustomerLocation.ID
INNER JOIN dbo.fn_Split(@CustomerNames,',') split ON split.Item = Customers.Name

SELECT @NameStr = COALESCE(@NameStr + ',', '') + singleLoc 
FROM @temp 

insert into @TempLocations values (@NameStr)
return
end

И применил его к исходному запросу следующим образом

select Products.product, Products.ID, Products.Customers, Locations.CustomerLocations
from Products
OUTER APPLY dbo.GetLocations(Products.Customers,',') AS Locations
where Products.orderCompleteDate is null

Однако это чрезвычайно медленно: запрос занимает ~ 10 секунд для таблицы, содержащей всего 2000 строк (первоначальный запрос выполняется почти мгновенно).Это говорит о том, что запрос не удалось оптимизировать, и он создается построчно.По этой причине я держался подальше от скалярных функций и пытался придерживаться табличных функций.Есть ли явная ошибка в моей логике / коде?

Ответы [ 2 ]

1 голос
/ 11 мая 2011

Обычно я предлагаю создать представление, основанное на ненормализованной таблице, которое выполняет нормализацию, а затем использовать его в качестве основы для любых будущих запросов. К сожалению, я не могу определить PK для вашей текущей таблицы Products, но вы, надеюсь, создадите это представление, используя schemabinding, и, надеюсь, сможете превратить его в индексированное представление (индексация на PK + имя клиента).

Запрос этого представления (с использованием Enterprise Edition или опции NOEXPAND) должен дать вам сопоставимую производительность, как если бы существовала нормализованная таблица.

0 голосов
/ 11 мая 2011

Одним из вариантов будет создание второй таблицы, которая нормализует таблицу продуктов и поддерживает ее синхронизацию с триггерами, которые вызывают функцию разделения при вставке строк.

Плюсы - вы получаете стандартную производительность и простые запросы SQL

Минусы могут привести к потере синхронизации таблиц, если что-то пойдет не так (всегда можно запланировать задание на периодическое восстановление новой таблицы с нуля)

Очевидно, что лучшим ответом было бы изменить дизайн таблицы продуктов, но предположим, что вы не можете возиться с разделенными функциями и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...