繁体   English   中英

SQL查询性能优化

[英]SQL Query Performance Optimization

我有以下SQL,它返回349017条记录。 记录数量每天都会增加。

目前,我使用分页仅显示12条记录。 每12条记录返回大约2到3秒。 如何将查询优化为0秒? 请给出任何解决方案/建议。

我有很多图像数据将在应用程序中显示。 用户滚动时,必须根据此查询快速加载图像。

SELECT 
    vInfo.UserId
    ,vInfo.VehicleInfoId
    ,vImage.GuidedTourTemplateId
    ,vImage.VehicleImageId
    ,vInfo.Value AS VehicleName
    ,vInfo.Value AS ImageName
    ,Prop.PropertyId
    ,COALESCE(Loc.LocationName, 'NA') AS VehicleLocation
    ,Prop.PropertyName
    ,vImage.Latitude
    ,vImage.Longitude
    ,vImage.IsMain
    ,CASE 
        WHEN (DATEADD(DAY, tPlan.BackupDays, CAST(vImage.CreatedDate AS DATETIME)) > (GETDATE()))
            THEN 1
        ELSE 0
        END AS IsAccess
    ,vImage.ImageURL
    ,vImage.ThumbImageURL
    ,CASE 
        WHEN vImage.AudioURL <> ''
            THEN 1
        ELSE 0
        END AS IsAudio
    ,vImage.AudioURL
    ,CASE 
        WHEN vImage.Comments <> ''
            THEN 1
        ELSE 0
        END AS IsComment
    ,vImage.Comments
    ,COALESCE(DImage.Damaged, 0) AS IsDamaged
    ,tImage.TotalAdditionalImages
    ,CONVERT(VARCHAR(12), CAST(vInfo.CreatedDate AS DATETIME), 107) AS CreateDate
    ,vInfo.EditDate
    ,0 AS RowNumber
FROM
    [dbo].[VehicleInfo] vInfo
INNER JOIN 
    [dbo].[Property] Prop ON Prop.PropertyId = vInfo.PropertyId
INNER JOIN 
    [dbo].[Location] Loc ON Loc.LocationId = vInfo.LocationId
INNER JOIN 
    [dbo].[VehicleImage] vImage ON vInfo.VehicleInfoId = vImage.VehicleInfoId
INNER JOIN 
    [dbo].[PropertyPlan] tPropPlan ON vImage.PropertyId = tPropPlan.PropertyId
INNER JOIN 
    [dbo].[PlanType] tPlan ON tPropPlan.PlanTypeId = tPlan.PlanTypeId
OUTER APPLY 
    (SELECT COUNT(VehicleInfoId) AS TotalAdditionalImages
     FROM [dbo].[VehicleImage]
     WHERE VehicleInfoId = vInfo.VehicleInfoId) tImage
OUTER APPLY 
    (SELECT 
         CASE 
            WHEN COUNT(VehicleInfoId) > 0
                THEN 1
                ELSE 0
            END AS Damaged
     FROM [dbo].[DamagedVehicleImage]
     WHERE VehicleInfoId = vInfo.VehicleInfoId) DImage
WHERE 
    vInfo.TenantId = '72c79d03-6692-4813-8c5a-4649cb34ca2f'
    AND Prop.DeleteStatus = 0
    AND vImage.IsMain = 1
ORDER BY 
    CAST(vInfo.CreatedDate AS DATETIME) DESC
    ,Prop.PropertyName
OFFSET 0 ROWS
FETCH NEXT 12 ROWS ONLY

执行计划

在此处输入图片说明

没有模式和示例数据,这只是一个猜测,但是看起来

ORDER BY 
    CAST(vInfo.CreatedDate AS DATETIME) DESC

是最大的时间浪费。

理想情况下,您不会将日期存储为datetime以外的其他内容-我猜您将需要在更多位置对createdData进行排序。

如果您不能修改数据类型,则可以创建基于函数的索引来减轻CAST操作的负担(今天几乎可以肯定没有对它进行索引)。

解决方案非常简单-您应该将vInfo.CreatedDate作为索引DATETIME列。

如果由于某种原因无法修改列类型,则可以创建一个PERSISTENT计算列 ,然后在其上定义一个索引。

例:

ALTER TABLE dbo.vInfo 
ADD _CreatedDateAsDateTime AS CONVERT(DATETIME, CreatedDate) PERSISTED;

CREATE INDEX [IX_...] ON dbo.vInfo(_CreatedDateAsDateTime) INCLUDE(...);
ALTER TABLE dbo.VehicleInfo
    ADD CreatedDate2 AS CONVERT(DATETIME, CreatedDate)
GO

CREATE UNIQUE NONCLUSTERED INDEX ix
ON dbo.VehicleInfo (CreatedDate2 DESC, PropertyId, TenantId)
    --INCLUDE (UserId, VehicleInfoId, Value, LocationId, EditDate)
    --WHERE TenantId = '72c79d03-6692-4813-8c5a-4649cb34ca2f'
GO


SELECT 
      vInfo.UserId
    , vInfo.VehicleInfoId
    , vImage.GuidedTourTemplateId
    , vImage.VehicleImageId
    , VehicleName = vInfo.Value
    , ImageName = vInfo.Value
    , Prop.PropertyId
    , VehicleLocation = ISNULL(Loc.LocationName, 'NA')
    , Prop.PropertyName
    , vImage.Latitude
    , vImage.Longitude
    , vImage.IsMain
    , IsAccess = IIF(DATEADD(DAY, tPlan.BackupDays, CAST(vImage.CreatedDate AS DATETIME)) > GETDATE(), 1, 0)
    , vImage.ImageURL
    , vImage.ThumbImageURL
    , IsAudio = IIF(vImage.AudioURL <> '', 1, 0)
    , vImage.AudioURL
    , IsComment = IIF(vImage.Comments <> '', 1, 0)
    , vImage.Comments
    , IsDamaged =
        CASE WHEN
             EXISTS(
                 SELECT 1
                 FROM DamagedVehicleImage i2
                 WHERE i2.VehicleInfoId = vInfo.VehicleInfoId
             )
            THEN 1
            ELSE 0
        END
    , TotalAdditionalImages = COUNT(vImage.VehicleInfoId) OVER (PARTITION BY vImage.VehicleInfoId)
    , CONVERT(VARCHAR(12), CreatedDate2, 107) AS CreateDate
    , vInfo.EditDate
    , 0 AS RowNumber
FROM dbo.VehicleInfo vInfo
JOIN dbo.Property Prop ON Prop.PropertyId = vInfo.PropertyId
JOIN dbo.Location Loc ON Loc.LocationId = vInfo.LocationId
JOIN dbo.VehicleImage vImage ON vInfo.VehicleInfoId = vImage.VehicleInfoId
JOIN dbo.PropertyPlan tPropPlan ON vImage.PropertyId = tPropPlan.PropertyId
JOIN dbo.PlanType tPlan ON tPropPlan.PlanTypeId = tPlan.PlanTypeId
WHERE vInfo.TenantId = '72c79d03-6692-4813-8c5a-4649cb34ca2f'
    AND Prop.DeleteStatus = 0
    AND vImage.IsMain = 1
ORDER BY
      CreatedDate2 DESC
    , Prop.PropertyName
OFFSET 0 ROWS FETCH NEXT 12 ROWS ONLY

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM