SQL Server长时间运行查询

时间:2017-03-11 02:21:44

标签: sql sql-server tsql query-optimization

有人可以帮助我理解为什么下面的查询运行时间超过一分钟?

当我评论以下内容时:

AND sys.fn_hadr_backup_is_preferred_replica(d.name) = 1

查询在不到一秒的时间内运行。

我正在寻找一些替代方法来重写查询。

SELECT
DISTINCT @@SERVERNAME AS ServerName ,
d.name AS DatabaseName ,
'Diff Backups Not Performed Recently' AS Finding ,
'Last differential backup: ' + COALESCE(CAST(MAX(b.backup_finish_date) AS VARCHAR(25)),'never') AS Details
FROM master.sys.databases d
    LEFT OUTER JOIN msdb.dbo.backupset b ON d.name COLLATE SQL_Latin1_General_CP1_CI_AS = b.database_name COLLATE SQL_Latin1_General_CP1_CI_AS
    AND b.type = 'I'
    AND b.server_name = SERVERPROPERTY('ServerName') /*Backupset ran on current server */
WHERE d.database_id <> 2 
    AND d.state NOT IN(1, 6, 10) /* Not currently offline or restoring, like log shipping databases */
    AND d.is_in_standby = 0 /* Not a log shipping target database */
    AND d.source_database_id IS NULL /* Excludes database snapshots */
    AND b.user_name = 'tsmadmin'
    AND sys.fn_hadr_backup_is_preferred_replica(d.name) = 1
GROUP BY d.name
HAVING MAX(b.backup_finish_date) <= DATEADD(dd, -2, GETDATE())
    OR MAX(b.backup_finish_date) IS NULL;

2 个答案:

答案 0 :(得分:1)

这可能是在 group by之后运行函数的一个好主意。尝试从where删除函数调用并将其添加到having子句:

HAVING (MAX(b.backup_finish_date) <= DATEADD(day, -2, GETDATE()) OR
        MAX(b.backup_finish_date) IS NULL
       ) AND
       sys.fn_hadr_backup_is_preferred_replica(d.name) = 1

我只是建议这样做,因为您按d.name进行汇总。通常,在聚合之前过滤会更好。但是,如果操作非常昂贵,那么在聚合之后过滤可能会更好。

答案 1 :(得分:0)

这会把它变成一个内在的连接AND b.user_name = 'tsmadmin'所以不妨使用连接

HAVING OR可能是问题

DISTINCT可能是个问题

SELECT @@SERVERNAME AS ServerName;
SELECT d.name AS DatabaseName  
     , COALESCE(CAST(MAX(b.backup_finish_date) AS VARCHAR(25)), 'never') AS Details
FROM master.sys.databases d
JOIN msdb.dbo.backupset b 
  ON d.name COLLATE SQL_Latin1_General_CP1_CI_AS = b.database_name COLLATE SQL_Latin1_General_CP1_CI_AS
 AND b.type = 'I'
 AND b.server_name = SERVERPROPERTY('ServerName') /*Backupset ran on current server */
 AND b.user_name = 'tsmadmin'
 AND d.database_id <> 2 
 AND d.state NOT IN(1, 6, 10)     /* Not currently offline or restoring, like log shipping databases */
 AND d.is_in_standby = 0          /* Not a log shipping target database */
 AND d.source_database_id IS NULL /* Excludes database snapshots */
 AND sys.fn_hadr_backup_is_preferred_replica(d.name) = 1
GROUP BY d.name
HAVING isnull(MAX(b.backup_finish_date), DATEADD(dd, -2, GETDATE())) 
       <= DATEADD(dd, -2, GETDATE());