-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. 鲜明&顺序是昂贵的操作查询,如果你不要求从查询中删除它。