我的 Linq to SQL 查询速度很慢(2 秒返回 1000 行)
var listReceptacle = await((STTEntities)_unitOfWork.Context).IRTReceptacles
.Include(r => r.Product)
.Include(r => r.IRTEvents)
.Where(r => r.IRTEvents.OrderByDescending(re => re.Timestamp)
.Take(1)
.Any(re => re.IRTEventTypeId == IRTEventType.InternalReceptacleCreated.Id
|| re.IRTEventTypeId == IRTEventType.InternalReceptacleReOpened.Id
|| re.IRTEventTypeId == IRTEventType.InternalReceptacleClosed.Id
|| re.IRTEventTypeId == IRTEventType.InternalReceptacleIsPendingDispatch.Id
)
)
.ToListAsync();
表格如下。
表在这些列上有索引
插座
ID
Barcode
活动
ID
EventTypeID
ReceptacleID
Timestamp
事件类型
ID
Code - must be unique
粘贴箱中的实际执行计划:https://www.brentozar.com/pastetheplan/?id=H1dRIdkN6
SQL 查询的实际执行计划显示排序块的成本为 94%。
这是实际执行计划的摘录(我已将整个计划粘贴在底部)
将鼠标悬停在排序块上会显示
我在事件表中添加了以下索引,但排序块仍然有 94% 的成本。
代码:
CREATE NONCLUSTERED INDEX [IX_IRTEvents_IRTEventTypeId_TimeStamp]
ON [dbo].[IRTEvents] ([IRTEventTypeId] ASC, [TimeStamp] ASC)
CREATE NONCLUSTERED INDEX [IX_IRTEvents_Id_TimeStamp]
ON [dbo].[IRTEvents] ([Id] ASC, [TimeStamp] ASC)
CREATE NONCLUSTERED INDEX [IX_IRTEvents_TimeStamp_2]
ON [dbo].[IRTEvents] ([TimeStamp] DESC)
INCLUDE (IRTEventTypeId)
这是查询(由 Linq 生成)
USE SwiftTrackAndTrace
DECLARE @p__linq__0 INT = 1
DECLARE @p__linq__1 INT = 3
DECLARE @p__linq__2 INT = 2
DECLARE @p__linq__3 INT = 6
SELECT
[Project3].[Id] AS [Id] ,
[Project3].[Barcode] AS [Barcode] ,
[Project3].[AllowedProductId] AS [AllowedProductId] ,
[Project3].[DestinationLocationId] AS [DestinationLocationId] ,
[Project3].[Id1] AS [Id1] ,
[Project3].[ProductGroupId] AS [ProductGroupId] ,
[Project3].[Code] AS [Code] ,
[Project3].[Description] AS [Description] ,
[Project3].[Rowversion] AS [Rowversion] ,
[Project3].[ValidateCheckDigit] AS [ValidateCheckDigit] ,
[Project3].[AllowCustom] AS [AllowCustom] ,
[Project3].[ImportInfo] AS [ImportInfo],
[Project3].[NewItem] AS [NewItem] ,
[Project3].[IsActive] AS [IsActive] ,
[Project3].[C1] AS [C1] ,
[Project3].[Id2] AS [Id2] ,
[Project3].[IRTReceptacleId] AS [IRTReceptacleId] ,
[Project3].[IRTEventTypeId] AS [IRTEventTypeId] ,
[Project3].[TIMESTAMP] AS [TIMESTAMP] ,
[Project3].[LocationId] AS [LocationId]
--[Project3].[UserId] AS [UserId]
FROM
(
SELECT
[Extent1].[Id] AS [Id] ,
[Extent1].[Barcode] AS [Barcode] ,
[Extent1].[AllowedProductId] AS [AllowedProductId] ,
[Extent1].[DestinationLocationId] AS [DestinationLocationId] ,
[Extent2].[Id] AS [Id1] ,
[Extent2].[ProductGroupId] AS [ProductGroupId] ,
[Extent2].[Code] AS [Code] ,
[Extent2].[Description] AS [Description] ,
[Extent2].[Rowversion] AS [Rowversion] ,
[Extent2].[ValidateCheckDigit] AS [ValidateCheckDigit] ,
[Extent2].[AllowCustom] AS [AllowCustom] ,
[Extent2].[ImportInfo] AS [ImportInfo],
[Extent2].[NewItem] AS [NewItem] ,
[Extent2].[IsActive] AS [IsActive] ,
[Extent3].[Id] AS [Id2] ,
[Extent3].[IRTReceptacleId] AS [IRTReceptacleId] ,
[Extent3].[IRTEventTypeId] AS [IRTEventTypeId] ,
[Extent3].[TIMESTAMP] AS [TIMESTAMP] ,
[Extent3].[LocationId] AS [LocationId] ,
--[Extent3].[UserId] AS [UserId]
CASE WHEN ([Extent3].[Id] IS NULL) THEN CAST(NULL AS INT) ELSE 1 END AS [C1]
FROM
[dbo].[IRTReceptacles] AS [Extent1]
LEFT OUTER JOIN
[dbo].[Products] AS [Extent2]
ON
[Extent1].[AllowedProductId] = [Extent2].[Id]
LEFT OUTER JOIN
[dbo].[IRTEvents] AS [Extent3]
ON
[Extent1].[Id] = [Extent3].[IRTReceptacleId]
WHERE
EXISTS
(
SELECT
1 AS [C1]
FROM
(
SELECT
TOP (1) [Project1].[IRTEventTypeId] AS [IRTEventTypeId]
FROM
(
SELECT
[Extent4].[IRTEventTypeId] AS [IRTEventTypeId],
[Extent4].[TIMESTAMP] AS [TIMESTAMP]
FROM
[dbo].[IRTEvents] AS [Extent4]
WHERE
[Extent1].[Id] = [Extent4].[IRTReceptacleId] ) AS [Project1]
ORDER BY
[Project1].[TIMESTAMP] DESC ) AS [Limit1]
WHERE
[Limit1].[IRTEventTypeId] IN (@p__linq__0,
@p__linq__1,
@p__linq__2,
@p__linq__3) ) ) AS [Project3]
ORDER BY
[Project3].[Id] ASC ,
[Project3].[Id1] ASC,
[Project3].[C1] ASC
你最好使用
JOIN
而不是那个复杂的 any
条件:
JOIN
可查询 IRTReceptacle(在 IRTReceptacleId 上)和 IRTEvent(在 IRTReceptacleId 和 Timestamp 上)以检查 IRTEventTypeId 上的条件。