通常长时间运行查询?

时间:2017-03-30 18:50:42

标签: sql sql-server query-performance

我继承了设计糟糕的SQL Server实现,包含可怕的数据库模式,以及需要数小时甚至数天才能执行的几个可怜的查询/视图。

我很好奇:经验丰富的DBA / SQL程序员可能认为查询需要花费的时间非常长?根据我的专业经验,我不习惯查看(用于观看或报告等)的查询,这些查询需要花费一两个小时才能运行。我们这里有几个需要1-2天或更长时间!

(这个数据库没有关系,没有主键,没有外键,几乎没有索引,到处都是重复数据,旧数据甚至不在表中,临时表到处都是,等等......呃!)

对于冗长的查询过程,您在可接受或正常的范围内考虑什么?

我试图进行健全性检查,以确定这个数据库真的有多糟糕......

1 个答案:

答案 0 :(得分:0)

这不是你问题的答案,在这里提供这个脚本比在评论中提供更容易。

您可能希望运行此查询,并查看SQL Server认为缺少的索引需要更好地执行的内容(迁移到新架构和数据库时的短期解决方案)。不要盲目地申请这些指数。这些只是建议供您考虑,SQL Server本身已经确定在运行时有用。您可以选择一个或两个,可能是调整包含列,然后选择AFTER TESTING,应用其中一些来帮助您加速现有系统(我忘记了这个查询的来源,所以我很遗憾无法归因于原作者):

SELECT 
  migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure, 
  (migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) AS [cumulative_impact],
  OBJECT_NAME(OBJECT_ID) as TableName,
  'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) 
  + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']'
  + ' ON ' + mid.statement 
  + ' (' + ISNULL (mid.equality_columns,'') 
    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 
    + ISNULL (mid.inequality_columns, '')
  + ')' 
  + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement, 
  migs.*, mid.database_id, mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
  AND database_id = DB_ID()
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

此外,您可以使用以下脚本查找“运行时间最长的查询”(及其SQL计划)。这里有一大堆信息,所以使用ORDER BY来在顶部引起不同类型的问题(例如,运行时间最长的查询可能只运行一次或两次,而运行数千次的查询可能不会运行很长,但可能会消耗更多的资源所有人告诉我们:

SELECT [St].Text,
       [Qp].[Query_Plan],
       [Qs].*
  FROM (SELECT TOP 50 *
          FROM [Sys].[Dm_Exec_Query_Stats]
         ORDER BY [Total_Worker_Time] DESC
) AS [Qs]
       CROSS APPLY [Sys].[Dm_Exec_Sql_Text] ([Qs].[Sql_Handle]) AS [St] 
       CROSS APPLY [Sys].[Dm_Exec_Query_Plan] ([Qs].[Plan_Handle]) AS [Qp]
 WHERE ([Qs].[Max_Worker_Time] > 300 OR [Qs].[Max_Elapsed_Time] > 300)
   AND [Qs].execution_count > 1
 ORDER BY min_elapsed_time DESC, max_elapsed_time DESC

这些查询仅返回正在运行的实例中的数据。停止并重新启动SQL Server会清除所有收集的数据,因此这些查询仅对在“真实世界”情况下已启动并运行一段时间的系统非常有用。

我希望你发现这些有用。