按极端性能影响排序

问题描述 投票:0回答:1

我在 SQL Server 中有一个复杂的查询,需要 70 秒才能完成 3,000,000 条记录。
当我删除两个

ORDER BY
子句时,只需要 0.5 秒即可完成。

SELECT TOP 100
    ROW_NUMBER() OVER ( ORDER BY format([DetectionDateTime],'yyyy/MM/dd') DESC , [DetectionTime] DESC) AS RowId,
    *
FROM (
    SELECT
        dbo.tblValidDetections.Id,
        dbo.tblCameras.CameraName, 
        TRY_CAST((TRY_CAST(dbo.tblValidDetections.DetectionDate as varchar)
            +  ' '
            + TRY_CAST(dbo.tblValidDetections.DetectionTime As varchar)) as datetime)
            as DetectionDateTime, 
        format(dbo.tblValidDetections.DetectionDate, 'yyyy/MM/dd', 'fa') AS DetectionDatePersian,
        dbo.tblValidDetections.DetectionTime,
        TRY_CAST(dbo.tblValidDetections.DetectionTime as varchar) AS DetectionTimeAsString,
        dbo.tblValidDetections.PelakCitySection,
        dbo.tblValidDetections.PelakRightSection,
        dbo.tblValidDetections.PelakAlphabetSection, 
        dbo.tblValidDetections.PelakLeftSection, 
        dbo.tblValidDetections.PelakCitySection + N' - ' + 
            dbo.tblValidDetections.PelakRightSection + N' ' + 
            dbo.tblValidDetections.PelakAlphabetSection + N' ' + 
            dbo.tblValidDetections.PelakLeftSection
            AS Pelak, 
        CASE
            WHEN dbo.tblValidDetections.Direction = 1 THEN N'In'
            WHEN dbo.tblValidDetections.Direction = 0 THEN N'Out'
            ELSE N'N/A'
            END AS CarDirection,
        dbo.__tbl_base_PelakTypesFarsi.pelakType, 
        dbo.__tbl_base_ProvinceList.ProvinceName, 
        dbo.__tbl_base_CityList.CityName
    FROM dbo.tblValidDetections 
    INNER JOIN dbo.tblCameras 
        ON dbo.tblValidDetections.DetectionCameraId = dbo.tblCameras.Id 
    INNER JOIN dbo.__tbl_base_PelakTypesFarsi 
        ON dbo.tblValidDetections.PelakTypeId = dbo.__tbl_base_PelakTypesFarsi.Id 
    LEFT OUTER JOIN dbo.__tbl_base_CityList 
        ON dbo.tblValidDetections.CityId = dbo.__tbl_base_CityList.Id 
    LEFT OUTER JOIN dbo.__tbl_base_ProvinceList 
        ON dbo.tblValidDetections.ProvinceId = dbo.__tbl_base_ProvinceList.Id
        AND dbo.__tbl_base_CityList.ProvinceId = dbo.__tbl_base_ProvinceList.Id
) As DetectionView  
ORDER BY
    format([DetectionDateTime],'yyyy/MM/dd') DESC,
    [DetectionTime] DESC

我已将

DetectionDate
转换为
fa
文化以获取波斯日历日期,我认为这与此处的性能无关。

sql sql-server performance sql-order-by sqlperformance
1个回答
1
投票

正如其他人所说,主要问题是您在

ORDER BY
子句中使用了计算值 - 无论是对于主查询还是在
ROW_NUMBER()
计算中。这消除了 SQL Server 可以使用索引有效地将查询结果限制为最近 100 行或计算
ROW_NUMBER()
仅针对这些行

因此,首先要做的就是在两个地方用直接列引用替换这些

ORDER BY
表达式 -
ORDER BY DetectionDate DESC, DetectionTime DESC
。您还需要确保
tblValidDetections(DetectionDate, DetectionTime)
上有适当的索引,或者以这两列开头的索引。

据我所知,不再需要子选择,因此可以将其消除。

最后,为了减少混乱并提高可读性,定义表别名并使用它们来限定所有列引用是一种很好的做法。

结果会是这样的:

SELECT TOP 100
    ROW_NUMBER() OVER (ORDER BY VD.DetectionDate DESC, VD.DetectionTime DESC) AS RowId,
    VD.Id,
    C.CameraName, 
    TRY_CAST((TRY_CAST(VD.DetectionDate as varchar)
        +  ' '
        + TRY_CAST(VD.DetectionTime As varchar)) as datetime)
        as DetectionDateTime, 
    format(VD.DetectionDate, 'yyyy/MM/dd', 'fa') AS DetectionDatePersian,
    VD.DetectionTime,
    TRY_CAST(VD.DetectionTime as varchar) AS DetectionTimeAsString,
    VD.PelakCitySection,
    VD.PelakRightSection,
    VD.PelakAlphabetSection, 
    VD.PelakLeftSection, 
    VD.PelakCitySection + N' - ' + 
        VD.PelakRightSection + N' ' + 
        VD.PelakAlphabetSection + N' ' + 
        VD.PelakLeftSection
        AS Pelak, 
    CASE
        WHEN VD.Direction = 1 THEN N'In'
        WHEN VD.Direction = 0 THEN N'Out'
        ELSE N'N/A'
        END AS CarDirection,
    PTF.pelakType, 
    PL.ProvinceName, 
    CL.CityName
FROM dbo.tblValidDetections VD
INNER JOIN dbo.tblCameras C
    ON VD.DetectionCameraId = C.Id 
INNER JOIN dbo.__tbl_base_PelakTypesFarsi PTF
    ON VD.PelakTypeId = PTF.Id 
LEFT OUTER JOIN dbo.__tbl_base_CityList CL
    ON VD.CityId = CL.Id 
LEFT OUTER JOIN dbo.__tbl_base_ProvinceList PL
    ON VD.ProvinceId = PL.Id
    AND CL.ProvinceId = PL.Id
ORDER BY VD.DetectionDate DESC, VD.DetectionTime DESC
© www.soinside.com 2019 - 2024. All rights reserved.