-1

我的存儲過程需要大約1分45秒,我該如何優化它?在做插入操作之前,我嘗試了幾項創建臨時表的操作。如何優化太慢的存儲過程?

我有預計執行計劃,但我不知道如何上傳它。

這是我的存儲過程的一部分,這需要更長的時間,查詢成本爲53%。

SELECT Distinct 
    BackupCTE.[InstanceName] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.EnvironmentType = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.EnvironmentType) END AS EnvironmentType 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.InstanceStatus = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.InstanceStatus) END AS [InstanceStatus] 
    ,BackupCTE.[BackupShare] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DatabaseOwner = 0 THEN '-1' 
      WHEN ISNULL(BackupCTE.IsMirroringEnabled,0) = 0 AND BackupCTE.DatabaseOwner NOT IN ('SA') AND BackupCTE.DatabaseStatus = 'Normal' AND BackupCTE.DatabaseReadOnly = 0 
       AND ISNULL(BackupCTE.IsDatabaseSnapshot,0) = 0 THEN '0' 
     ELSE '1' END AS DatabaseOwner 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DBRecoveryModel = 0 THEN '-1' 
      WHEN BackupCTE.DatabaseStatus = 'Normal' AND BackupCTE.DatabaseName NOT IN ('master', 'msdb', 'IHC_DBA','distribution','ReportServerTempDB','NavicareReporting','ReportServer') AND 
       BackupCTE.RecoveryModel NOT IN ('Full','BulkLogged') THEN '0' 
      ELSE '1' 
    END AS [DBRecoveryModel] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.AutoShrink = 0 THEN '-1'    
     ELSE CONVERT(VARCHAR, BackupCTE.[AutoShrink]) END AS [AutoShrink] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.AutoClose = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.[AutoClose]) END AS [AutoClose] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.BackupCompression = 0 THEN '-1' 
      WHEN BackupCTE.[BackupCompression] = 0 THEN '0' 
      Else '1' END AS [BackupCompression] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.XPCmdShell = 0 THEN '-1' 
     WHEN CONVERT(VARCHAR,BackupCTE.[XPCmdShell]) = 0 THEN '1' 
     Else '0' END AS [XPCmdShell] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.EncryptionEnabled = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.[EncryptionEnabled]) END AS [EncryptionEnabled] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.IsIdera = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.[IsIdera]) END AS [IsIdera] 
    ,[HoursRetentionShare] 
    ,[HoursSinceLastFullBackup] 
    ,[HoursSinceLastDiffBackup] 
    ,[HoursSinceLastLogBackup] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.ExceededBkpTimeFrame = 0 THEN '-1' Else BackupCTE.ExceededBkpTimeFrame 
    END AS ExceededBkpTimeFrame 
    ,BackupType 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[Primary] = 0 THEN '-1' Else BackupCTE.[Primary] END AS [Primary] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[Secondary] = 0 THEN '-1' Else BackupCTE.[Secondary] END AS [Secondary] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[LockPages] = 0 THEN '-1' 
     Else CONVERT(varchar,BackupCTE.[LockPages]) END AS [LockPages] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[SADisabled] = 0 THEN '-1' 
     WHEN CONVERT(varchar,BackupCTE.[SADisabled]) = 0 AND BackupCTE.VersionName like 'Microsoft SQL Server 2000 %' THEN '1' 
     ELSE CONVERT(varchar,BackupCTE.[SADisabled]) 
     END AS [SADisabled] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.ServiceAccount = 0 THEN '-1' 
     WHEN StdServiceAccount.IsValid = 1 
        OR BackupCTE.ServiceAccount IN ('CO\lpsqldbadmin','[email protected]')     
      THEN '1' 
      ELSE '0' END AS ServiceAccount 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[ServicePackFlag] = 0 THEN '-1' Else BackupCTE.[ServicePack] END AS [ServicePack] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[MaxMemory] = 0 THEN '-1' Else BackupCTE.[MaxMemory] END AS [MaxMemory] 
    ,[JobName] 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[JobOwner] = 0 THEN '-1' 
     WHEN BackupCTE.JobOwner NOT IN ('SA') AND JobEnabled = 1 AND DELETED IS NULL THEN '0' 
     ELSE '1' END AS JobOwner 
    ,[JobEnabled] 
    ,CASE WHEN BackupCTE.EnvironmentType = 'PROD' AND BackupCTE.[Primary] NOT IN ('Tamie Jensen', 'Chase Mahony','Megna Musapeta','Aaron Uppencamp') THEN '0' 
     WHEN BackupCTE.EnvironmentType = 'STBY' AND BackupCTE.[Primary] NOT IN ('Tamie Jensen', 'Chase Mahony','Megna Musapeta','Aaron Uppencamp') THEN '0' 
     ELSE '1' END AS IsNonPrimary 
    ,CASE WHEN BackupCTE.EnvironmentType = 'PROD' AND BackupCTE.[Secondary] IN ('NONE') THEN '0' 
     WHEN BackupCTE.EnvironmentType = 'STBY' AND BackupCTE.[Secondary] IN ('NONE') THEN '0' 
     ELSE '1' END AS IsNonSecondary 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[MaxMemory] = 0 THEN '-1' 
     WHEN BackupCTE.[MaxMemory]%8 = 0 THEN '1' 
     ELSE '0' END AS FlagMemory 
    ,CASE WHEN BackupCTE.JobName NOT LIKE '%Insure%' 
    THEN 
     CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.MaintenanceJob = 0 THEN '-1' 
       WHEN JobSchMultiplier < 0 THEN '1' --One Time Job. No Need To Flag 
       WHEN DATEDIFF(HH, BackupCTE.JobRunDate, GETDATE()) > 24*JobSchMultiplier THEN '0' 
       ELSE '1'    
     END 
    ELSE '1' END AS MaintenanceJob 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.ServicePackFlag = 0 THEN '-1' 
      WHEN LTRIM(RTRIM(SUBSTRING(PatchingStds.ServicePack,3, LEN(PatchingStds.ServicePack)-2))) > ISNULL(LTRIM(RTRIM(SUBSTRING(InstanceSQLDTl.ServicePack,3, 
       LEN(InstanceSQLDTl.ServicePack)-2))),0) THEN '0' 
     WHEN LTRIM(RTRIM(SUBSTRING(VersionName,CHARINDEX('-',VersionName)+1,abs(CASE WHEN CHARINDEX('(',VersionName) > 0 THEN CHARINDEX('(',VersionName)-CHARINDEX('-',VersionName) ELSE len(VersionName)-CHARINDEX('-',VersionName) end)))) <> LTRIM(RTRIM(PatchingStds.SQLBuild)) THEN '2' 
     ELSE '1' END AS ServicePackFlag 
    ,VersionName 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.SAViolations = 0 THEN '-1' 
     WHEN LoginName Not IN ('CO\DBA Group','CO\DBAdmin') AND SYSAdmin = 1 OR SecurityAdmin = 1 OR ServerAdmin = 1 OR SetupAdmin = 1 OR ProcessAdmin = 1 OR DiskAdmin = 1 
                  OR DBCreator = 1 OR BulkAdmin = 1 THEN '0' 
     ELSE '1' END AS SAViolations 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.IsBackupShare = 0 THEN '-1' 
     WHEN NOT (BackupCTE.[BackupShare] LIKE '\\CO.IHC.COM%' OR BackupCTE.[BackupShare] LIKE '\\CO-LP-SQL1%' OR BackupCTE.[BackupShare] LIKE '\\CO-LP-SQL2%' 
       OR BackupCTE.[BackupShare] LIKE '\\CO-TX-VAULT2%' OR BackupCTE.[BackupShare] LIKE '\\co-tx-vpdsfile2\txPDSsqlBackups%' AND BackupCTE.[BackupShare] NOT LIKE '%Test') OR BackupCTE.[BackupShare] = 'NONE LISTED' THEN '0' 
     ELSE '1' END AS IsBackupShare 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.Tempdb_DataFileCount = 0 THEN '-1' 
      WHEN TEMPDBFileCount.Tempdb_DataFileCount >= 8 OR TEMPDBFileCount.Tempdb_DataFileCount > TEMPDBFileCount.OptimalTempdbFilecount THEN '1' 
      WHEN TEMPDBFileCount.OptimalTempdbFilecount > TEMPDBFileCount.Tempdb_DataFileCount THEN '0' 
      ELSE '1'END AS Tempdb_DataFileCount 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DataAutoGrow = 0 THEN '-1' ELSE BackupCTE.DataAutoGrow END AS DataAutoGrow 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.LogAutoGrow = 0 THEN '-1' ELSE BackupCTE.LogAutoGrow END AS LogAutoGrow 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.MaintVersion = 0 THEN '-1' ELSE BackupCTE.MaintVersion END AS MaintVersion 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.MaintVersion = 0 THEN '-1' 
     WHEN BackupCTE.MaintVersion = 2.02 OR BackupCTE.MaintVersion = 2.03 THEN '1' 
     ELSE '0' END AS FlagMaintVersion 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DBCompatibilityLevel = 0 THEN '-1' 
      WHEN BackupCTE.DBCompatibilityLevel < 90 THEN '0' 
      ELSE '1' END AS DBCompatibilityLevel 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.FlagVersionName = 0 THEN '-1' 
      WHEN NOT (BackupCTE.VersionName LIKE 'Microsoft SQL Server 2005%' OR BackupCTE.VersionName LIKE 'Microsoft SQL Server 2000%') THEN '1' 
      ELSE '0' END AS FlagVersionName 
    ,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.VLFCount = 0 THEN '-1' 
      ELSE BackupCTE.VLFCount END AS VLFCount 
Into #FinalData 
FROM [DBAPP].InstanceSQLDtl 
LEFT JOIN #BackupCTE BackupCTE ON InstanceSQLDtl.InstanceID = BackupCTE.InstanceID 
LEFT JOIN [DBAPP].[SQLPatchingStandards] PatchingStds ON LTRIM(RTRIM(LEFT(VersionName, CHARINDEX('-', VersionName)-1))) = LTRIM(RTRIM(LEFT 
      (PatchingStds.SQLVersion,CHARINDEX('-',PatchingStds.SQLVersion)-1))) 
LEFT JOIN [DBAPP].[ComplianceReportExceptions] ON ComplianceReportExceptions.InstanceName = BackupCTE.InstanceName 
LEFT JOIN [DBAPP].[TEMPDBFileCount] ON InstanceSQLDtl.InstanceID = [TEMPDBFileCount].InstanceID AND Type_DESC = 'ROWS' 
LEFT JOIN DBO.fnGetServiceNames() StdServiceAccount ON BackupCTE.InstanceID = StdServiceAccount.InstanceID 
Where BackupCTE.[InstanceName] IS NOT NULL 
ORDER BY [InstanceName] 
+3

所以你放棄一個存儲過程有近500線,並沒有任何細節上的論壇,並希望有人能夠幫助???? –

+0

你在分析字符串和在聯合中使用UDF ...我會說你很幸運,它完成了... –

+0

現在它只是超過100行。但仍......沒有表格定義和執行計劃,這裏幾乎沒有人能做到。那個函數fnGetServiceNames可能是我開始的地方。 –

回答

2

那麼多的字符串操作和CASE語句總是會很慢。也許你可以將它作爲一個夜間批處理過程運行到數據集市?否則,這裏有幾個技巧:

  1. 由於許多你的CASE語句正在測試... InstanceName是NULL,則可以在半和使用UNION將查詢所有參加記錄在一起的地方是和不爲null(請參閱示例)。這將刪除一堆CASE檢查。
  2. 如果只有一個項目,請不要使用WHERE IN('SA'),而應使用不等於(<>)。
  3. 如果可能,請避免在JOIN條件下進行字符串操作(...PatchingStds ON LTRIM(RTRIM(LEFT(VersionName...)。嘗試將這些字段存儲在某個地方,無論是專用列還是持久計算列。這樣,您可以在該字段中加入索引以加快聯接速度。
  4. 在可能的情況下,在連接字段上有索引,但受多種因素影響,但大多數情況下,在單個表上沒有太多索引,因爲這會降低INSERT語句的速度。
SELECT DISTINCT 
    BackupCTE.[InstanceName] 
    , EnvironmentType = CASE WHEN ComplianceReportExceptions.EnvironmentType = 0 THEN '-1' ELSE CONVERT(VARCHAR, BackupCTE.EnvironmentType) END 
    , [InstanceStatus] = CASE WHEN ComplianceReportExceptions.InstanceStatus = 0 THEN '-1' ELSE CONVERT(VARCHAR,BackupCTE.InstanceStatus) END 
    , BackupCTE.[BackupShare] 
    , DatabaseOwner = 
     CASE WHEN ComplianceReportExceptions.DatabaseOwner = 0 THEN '-1' 
      WHEN ISNULL(BackupCTE.IsMirroringEnabled,0) = 0 
       AND BackupCTE.DatabaseOwner <> 'SA' 
       AND BackupCTE.DatabaseStatus = 'Normal' 
       AND BackupCTE.DatabaseReadOnly = 0 
       AND ISNULL(BackupCTE.IsDatabaseSnapshot,0) = 0 
      THEN '0' 
      ELSE '1' 
     END 
    -- Etc... 
INTO #FinalData 
FROM [DBAPP].InstanceSQLDtl 
    LEFT JOIN #BackupCTE BackupCTE ON InstanceSQLDtl.InstanceID = BackupCTE.InstanceID 
    LEFT JOIN [DBAPP].[SQLPatchingStandards] PatchingStds ON LTRIM(RTRIM(LEFT(VersionName, CHARINDEX('-', VersionName)-1))) = LTRIM(RTRIM(LEFT 
       (PatchingStds.SQLVersion,CHARINDEX('-',PatchingStds.SQLVersion)-1))) 
    LEFT JOIN [DBAPP].[ComplianceReportExceptions] ON ComplianceReportExceptions.InstanceName = BackupCTE.InstanceName 
    LEFT JOIN [DBAPP].[TEMPDBFileCount] ON InstanceSQLDtl.InstanceID = [TEMPDBFileCount].InstanceID AND Type_DESC = 'ROWS' 
    LEFT JOIN DBO.fnGetServiceNames() StdServiceAccount ON BackupCTE.InstanceID = StdServiceAccount.InstanceID 
WHERE BackupCTE.[InstanceName] IS NOT NULL 
    AND DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL 
--**************** 
UNION ALL 
--**************** 
SELECT DISTINCT 
    BackupCTE.[InstanceName] 
    , EnvironmentType = CONVERT(VARCHAR,BackupCTE.EnvironmentType) 
    , [InstanceStatus] = CONVERT(VARCHAR,BackupCTE.InstanceStatus) 
    , BackupCTE.[BackupShare] 
    , DatabaseOwner = 
     CASE 
      WHEN ISNULL(BackupCTE.IsMirroringEnabled,0) = 0 
       AND BackupCTE.DatabaseOwner <> 'SA' 
       AND BackupCTE.DatabaseStatus = 'Normal' 
       AND BackupCTE.DatabaseReadOnly = 0 
       AND ISNULL(BackupCTE.IsDatabaseSnapshot,0) = 0 
      THEN '0' 
      ELSE '1' 
     END 
-- Etc... 
INTO #FinalData 
FROM [DBAPP].InstanceSQLDtl 
    LEFT JOIN #BackupCTE BackupCTE ON InstanceSQLDtl.InstanceID = BackupCTE.InstanceID 
    LEFT JOIN [DBAPP].[SQLPatchingStandards] PatchingStds ON LTRIM(RTRIM(LEFT(VersionName, CHARINDEX('-', VersionName)-1))) = LTRIM(RTRIM(LEFT 
       (PatchingStds.SQLVersion,CHARINDEX('-',PatchingStds.SQLVersion)-1))) 
    LEFT JOIN [DBAPP].[ComplianceReportExceptions] ON ComplianceReportExceptions.InstanceName = BackupCTE.InstanceName 
    LEFT JOIN [DBAPP].[TEMPDBFileCount] ON InstanceSQLDtl.InstanceID = [TEMPDBFileCount].InstanceID AND Type_DESC = 'ROWS' 
    LEFT JOIN DBO.fnGetServiceNames() StdServiceAccount ON BackupCTE.InstanceID = StdServiceAccount.InstanceID 
WHERE BackupCTE.[InstanceName] IS NOT NULL 
    AND DBAPP.ComplianceReportExceptions.InstanceName IS NULL 
--**************** 
ORDER BY [InstanceName] 
+0

分而治之是開始解決這個問題的好方法。 – Namphibian

-1

下面是導致降級的查詢性能的可能性,

  1. 在不轉換科拉姆值的條款,而不是這個創建一個單獨的科拉姆和預填充轉換,如果您使用轉換 它禁止使用索引搜索表中的記錄。

  2. 使用與(NOLOCK)由

  3. 鮮明&順序是昂貴的操作查詢,如果你不要求從查詢中刪除它。