У меня довольно большой запрос, который выполняется очень и очень медленно на БД с очень небольшим объемом данных (наибольшее количество строк для таблицы, к которой этот запрос обращается, составляет 8 КБ, и большинство фильтров относятся к идентификаторам со свойствами навигации EF, передан параметр - один единственный идентификатор).
Он шел гладко, но после нескольких изменений (к сожалению, сегодня мы изменили «лот», чтобы преобразовать его в один запрос, пока он не превысил 30 в cs html с отложенной загрузкой и теперь все предварительно загружено в начале файла) теперь он работает в темпе (время ожидания составляет 30 с c и занимает 34). Запуск его в SQL серверной студии управления обеспечивает одно и то же время выполнения (34 се c), выполнение этого несколько раз не ускоряет его, показывает план выполнения, немного ждет, затем запускает его снова и в какой-то момент идет от 34 до 0 секунд.
Мы исключили следующее:
Кэширование выполнения плана запроса ( Как очистить запрос SQL к серверу кэш? ): время выполнения не меняется после сброса планов, как только оно быстро, оно остается быстрым
Результат не кэшируется: изменение guid (которое изменяет значения всего остального) ничего не меняет, раз оно быстро, оно остается быстрым
SQL Проблема с установкой сервера: когда это случилось на моем коллеге P C, я взял последнюю версия и воспроизводит ту же проблему
Проблемы с компьютером: ничего не занимает процессорное время, кроме сервера SQL, больше ничего не открывается, оба компьютера работают нормально и не связаны (не включены тот же ne twork / not on domain et c), что-то, что могло бы повлиять на них обоих отрицательно в одно и то же время, может быть исключено.
Мы в растерянности, потому что отладку действительно сложно «почему» - это медленно начинаться, когда он заканчивается мгновенным выполнением из ниоткуда.
Я не уверен, что этот запрос настолько полезен, поэтому, почему я публикую его в последний раз, я переименовал некоторые таблицы (из T0 T1 и др. c) чтобы было легче читать, но это не так легко переварить. Ниже вы найдете и код C#, использованный для его генерации, и результат SQL, который снова и снова занимает 34 секунды, пока не потребуется 0!
LINQ (ef core latest, 3.1):
Context.Orders
.Where(o => o.UniqueId == new Guid("MY GUID HERE"))
.SelectMany(o => o.Products)
.Where(FranceMontgolfieres.Models.Mappings.ProductOrder.IsTicketExpression)
.Select(po => new
{
po.UniqueId,
ProductId = po.Product.Id,
ProductName = po.Product.Name,
AllPassengerAreRegistered = po.Passengers.All(pa => pa.Passenger != null),
passengers = po.Passengers
.Select(pa => new
{
pa.UniqueId,
IsRegistered = pa.Passenger != null,
pa.Passenger.FirstName,
pa.Passenger.LastName,
FullName = pa.Passenger.FirstName + " " + pa.Passenger.LastName,
HasFlown = pa.Passenger.Manifests
.Any(m => m.History
.Any(h => h.Status == PassengerManifestStatus.Flown)),
HasPendingFlight = pa.Passenger.Manifests
.Any(m => m.History
.Any(h => h.Status == PassengerManifestStatus.Incoming)),
HasPendingReport = pa.Passenger.Manifests
.Any(m => m.History
.Any(h => h.Status == PassengerManifestStatus.Report)),
Manifests = pa.Passenger.Manifests
.Select(m => new
{
manifest = new
{
HasFlown = m.History
.Any(h => h.Status == PassengerManifestStatus.Flown),
HasPendingFlight = m.History
.Any(h => h.Status == PassengerManifestStatus.Incoming),
HasPendingReport = m.History
.Any(h => h.Status == PassengerManifestStatus.Report),
m.Manifest.StartDate,
m.Manifest.FlightBase.Name,
m.Manifest.FlightBase.Location,
m.Manifest.State
},
history = m.History
.Select(h => new
{
h.Date,
h.Status
})
})
}),
PendingReservationExists = po.PendingReservation != null
})
.ToList();
Что мы запускаем перед запросом (по-прежнему занимает 0 se c после), чтобы убедиться, что он не кэшируется:
CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC FREEPROCCACHE;
GO
DBCC FREESYSTEMCACHE("ALL");
GO
DBCC FREESESSIONCACHE;
GO
DBCC FLUSHAUTHCACHE;
GO
SQL Запрос:
SELECT [ProductOrders_p1].[UniqueId],
[Products_p2].[Id],
[TranslatableString_t].[Id],
[TranslatableString_t].[MainPageCompanyDetailId],
[TranslatableString_t].[Text],
CASE
WHEN NOT EXISTS (
SELECT 1
FROM [ProductOrderPassenger] AS [p]
LEFT JOIN [Passengers] AS [p0] ON [p].[Id] = [p0].[ProductOrderPassengerId]
WHERE ([ProductOrders_p1].[Id] = [p].[ProductOrderId]) AND [p0].[Id] IS NULL) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END,
CASE
WHEN [PendingReservations_p3].[Id] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END,
[o].[Id],
[ProductOrders_p1].[Id],
[t3].[UniqueId],
[t3].[c],
[t3].[FirstName],
[t3].[LastName],
[t3].[c0],
[t3].[c1],
[t3].[c2],
[t3].[c3],
[t3].[Id],
[t3].[c4],
[t3].[c00],
[t3].[c10],
[t3].[StartDate],
[t3].[Id0],
[t3].[MainPageCompanyDetailId],
[t3].[Text],
[t3].[Id00],
[t3].[MainPageCompanyDetailId0],
[t3].[Text0],
[t3].[State],
[t3].[ManifestId],
[t3].[PassengerId],
[t3].[Id1],
[t3].[Date],
[t3].[Status],
[t3].[Id2]
FROM [Orders] AS [o]
INNER JOIN [ProductOrders] AS [ProductOrders_p1] ON [o].[Id] = [ProductOrders_p1].[OrderId]
LEFT JOIN [Products] AS [Products_p2] ON [ProductOrders_p1].[ProductId] = [Products_p2].[Id]
LEFT JOIN [TranslatableStrings] AS [TranslatableString_t] ON [Products_p2].[NameId] = [TranslatableString_t].[Id]
LEFT JOIN [PendingReservations] AS [PendingReservations_p3] ON [ProductOrders_p1].[Id] = [PendingReservations_p3].[ProductOrderId]
LEFT JOIN (
SELECT [ProductOrderPassengers_p4].[UniqueId], CASE
WHEN [Passengers_p5].[Id] IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c], [Passengers_p5].[FirstName], [Passengers_p5].[LastName], ([Passengers_p5].[FirstName] + N' ') + [Passengers_p5].[LastName] AS [c0], CASE
WHEN EXISTS (
SELECT 1
FROM [ManifestPassengers] AS [m]
WHERE ([Passengers_p5].[Id] IS NOT NULL AND ([Passengers_p5].[Id] = [m].[PassengerId])) AND EXISTS (
SELECT 1
FROM [ManifestPassengerHistories] AS [m0]
WHERE (([m].[ManifestId] = [m0].[ManifestPassengerManifestId]) AND ([m].[PassengerId] = [m0].[ManifestPassengerPassengerId])) AND ([m0].[Status] = 5))) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c1], CASE
WHEN EXISTS (
SELECT 1
FROM [ManifestPassengers] AS [m1]
WHERE ([Passengers_p5].[Id] IS NOT NULL AND ([Passengers_p5].[Id] = [m1].[PassengerId])) AND EXISTS (
SELECT 1
FROM [ManifestPassengerHistories] AS [m2]
WHERE (([m1].[ManifestId] = [m2].[ManifestPassengerManifestId]) AND ([m1].[PassengerId] = [m2].[ManifestPassengerPassengerId])) AND ([m2].[Status] = 1))) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c2], CASE
WHEN EXISTS (
SELECT 1
FROM [ManifestPassengers] AS [m3]
WHERE ([Passengers_p5].[Id] IS NOT NULL AND ([Passengers_p5].[Id] = [m3].[PassengerId])) AND EXISTS (
SELECT 1
FROM [ManifestPassengerHistories] AS [m4]
WHERE (([m3].[ManifestId] = [m4].[ManifestPassengerManifestId]) AND ([m3].[PassengerId] = [m4].[ManifestPassengerPassengerId])) AND ([m4].[Status] = 2))) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c3], [ProductOrderPassengers_p4].[Id], [t2].[c] AS [c4], [t2].[c0] AS [c00], [t2].[c1] AS [c10], [t2].[StartDate], [t2].[Id] AS [Id0], [t2].[MainPageCompanyDetailId], [t2].[Text], [t2].[Id0] AS [Id00], [t2].[MainPageCompanyDetailId0], [t2].[Text0], [t2].[State], [t2].[ManifestId], [t2].[PassengerId], [t2].[Id1], [t2].[Date], [t2].[Status], [t2].[Id2], [ProductOrderPassengers_p4].[ProductOrderId]
FROM [ProductOrderPassenger] AS [ProductOrderPassengers_p4]
LEFT JOIN [Passengers] AS [Passengers_p5] ON [ProductOrderPassengers_p4].[Id] = [Passengers_p5].[ProductOrderPassengerId]
LEFT JOIN (
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [ManifestPassengerHistories] AS [m5]
WHERE (([m8].[ManifestId] = [m5].[ManifestPassengerManifestId]) AND ([m8].[PassengerId] = [m5].[ManifestPassengerPassengerId])) AND ([m5].[Status] = 5)) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c], CASE
WHEN EXISTS (
SELECT 1
FROM [ManifestPassengerHistories] AS [m6]
WHERE (([m8].[ManifestId] = [m6].[ManifestPassengerManifestId]) AND ([m8].[PassengerId] = [m6].[ManifestPassengerPassengerId])) AND ([m6].[Status] = 1)) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c0], CASE
WHEN EXISTS (
SELECT 1
FROM [ManifestPassengerHistories] AS [m7]
WHERE (([m8].[ManifestId] = [m7].[ManifestPassengerManifestId]) AND ([m8].[PassengerId] = [m7].[ManifestPassengerPassengerId])) AND ([m7].[Status] = 2)) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [c1], [m9].[StartDate], [t0].[Id], [t0].[MainPageCompanyDetailId], [t0].[Text], [t1].[Id] AS [Id0], [t1].[MainPageCompanyDetailId] AS [MainPageCompanyDetailId0], [t1].[Text] AS [Text0], [m9].[State], [m8].[ManifestId], [m8].[PassengerId], [m9].[Id] AS [Id1], [m10].[Date], [m10].[Status], [m10].[Id] AS [Id2]
FROM [ManifestPassengers] AS [m8]
INNER JOIN [Manifests] AS [m9] ON [m8].[ManifestId] = [m9].[Id]
LEFT JOIN [FlightBases] AS [f] ON [m9].[FlightBaseId] = [f].[Id]
LEFT JOIN [TranslatableStrings] AS [t0] ON [f].[NameId] = [t0].[Id]
LEFT JOIN [TranslatableStrings] AS [t1] ON [f].[LocationId] = [t1].[Id]
LEFT JOIN [ManifestPassengerHistories] AS [m10] ON ([m8].[ManifestId] = [m10].[ManifestPassengerManifestId]) AND ([m8].[PassengerId] = [m10].[ManifestPassengerPassengerId])
) AS [t2] ON [Passengers_p5].[Id] = [t2].[PassengerId]
) AS [t3] ON [ProductOrders_p1].[Id] = [t3].[ProductOrderId]
WHERE ([o].[UniqueId] = 'd26013b9-b9bc-4497-b351-544739851d3d') AND EXISTS (
SELECT 1
FROM [ProductProductComponents] AS [p6]
INNER JOIN (
SELECT [p7].[Id], [p7].[DescriptionId], [p7].[Discriminator], [p7].[DisplayDescriptionInProduct], [p7].[FunctionnalName], [p7].[HTPrice], [p7].[IsArchived], [p7].[IsChildrenPrice], [p7].[IsOptionnal], [p7].[IsSelectedInBasketByDefault], [p7].[IsShipping], [p7].[NameId], [p7].[ParentProductComponentId], [p7].[ShowInBasket], [p7].[ShowInInvoice], [p7].[VATRate], [p7].[AllowPartnerBase], [p7].[AllowWeekends], [p7].[ValidForTicks]
FROM [ProductComponents] AS [p7]
WHERE [p7].[Discriminator] IN (N'ProductComponent', N'FlightProductComponent')
) AS [t4] ON [p6].[ProductComponentId] = [t4].[Id]
WHERE ([Products_p2].[Id] IS NOT NULL AND ([Products_p2].[Id] = [p6].[ProductId])) AND ([t4].[Discriminator] = N'FlightProductComponent'))
ORDER BY [o].[Id], [ProductOrders_p1].[Id], [t3].[Id], [t3].[ManifestId], [t3].[PassengerId], [t3].[Id1], [t3].[Id2]