2016-04-14 38 views
1

Aşağıdaki SQL var ve 349.017 kayıtları döndürür. Kayıtların sayısı günlük olarak artacaktır. SQL Sorgusu Performansı Optimizasyonu

Şu anda sadece 12 kayıtları görüntülemek için sayfalama kullandı. Her 12 kaydı iade etmek yaklaşık 2 ila 3 saniye sürdü. Sorguyu 0 saniyeye kadar nasıl optimize ederim? Lütfen herhangi bir çözüm/öneri verin.

ben uygulamada gösterilecektir görüntü çok veri var. Kullanıcı kaydırdığında, resimler bu sorguya göre hızlı bir şekilde yüklenmelidir. Bir şema ve örnek veri olmadan

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 

Yürütme planı

enter image description here

+1

Ben tarih ben tam o datetime – StackUser

+0

sıralama yerine '> mohan111

cevap

0

Çözüm gerçekten basittir - Eğer vInfo.CreatedDate olarak endeksli DATETIME sütunu olmalıdır.

sütun türünü değiştirerek nedense mümkün değilse, bir PERSISTENT computed column oluşturduktan sonra, buna bir dizin tanımlayabilirsiniz.

Örnek:

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

CREATE INDEX [IX_...] ON dbo.vInfo(_CreatedDateAsDateTime) INCLUDE(...); 
+0

Cevabınız Ginden için teşekkürler. Cevabınızı ben seçtim. – StackUser

4

, bu sadece bir tahmin, ama

ORDER BY 
    CAST(vInfo.CreatedDate AS DATETIME) DESC 

büyük zaman lavabo gibi görünmektedir.

İdeali, datetime dışındaki bir şey olarak tarihleri ​​saklamak olmaz - Ben daha fazla yerde createdData göre sıralama gerekir tahmin ediyorum.

Veri türünü değiştiremezseniz, CAST işleminizi azaltmak için bir function-based index (hemen hemen dizine alınmamış) oluşturabilirsiniz.

+0

Cevabınız Neville için teşekkürler. Haklısın ama Ginden kesin kodu verdi. oysa ben oy verebilirim. – StackUser

0
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