Пожалуйста, потерпите меня - я знаю, что это сложно.
У меня есть таблица с квартирами, а другая - с арендой этих квартир. Моя задача - выбрать из списка «наиболее актуальную» аренду. В общем, это означает самый последний срок аренды, но есть несколько причуд, которые делают его более сложным, чем просто заказ по дате.
Это привело меня к созданию этого общего запроса табличного выражения в представлении, которое я затем СОЕДИНЯЛ со многими другими внутри хранимой процедуры, чтобы получить нужные мне результаты:
WITH TempTable AS (
SELECT l.BuildingID, l.ApartmentID, l.LeaseID, l.ApplicantID,
ROW_NUMBER() OVER (PARTITION BY l.ApartmentID ORDER BY s.Importance DESC, MovedOut, MovedIN DESC, LLSigned DESC, Approved DESC, Applied DESC) AS 'RowNumber'
FROM dbo.NPleaseapplicant AS l INNER JOIN
dbo.NPappstatus AS s ON l.BuildingID = s.BuildingID AND l.AppStatus = s.Code
)
SELECT BuildingID, ApartmentID, LeaseID, ApplicantID
FROM TempTable
WHERE RowNumber = 1
Это работает и возвращает правильный результат. Проблема, с которой я сталкиваюсь, заключается в очень низкой производительности.
В качестве теста я создал временную таблицу внутри хранимой процедуры вместо использования View, и получил намного, гораздо лучшую производительность:
CREATE TABLE #Relevant (
BuildingID int,
ApartmentID int,
LeaseID int,
ApplicantID int,
RowNumber int
)
INSERT INTO #Relevant (BuildingID, ApartmentID, LeaseID, ApplicantID, RowNumber)
SELECT l.BuildingID, l.ApartmentID, l.LeaseID, l.ApplicantID,
ROW_NUMBER() OVER (PARTITION BY l.ApartmentID ORDER BY s.Importance DESC, MovedOut, MovedIN DESC, LLSigned DESC, Approved DESC, Applied DESC) AS 'RowNumber'
FROM dbo.NPleaseapplicant AS l INNER JOIN
dbo.NPappstatus AS s ON l.BuildingID = s.BuildingID AND l.AppStatus = s.Code
WHERE (l.BuildingID = @BuildingID)
DROP TABLE #Relevant
На первый взгляд это не значит для меня. Я слышал, что временные таблицы, как известно, плохо влияют на производительность. Проблема заключается в том, что я могу лучше ограничить запрос в таблице Temp с помощью предложения WHERE, чего нет в представлении. С более чем 10000 аренды в 16 зданиях в таблице, возможность фильтрации с ГДЕ может отбрасывать строки, затронутые 90% - 95%.
Имея все это в виду, есть что-то яркое, что я здесь скучаю? Я делаю что-то не так с представлением, которое может вызвать ужасную производительность, или это просто вопрос меньшего набора результатов в таблице временных параметров, превосходящего неограниченный набор результатов в CTE?
РЕДАКТИРОВАТЬ: Я должен добавить, что эта бизнес-логика выбора "наиболее подходящего аренды" является ключом ко многим отчетам в системе. Вот почему он был помещен в View для начала. Представление дает нам возможность «Один раз написать, использовать много», тогда как временная таблица в хранимой процедуре должна быть воссоздана для каждого другого хранимого процесса в системе. Некрасиво.
РЕДАКТИРОВАТЬ # 2: Могу ли я использовать табличную функцию вместо представления? Позволит ли это мне ограничить число строк, затронутых заранее, и по-прежнему использовать полученный набор данных в JOIN с другими таблицами? Если это работает - и имеет приличную производительность - это позволило бы мне хранить бизнес-логику в одном месте (функцию) вместо дублирования ее в десятках хранимых процедур.