#sql-server
#sql-server
Вопрос:
У меня есть 3 представления:
View1
ID, A1, A2, A3, A4, ..., Ax
View2
ID, B1, B2, B3, B4, ..., By
View3
ID, C1, C2, C3, C4, ..., Cz
У меня также есть временная таблица, содержащая список значений идентификаторов, которые меня интересуют. Если я выполняю запрос между любым представлением и выполняю внутреннее объединение с моей таблицей значений идентификаторов, результаты возвращаются почти сразу.
select ViewX.*
from #Ids
inner join ViewX on ViewX.ID = #IDs.ID
Однако, если я выполняю комбинацию любых 2 представлений и внутреннего соединения с временной таблицей, то результаты могут занять гораздо больше времени (15-25 секунд).
select ViewX.*, ViewY.*
from #IDs
inner join ViewX on ViewX.ID = #IDs.ID
inner join ViewY on ViewY.ID = #IDs.ID
Итак, вопрос из двух частей: почему объединение более одного представления занимает намного больше времени и как исправить, чтобы сделать его более эффективным?
Некоторая дополнительная справочная информация; Столбцы View2 и View3 являются вложенными запросами, простое создание нового представления со всеми столбцами из каждого представления становится еще менее эффективным, чем сейчас.
Спасибо
Я работал над проблемой и свел ее к одной части. Вот запрос.
select
VPayersOrderTracking.*,
(
select
count(todsdMRID.TOrderDetailsStatusDocumentsId)
from #orderDetailsReturn as odrMRID
inner join TOrderDetailsStatus as todsMRID on todsMRID.TOrderDetailsId = odrMRID.TOrderDetailsId
inner join TOrderDetailsStatusDocuments as todsdMRID on todsdMRID.TOrderDetailsStatusDocumentsId = todsMRID.TOrderDetailsStatusId
inner join LDocumentTypes as ldtMRID on ldtMRID.LDocumentTypesId = todsdMRID.LDocumentTypesId
where odrMRID.TOrderDetailsId = odr.TOrderDetailsId and ldtMRID.IsReportTypeDocument = 1
) as MedicalReportsIncludingDelectedCount,
from #orderDetailsReturn as odr
inner join VPayersOrderTracking on odr.TOrderDetailsId = VPayersOrderTracking.TOrderDetailsId
inner join VProvidersTrackingDocuments on VProvidersTrackingDocuments.TOrderDetailsId = odr.TOrderDetailsId
order by
VPayersOrderTracking.TOrderHeadersId desc, VPayersOrderTracking.SequenceNumber
Если я выполняю этот запрос без вложенного запроса, он возвращает все записи менее чем за 1 секунду. Если я включу запрос, потребуется около 10 секунд, чтобы вернуть то же количество строк. Обычно таких подзапросов было бы 4, что, конечно, пропорционально увеличивает время.
Комментарии:
1. Единственный способ ответить на ваш вопрос — просмотреть ваш план выполнения. Это зависит от вашей настройки, не связанной с упомянутой вами комбинацией временных таблиц представлений. Компонент database Engine создает план выполнения с учетом всего запроса, а представления встроены, т.Е. Представление SQL объединяется в полный запрос. Таким образом, разные комбинации представлений приведут к совершенно разным планам выполнения. Google вставьте план.
Ответ №1:
Возможно, было бы лучше, если бы вы переписали это представление как Inline Table-Valued Function
— по сути, это представление с параметрами.
В таком случае вы сможете сначала отфильтровать данные. Например, если вы извлекаете идентификаторы для определенного объекта (страны, языка, бренда и т.д.), Вы сможете передать это значение в качестве параметра в представление и вернуть x% строк вместо 100% строк.
Другой способ оптимизации представления — сделать его индексированным представлением, но есть некоторые требования, поскольку одно из них — не иметь вложенных запросов, как у вас.
Если логика представлений сложна и не может быть переписана, вы можете создать эти представления в виде таблиц, используя триггер или хранимую процедуру для материализации результатов.
И отправной точкой будет совместное использование определений представлений и обращение за помощью для их оптимизации.
Комментарии:
1. Я не администратор базы данных, поэтому я немного не в своей тарелке. Однако то, что вы сказали, заставило меня задуматься, и я смог повысить производительность. Это все еще не то, чего бы мне хотелось. Я думаю, вы правы в том, что логика вложенного запроса — это то, где можно получить наибольшую выгоду. Я покажу часть кода вложенного запроса в следующем комментарии.
2. выберите #temp.OrderID, (выберите count(documents.documentsId) из #temp как статус внутреннего соединения T.OrderID = статус. Документы внутреннего объединения OrderID в status.documentsId = documents.documentsId где T.OrderID = #temp.OrderID и documents.status = 1 ) из #temp
3. @tdinpsp я вижу. Это можно сделать без подзапроса, но я предполагаю, что у вас есть другие подобные подзапросы — если вы можете опубликовать всю инструкцию, я могу попытаться упростить ее.
4. Я добавил, где я нахожусь сегодня выше.