这两天对公司的一个项目进行优化,看着长长的SQL,脑袋不经有些大,一时间竟然不知道如何下手,一顿手忙脚乱后,小有成效,响应速度快了不少,同样的条件下可以做到秒级响应。闲暇时间想了想,还是得做点功课,最起码也要把原来丢下的东西捡回来,再有这样的事情不至于抓瞎。这样就有了今天的这篇文章,先挤一点,以后慢慢补充。
Microsoft SQL Server 在2005以后提供了一些工具来监控数据库,这对我们进行数据库方面的调优提供了极大的便利,在今天之前有的我也只是听说过,缺乏实际的操作。下面我们就来了解一下DMO和他的孩子DMV[动态管理视图]。
首先我们先要看下DMO都能做些什么?[网上抄来的]:
- 执行相关的DMO(sys.dm_exec_*):提供与执行相关的统计信息。可以用于监控与缓存查询、执行计划、活动连接/会话和带有执行计划的当前运行的查询的相关统计信息。
- 索引相关的DMO(sys.dm_db_index_*和sys.dm_db_missing_*):提供关于索引的统计信息。这些DMO可以用于监控和分析因为丢失索引、无效索引而导致的性能问题,也可以用来检查索引的使用情况。
- 数据库相关DMO(sys.dm_db_*):提供数据库相关统计信息。可以用于监控和分析数据库的性能问题,分析数据库相关文件的统计信息、会话统计信息和任务统计信息。
- I/O相关DMO(sys.dm_io_*):提供I/O操作的统计信息,用于监控和分析SQLServer的I/O性能问题。
- OS相关DMO(sys.dm_os_*):提供关于sqlos内部统计信息,用于监控和分析服务器配置问题。
- 事务相关的DMO(sys.dm_trn_*):提供事务相关的统计信息,用于监控和分析长时间运行的事务的锁定、死锁问题。
看了网上的描述使我对DMO更好奇了,你呢,有木有?我们先来看些实际的代码吧:
- DMV获取当前正在执行的查询信息
SELECT DB_NAME(R.database_id) AS DatabaseName ,
S.original_login_name AS LoginName ,
S.host_name AS ClientMachine ,
S.program_name AS ApplicationName ,
R.start_time AS RequestStartTime ,
ST.text AS SQLQuery ,
QP.query_plan AS ExecutionPlan ,
R.cpu_time AS CPUTime ,
R.total_elapsed_time AS TotalTimeElapsed ,
R.open_transaction_count AS TotalTransactionOpened ,
R.reads ,
R.logical_reads ,
R.writes AS TotalWrites
FROM sys.dm_exec_requests AS R
INNER JOIN sys.dm_exec_sessions AS S ON R.session_id = S.session_id
CROSS APPLY sys.dm_exec_sql_text(R.sql_handle) AS ST
CROSS APPLY sys.dm_exec_query_plan(R.plan_handle) AS QP
ORDER BY TotalTimeElapsed DESC
GO
- 通过DMV获取的索引缺失的表和需要建立索引的列
SELECT MID.statement AS ObjectName ,
MID.equality_columns ,
MID.inequality_columns ,
MID.included_columns ,
MIGS.avg_user_impact AS ExpectedPerformanceImprovement ,
( MIGS.user_seeks + MIGS.user_scans ) * MIGS.avg_total_user_cost
* MIGS.avg_user_impact AS PossibleImprovement
FROM sys.dm_db_missing_index_details AS MID
INNER JOIN sys.dm_db_missing_index_groups AS MIG ON MID.index_handle = MIG.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats AS MIGS ON MIG.index_group_handle = MIGS.group_handle
GO
查询结果: ObjectName equality_columns inequality_columns included_columns ExpectedPerformanceImprovement PossibleImprovement
SalesOrderDetail NULL [ModifiedDate] 需要查询的列 88.23 97.8503286933556
SalesOrderDetail [ProductID] NULL 需要查询的列 99.52 110.371355679052
通过上面的查询结果,我们可以很清楚的看到,SQL Server推荐的需要建立所以的表和列,更为友好的是,它还给出了建立索引后能带来多少的效率提升。那要怎么来建立索引呢?描述比较绕口,我抄来以为网友的说明,呵呵:
若要将由 sys.dm_db_missing_index_details 返回的信息转换为 CREATE INDEX 语句,则相等列应该放置在不等列前面,并且应该一起创建索引键。应该使用 INCLUDE 子句将包含列添加到
CREATE INDEX 语句。若要确定相等列的有效顺序,请基于其选择性排序:首先列出选择性最强的列(列列表中的最左侧)。也就是这样:
create index [索引名称] on [表](equality_columns,inequality_columns) include(included_columns)
是不是很方便?当然效果好不好,不能只看广告,要看实际效果哦。
需要注意的是sys.dm_db_missing_index_details记录了当前数据库下所有的missing index的信息,他针对的是SQLSERVER从启动以来所有运行的语句,而不是针对某一个查询。并且sys.dm_db_missing_index_details返回的信息会不是持久化的。
今天先写到这里,我们还可以通过DMV查看tempDB的情况以及查看查看磁盘IO的情况,这些将在以后进行,今天只是我的一个备忘记录。