我继承了设计糟糕的SQL Server实现,包含可怕的数据库模式,以及需要数小时甚至数天才能执行的几个可怜的查询/视图。
我很好奇:经验丰富的DBA / SQL程序员可能认为查询需要花费的时间非常长?根据我的专业经验,我不习惯查看(用于观看或报告等)的查询,这些查询需要花费一两个小时才能运行。我们这里有几个需要1-2天或更长时间!
(这个数据库没有关系,没有主键,没有外键,几乎没有索引,到处都是重复数据,旧数据甚至不在表中,临时表到处都是,等等......呃!)
对于冗长的查询过程,您在可接受或正常的范围内考虑什么?
我试图进行健全性检查,以确定这个数据库真的有多糟糕......
答案 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会清除所有收集的数据,因此这些查询仅对在“真实世界”情况下已启动并运行一段时间的系统非常有用。
我希望你发现这些有用。