首页 > 解决方案 > 视图性能问题中的计算列

问题描述

我有一个存储为地理类型的位置数据(Lat/Lngs)的表。

现在这个位置数据代表了一个旅程,所以我想计算旅程中行驶的距离,每天的距离和每月的距离。因此,为此我需要一个属性来计算与旅程中下一个位置的距离。

如果我使用带有窗口函数的表中的 Select 来执行此操作,则性能非常好,并且执行计划似乎很好。执行计划

这是查询 -

Select
    iVehicleMonitoringId,
    iAssetId,
    iDriverId,
    dtUtcDatetime,
    sptGeoLocaitonPoint,
    fAngel,
    sDirection,
    fSpeedKPH,
    eEventCode,
    fDistanceTravelled = sptGeoLocaitonPoint.STDistance(LEAD(sptGeoLocaitonPoint) OVER(PARTITION BY iAssetId ORDER BY dtUTCDateTime)),
    eIgnition,
    eDoor,
    eSeatbelt,
    eIgnition2,
    sAddress
From dbo.VehicleMonitoringLog

Where iAssetId = 1
    AND dtUTCDateTime BETWEEN N'2017-12-27' AND N'2017-12-27 23:59:59.997'

现在因为我的代码中需要这个距离计算属性。我决定使用该fDistanceTravelled属性创建一个 SQL 视图。

CREATE VIEW [dbo].[TB5_xPT_VehicleMonitoringLogs]
AS
    Select
        iVehicleMonitoringId = ISNULL(iVehicleMonitoringId, -1),
        iAssetId,
        iDriverId,
        dtUtcDatetime,
        sptGeoLocaitonPoint,
        fAngel,
        sDirection,
        fSpeedKPH,
        eEventCode,
        fDistanceTravelled = sptGeoLocaitonPoint.STDistance(LEAD(sptGeoLocaitonPoint) OVER(PARTITION BY iAssetId ORDER BY dtUTCDateTime)),
        eIgnition,
        eDoor,
        eSeatbelt,
        eIgnition2,
        sAddress
    From dbo.VehicleMonitoringLog
GO

但是当我将此视图导入到我的实体框架中时,它会超时。所以我检查了执行计划,它与从表中选择的不匹配。 查看执行计划

这是查询 -

Select
    *
From TB5_xPT_VehicleMonitoringLogs
Where iAssetId = 1
    AND dtUTCDateTime BETWEEN N'2017-12-27' AND N'2017-12-27 23:59:59.997'

要在代码中执行此操作,我需要遍历列表中的所有位置日志。

DbGeography prevPoint = null;
foreach (var historyLog in historyLogs)
{
    var distanceFromPrevPoint = 0.0;
    if (prevPoint != null)
    {
        var distance = prevPoint.Distance(historyLog.sptGeoLocaitonPoint);
        if (distance != null)
            distanceFromPrevPoint = Math.Round(((double)distance * .001), 2);
    }

    var locationLog = Mapper.Map<LocationLogDTO>(historyLog);

    locationLog.DistanceTravelled = distanceFromPrevPoint;

    prevPoint = historyLog.sptGeoLocaitonPoint;

    historyDto.LocationLogs.Add(locationLog);
}

我不想这样做。我需要一种更好的方法来做到这一点。

编辑

图片解释fDistanceTravelled列计算。

在此处输入图像描述

标签: c#sqlentity-frameworksql-server-2016

解决方案


推荐阅读