SQLServer笔试题_第1页
SQLServer笔试题_第2页
SQLServer笔试题_第3页
SQLServer笔试题_第4页
SQLServer笔试题_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、问题一、 请用T-SQL实现查找10万以内的质数。问题二、 有哪些操作会使用到TempDB;如果TempDB异常变大,可能的原因是什么,该如何处理;在讨论Tempdb空间使用之前,我们先简单介绍一下通常什么操作会大量使用Tempdb。在SQL 2005和SQL 2008里,使用Tempdb空间的远远不止是临时表。常见的使用对象有:用户对象(user_object_reserved_page_count)用户对象由用户显式创建。这些对象可以位于用户会话的作用域中,也可位于创建对象所用例程的作用域中。 可以是存储过程、触发器或用户定义函数。 用户对象可以是下列项之一:· 用户定义的表和索

2、引· 系统表和索引· 全局临时表和索引· 局部临时表和索引· table 变量· 表值函数中返回的表内部对象(internal_object_reserved_page_count)内部对象是根据需要由 SQL Server 数据库引擎创建的,用于处理 SQL Server 语句。 内部对象可以在语句的作用域中创建和删除。 内部对象可以是下列项之一:· 用于游标。· 用于哈希联接或哈希聚合操作的查询。· 某些 GROUP BY、ORDER BY 或 UNION 查询的中间排序结果。版本存储(version_stor

3、e_reserved_page_count)版本存储区主要用来支持Snapshot事务隔离级别,以及SQL 2005以后推出的一些其他提高数据库并发度的新功能。由此可见,光从用户发过来的语句本身,是很难判断这个连接的操作是否会使用Tempdb的。一个典型的例子,就是某些查询。如果表格上有良好的索引做支持,SQL Server不需要做哈希联接(Hash Join),那这个查询就不会用Tempdb。反之,如果表格很大,又没有好的索引,那Tempdb使用量就可能不小。tempdb空间使用的一大特点,是只有一部分对象,例如用户创建的临时表、table变量等,可以用sys.allocation_unit

4、s 和 sys.partitions这样的管理视图来管理。许多内部对象和版本存储在这些管理视图里没有体现。所以,sp_spaceused的结果和真实使用 会有很大差异,tempdb的空间使用是不能用sp_spaceused来跟踪的。必须借助sys.dm_db_这样的管理视图和管理函数,才能看到全貌。下面以一个实例,讨论一下如何用DBCC命令、管理视图(DMV)以及管理函数(DMF)来监视是什么语句正在使用tempdb。为了使结果简单,我们在测试之前先把SQL Server重起一次。然后我们在Management Studio里做一个连接(连接A),将下面语句输入。这些语句会使用tempdb的空

5、间。select spidgouse adventureworksgoselect getdate()goselect * into #mySalesOrderDetailfrom Sales.SalesOrderDetail- 创建一个temp table- 这个操作应该会申请user objects pagegowaitfor delay '0:0:2'select getdate()godrop table #mySalesOrderDetail- 删除一个temp table- 这个操作后user object page数量应该会下降gowaitfor delay &#

6、39;0:0:2'select getdate()goselect top 100000 * fromSales.SalesOrderDetailINNER JOIN Sales.SalesOrderHeaderON Sales.SalesOrderHeader .SalesOrderID = Sales.SalesOrderHeader.SalesOrderID;- 这里做了一个比较大的join.- 应该会有internal objects的申请.goselect getdate()- join 语句做完以后internal objects page数目应该下降go那用什么脚本可用监

7、视上面的行为呢?下面的脚本就可以监视和发现当前的Tempdb使用者。这个脚本需要在使用tempdb的语句开始运行之前开始。(读者当然可以根据自己的喜好,修改这个脚本。)脚本首先用“dbcc show”语句查询当前tempdb的总体使用量。再查询sys.dm_db_视图,得到 Tempdb里当前总共有多少用户对象、内部对象、以及版本存储。然后查询sys.dm_db_session_space_usage和 sys.dm_exec_sessions,找到当前使用Tempdb的所有连接。最后通过sys.dm_exec_sql_text,找到这些连接正在 运行的语句。use tempdb &

8、#160;                                                  

9、           - 每隔1秒钟运行一次,直到用户手工终止脚本运行while 1=1                                 

10、60;                             begin                   

11、0;                                               select getdate()

12、                                                  

13、      - 从文件级看tempdb使用情况dbcc show                                       

14、0;              - Query 1- 返回所有做过空间申请的session信息Select 'Tempdb' as DB, getdate() as Time,                       &

15、#160;                                    SUM (user_object_reserved_page_count)*8 as user_objects_kb,    &

16、#160;        SUM (internal_object_reserved_page_count)*8 as internal_objects_kb,     SUM (version_store_reserved_page_count)*8  as version_store_kb,         SUM (unallocated_extent_page_count)*8 as fr

17、eespace_kb               From sys.dm_db_                               

18、;          Where database_id = 2                                     &

19、#160;              - Query 2- 这个管理视图能够反映当时tempdb空间的总体分配SELECT t1.session_id,                         

20、0;                         ernal_objects_alloc_page_count,  t1.user_objects_alloc_page_count,ernal_objects_dealloc_page_count , t1.user_objects_dealloc_page_c

21、ount,t3.*from sys.dm_db_session_space_usage  t1 ,                               - 反映每个session累计空间申请sys.dm_exec_sessions as t3- 每个session的信息w

22、heret1.session_id = t3.session_idand (ernal_objects_alloc_page_count>0or t1.user_objects_alloc_page_count >0or ernal_objects_dealloc_page_count>0or t1.user_objects_dealloc_page_count>0)- Query 3- 返回正在运行并且做过空间申请的session正在运行的语句SELECT t1.session_id,     

23、                                               st.text  

24、0;                                                 

25、0;   from sys.dm_db_session_space_usage as t1,                               sys.dm_exec_requests as t4    

26、60;                                         CROSS APPLY sys.dm_exec_sql_text(t4.sql_handle) AS

27、st                    where  t1.session_id = t4.session_id                       

28、;                   and t1.session_id >50                           

29、0;                    and (ernal_objects_alloc_page_count>0or t1.user_objects_alloc_page_count >0or ernal_objects_dealloc_page_count>0or t1.user_objects_dealloc_page_count>0)&#

30、160;                                             waitfor delay '0:0:1&#

31、39;                                                  &#

32、160; end                          图1 在运行这个脚本的连接(连接B)里(图1),我们选择好“Result to File”。先开始运行它,指定输出文件路径。然后,我们再运行连接A(图2)。连接A运行结束后,手工停止连接B的运行。图2 在连接A的结果中(),可以得到四个时间。

33、图片上的例子,是:11:39:36.513     - 开始创建temp table11:39:38.920 开始删除temp table11:39:40.937 开始查询11:39:45.733 查询结束  连接B生成的是一个文本文件。利用一些有“列出所有包含某个特定字符串”行功能的编辑器工具,可以把每个命令结果挑出来。 从连接B生成的文本文件里所有dbcc show的结果(图3),可以看出tempdb的使用空间有过两次增长(从23到210,从47到118),中间有一次下降(从210到47)。  图3从

34、连接B生成的文本文件里所有Query 1的结果(图3),我们可以看到有三段时间,user object和internal object空间有申请和释放动作。它们分别是11:39:36 11:39:37 (user_objects_kb增长),11:39:40 11:39:41 (user_objects_kb下降),11:39:40 11:39:43(internal_objects_kb增长)。图4从Query 2的结果(图4)可以看到Connection A在这三个时间段都处于运行状态。图5  根据时间,可以从Query 3的结果(图5)里找到Connection A当

35、时正在运行的语句。例如在11:39:40 11:39:43(internal_objects_kb增长)这段时间里,一直都在运行下面这句话:图6从上面的结果可以看出,连接A的语句中,用tempdb最多的时间点在11:39:41和11:39:42之间,连接正在做图6里面的那条查询语句。SQL Server需要空间存放一些内部对象,来完成Inner Join。问题三、 死锁如何跟踪;用Profile做跟踪时,一般我们需要跟踪哪些事件;SQL Server跟踪(SQL Server Profile)的一些监控方式和途径使用场景    记得某次给一家公司调优的时候,负责人

36、发给我一堆业务的T-SQL脚本,我面对海量脚本还是从容,虽然不了解内部复杂的业务,但是我们得专注问题的关键 “慢”,我们根据查询的“慢”把他们筛选出来,一一调式优化,不就迅速解决问题吗?三天后,负责人含泪握着我的手,哥们辛苦了,查询响应得到了质的改善。跟踪提供者    SQL Server 为我们两者提供跟踪的方式:一种是一个物理文件(可保存在本机或者UNC网络路径),一种是行集。对于后者大家应该比较熟悉这个工具在 SSMS 的 工具 > SQL Profile详细的我暂时不介绍,先说说两者的区别和类同点 DIFFAndSame(行集,文件提供者)。

37、3; 两者都是用类似Buffer来保存当前的事件数据,很明显是为了减少IO的压力,这样可以不阻塞和尽量不遗漏 事件数据,当Buffer 到达一定量时候可能才会Flush到磁盘或者发送到网络的终端(客户端)显示监控行集。· 物理文件保存监控结果的方式的重要保证是不能遗漏任何事件,一旦IO降速的时候,可能会影响到整个T-SQL的执行情况。 SELECT * FROM sys.dm_os_wait_stats WHERE wait_type IN ('SQLTRACE_LOCK','IO_COMPLETION'); 我使用这个语句来监控TRACE 和IO 完

38、成对我当前机器的影响,我的某个客户的IO情况:                       wait_type  waiting_tasks_count wait_time_msmax_wait_time_ms signal_wait_time_ms IO_COMPLETION3634    418960 SQLTRACE_LOCK120

39、07 1759431001 1281因为我进行了大量的过滤,因此这个值还是能够接受的,影响不是特别大。· 行结果集的方式,其实也是我们最熟悉的,就是使用SQL Server Profile监控GUI 直接展现给我们看到的。但是,我是非常不建议使用的,首先如果Buffer满了,它有一定的延迟,可能会抛弃事件已 清空缓存区继续接受事件,而事件没有发送到Client,也没有写到物理文件,自然就丢失了。比如,SQL Server Profile 在DB服务器进行监控,因为高负载的机器再用来展示,很有可能就会丢失事件,另外物理文件方式,其实是接受一个足够大的Buffer,进行的大块写操作, 性

40、能是优于行集的。(行集)保密性原则    SQL Server的安全特性会自动过滤 包含隐私的数据,比如密码。我在我的SSMS中执行了如下的语句:EXEC sp_password 'pp','pp1','sa'这是修改sa帐号密码的系统sp,我打开了SQL Server Profile > 选择了T-SQL 监控模版 然后执行上面的存储过程,监控结果:监控结果:-*sp_password- SQL Server Profile     使用SQL Server Pro工具

41、还是很多优势,首先是减少了我们监控的复杂性,可以快速的建立监控,在跟踪属性中,可以可以选择MSSQL为我们提供的模版,包括常用的T-SQL、T-SQL Duration、T-SQL Locks模版分别监控当前DB运行的所有查询,所有查询的耗时、所有的锁定状态。在跟踪属性 > 选择事件选择 我们可以选择自己需要的事件,所有的事件在MSDN 都有定义->单击列筛选器 可以自定义过滤,排序噪点干扰因素(我随便选择了一个耗时 = 500 微妙的过滤条件)其他的模版大家可以自己看看MSDN 手册,自己尝试一下:SQL Server 2008 R2 本机  MSDN 服务器

42、端跟踪和物理方式收集    SQL Server Profile 只是对一些存储过程的封装,我更倾向于,自己定义常用的脚本,将监控结果保存在本机,用来大量的分析和存档。当然涉及4个存储过程,虽然设置过滤的脚本非常麻烦,但是SQL Server Profile 可以利用 文件->导出 可以导出监控脚本意味着,我们不需要编写复杂的T-SQL 脚本,不过还是建议大家熟悉这几个存储过程:· sp_trace_create 定义跟踪 ,创建的跟踪会在sys.traces查询的到。· s_trace_setevent 设置监控事件· sp_

43、trace_setfilter 设置过滤· sp_trace_setstatus 设置跟踪的状态  常用的是  sp_trace_setstatus traceid,0 停止功能 、sp_trace_setstatus traceid,2 移除跟踪,这将导致sys.traces最终查询不到该跟踪其实整个跟踪还是比较简单的。我这里有一个常用的脚本:用来 监控超过指定秒数 和 数据库 的 批处理和存储过程 语句(超过5MB的文件,会执行ROLLOVER,根据文件名在后面添加类似_1,_2.trc的跟踪结果):CREATE PROC dbo.sp_trace_sql_d

44、urtion DatabaseName nvarchar(128), Seconds bigint, nvarchar(260)ASBEGINDECLARE rc int,TraceID int,Max bigint;SET Max = 5; EXEC sp_trace_create TraceID OUTPUT,2,NULL; IF rc != 0 RETURN; DECLARE On bit;SET On = 1; EXEC sp_trace_setevent TraceID,10,35,On;EXEC sp_trace_setevent Trace

45、ID,10,1,On;EXEC sp_trace_setevent TraceID,10,13,On;EXEC sp_trace_setevent TraceID,41,35,On;EXEC sp_trace_setevent TraceID,41,1,On;EXEC sp_trace_setevent TraceID,41,13,On; SET Seconds = Seconds * 1000000; EXEC sp_trace_setfilter TraceID,13,0,4,Seconds; IF DatabaseName IS NOT NULL EXEC

46、sp_trace_setfilter TraceID,35,0,0,DatabaseName EXEC sp_trace_setstatus TraceID,1SELECT TraceID = TraceID; END参数非常的明了,数据库名称、执行事件超过多少秒、保存的路径。当我们运行这个脚本一段事件以后,可以快速的发现大量耗时的T-SQL,我们可以通过SELECT * FROM fn_trace_gettable(N'监控文件路径',1);来查看行方式的结果。同样的富有创造力的读者可以自己创建监控锁定,监控死锁等方式保存文件,但是我的建议是尽可能的减少噪

47、音,也就是说我们要达到什么目地就建立什么功能,这样才能将大问题细化解决。在Microsfot SQL Server 2005 技术内幕: T-SQL 程序设计 中有一个正则,用来将类似的语句全部组合成,只有参数形式替换具体值的SQL CLR,但是我认为那个正则还有bug,等我空了给大家写一个,自己也能使用的更完善。监控异常 在上个系列中,讲述了具体的SQL Event抓去的异常,可以及时通知,但是具体的异常信息,并不是特别详细。因此我们可以选择事件中的Error来添加有关T-SQL批处理和SP的所有异常,用于分析,这个跟踪非常有利于我们监控一些异常情况!我创建了一个跟踪的脚本,和上面的跟踪事件

48、的脚本一样,超过5MB RollOver。 我们要定期的执行这个跟踪,虽然不建议长期开启,但是定期监控处理异常是有利我们系统更加长时间运作的。CREATE PROC dbo.sp_trace_sql_exception nvarchar(260)ASDECLARE rc int,TraceID int,Max bigintSET max = 5   EXEC rc = sp_trace_create TraceID output, 2, , Max, NULL IF (rc != 0) RETURN; DECLARE on bitSET on = 1EXEC sp

49、_trace_setevent TraceID, 33, 1, onEXEC sp_trace_setevent TraceID, 33, 14, onEXEC sp_trace_setevent TraceID, 33, 51, onEXEC sp_trace_setevent TraceID, 33, 12, onEXEC sp_trace_setevent TraceID, 11, 2, onEXEC sp_trace_setevent TraceID, 11, 14, onEXEC sp_trace_setevent TraceID, 11, 51, onEXEC sp_trace_s

50、etevent TraceID, 11, 12, onEXEC sp_trace_setevent TraceID, 13, 1, onEXEC sp_trace_setevent TraceID, 13, 14, onEXEC sp_trace_setevent TraceID, 13, 51, onEXEC sp_trace_setevent TraceID, 13, 12, on DECLARE intfilter int,bigintfilter bigint; EXEC sp_trace_setstatus TraceID, 1 SELECT Trace

51、ID=TraceIDGOTO finish ERROR: SELECT ErrorCode=rc FINISH: 定期执行吧,同志们,找异常。默认跟踪和黑盒跟踪    在sys.traces中的TraceID = 1的跟踪是SQL Server 默认跟踪,这个跟踪比较轻量级,一般监控服务器的启用停止,对象的创建和删除,日志和数据文件自动增长以及其他数据库的变化。(监控那些没事删错了表的 人,是最好的,当然前提不要都使用一个帐号!)可以通过EXEC sp_configure 'default trace enabled',0;RE

52、CONFIGURE WITH OVERRIDE;来关闭默认跟踪。黑盒跟踪,就是可以帮助我们诊断数据库没事自个奔了的异常,在MSDN 搜索sp_create_trace的时候应该也发现了的选项,那么我们也能创建一个类似的存储过程来快速的创建黑盒跟踪,帮助我们诊断一些异常!CREATE PROCEDURE sp_trace_blackbox nvarchar(260)ASBEGIN DECLARE TraceID int,Max bigint SET Max = 25; EXEC sp_trace_create TraceID OUTPUT,8, EXEC sp_trace_setstatus T

53、raceID,1;END我这里提供 = NULL参数,这个默认就保存在SQL Server的数据文件夹中。问题四、 阻塞如何跟踪和查找;当一个数据库会话中的事务正锁定一个或多个其他会话事务想要读取或修改的资源时,会产生阻塞(Blocking)。通常短时间的阻塞没有问题,且是较忙的应用程序所需要的。然而,设计糟糕的应用程序会导致长时间的阻塞,这就不必要地锁定了资源,而且阻塞了其他会话读取和更新它们。当一个数据库会话中的事务正锁定一个或多个其他会话事务想要读取或修改的资源时,会产生阻塞(Blocking)。通常短时间的阻塞没有问题,且是较忙的应用程序所需要的。然而,设计糟糕的应用程序会导致长时间的

54、阻塞,这就不必要地锁定了资源,而且阻塞了其他会话读取和更新它们。在SQL Server中,一个阻塞的进程会无限期地保持阻塞,或者直到它超时(根据set lock_timeout)、服务器关闭、进程被杀死、连接完成了更新或者其他发生在原始事务上的操作导致它释放了资源上的锁。发生长时间阻塞的原因如下:1. 在一个没有索引的表上的过量的行锁会导致SQL Server得到一个锁,从而阻塞其他事务。 2. 应用程序打开一个事务,并在事务保持打开的时候要求用户进行反馈或交互。这通常是让最终用户在GUI上输入数据而保持事务打开的时候发生。此时,事务引用的任何资源都会被占据。 3. 事务BEGIN后查询的数据

55、可能在事务事务开始前被调用 4. 查询不恰当地使用锁定提示。例如,应用程序仅使用很少的行,但却使用一个表锁提示 5. 应用程序使用长时间运行的事务,在一个事务中更新了很多行或很多表(把一个大量更新的事务变成多个更新较少的事务有助于改善并发性)一、找到并解决阻塞进程下面我们演示使用SQL Server动态管理视图sys.dm_os_waiting_tasks找出阻塞进程,该视图用于代替早期SQL Server版本中的系统存储过程sp_who找出阻塞的进程后,我们使用sys.dm_exec_sql_text动态管理函数和sys.dm_exec_Connections(DMV)找出正在执行的查询的S

56、QL文本,然后强制结束进程。强制结束进程,我们使用kill命令。kill的用法,请参看MSDN:该命令有三个参数:· session ID 要终止的进程的会话 ID。session ID 是在建立连接时为每个用户连接分配的唯一整数 (int)。在连接期间,会话 ID 值与该连接捆绑在一起。连接结束时,则释放该整数值,并且可以将它重新分配给新的连接。使用 KILL session ID 可终止与指定的会话 ID 关联的常规非分布式事务和分布式事务。 · UOW 标识分布式事务的工作单元 (UOW) ID。UOW 是可从 sys.dm_tran_locks 动态管理视图的 re

57、quest_owner_guid 列中获取的 GUID。也可从错误日志中或通过 MS DTC 监视器获取 UOW。有关监视分布式事务的详细信息,请参阅 MS DTC 文档。使用 KILL UOW 可终止孤立的分布式事务。这些事务不与任何真实的会话 ID 相关联,与虚拟的会话 ID = '-2' 相关联。可使标识孤立事务变得更为简单,其方法是查询 sys.dm_tran_locks、sys.dm_exec_sessions 或 sys.dm_exec_requests 动态管理视图中的会话 ID 列。 · WITH STATUSONLY 生成由于更早的 KILL 语句而

58、正在回滚的指定 session ID 或 UOW 的进度报告。KILL WITH STATUSONLY 不终止或回滚 session ID 或 UOW,该命令只显示当前的回滚进度。在第一个查询窗口:1. BEGIN TRAN 2. UPDATE Production.ProductInventory 3. SET Quantity = 400 4. WHERE ProductID = 1 AND 5. LocationID = 1 第二个窗口:1. UPDATE Production.ProductInventory 2. SET Quantity = 406 3. WHERE Product

59、ID = 1 AND 4. LocationID = 1 第三个窗口:1. SELECT blocking_session_id, wait_duration_ms, session_id 2. FROM sys.dm_os_waiting_tasks 3. WHERE blocking_session_id IS NOT NULL 4. 5. /*blocking_session_id wait_duration_ms session_id 6. 52 23876 54 7. */ 可以看出是SessionID为52的会话阻塞了SessionID为54的会话。那么,52正在干啥坏事呢?在第三

60、个窗口中执行:1. SELECT t.text 2. FROM sys.dm_exec_connections c 3. CROSS APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) t 4. WHERE c.session_id = 54 5. 6. /*text(1 int,2 tinyint,3 tinyint) 7. UPDATE Production.ProductInventory set Quantity = 1 8. WHERE ProductID=2 AND LocationID=3 9. */ 注意:这并不是第一个查

61、询窗口中的原SQL语句,SQL Server进行了自动参数化计划缓存(预编译)。我们强制终止会话。在第三个窗口中执行:kill 52 注意:窗口一的语句和窗口二的语句均终止。提示:第三个语句中,使用sys.dm_exec_connections(DMV)返回了Session ID为53的most_recent_sql_handle列。这是SQL文本在内存中的指针。作为sys.dm_exec_sql_text动态管理函数的输入参数使用。从sys.dm_exec_sql_text返回了text列,该列显示了阻塞进程的SQL文本。如果阻塞成串,必须通过blocking_session_id和sess

62、ion_ID列仔细查看每一个阻塞进程,直到发现原始的阻塞进程。二、配置语句等待锁释放的时长如果有一个事务或语句被阻塞,意味着它在等待资源上的锁被释放。我们可以事先通过set lock_Timeout来设定需要等待的时间。语法如下:SET LOCK_TIMEOUT time_period参数以毫秒为单位。超过时会返回锁定错误。示例:在第一个窗口中执行:1. USE AdventureWorks 2. BEGIN TRAN 3. UPDATE Production.ProductInventory 4. SET Quantity = 400 5. WHERE ProductID = 1 AND 6

63、. LocationID = 1 在第二个窗口中执行:1. USE AdventureWorks 2. SET LOCK_TIMEOUT 1000 3. UPDATE Production.ProductInventory 4. SET Quantity = 406 5. WHERE ProductID = 1 AND 6. LocationID = 1 7. 8. /*秒后的执行结果Msg 1222, Level 16, State 51,Line 3 9. Lock request time out period exceeded. 10. The statement has been t

64、erminated. 11. */ 解析:在这个示例中,我们设置了锁超时时间为1000毫秒,即秒。这个设置不会影响资源被进程占有的时间,只会影响等待另一个进程释放资源访问的时间。问题五、 发现有问题的语句后,如何进行处理;当你面对一个“有问题”的语句时,应该怎么分析它的问题所在,最后达到优化语句的目的呢?首先要想一想,“有问题”的语句“问题”究竟在那里?也就是说,你要优化的目标是什么。常见的需求有:1)语句需要访问大量的数据页面,造成内在压力、磁盘繁忙等。对于这类问题,所关心的是为什么语句要执行要访问这么多数据页面?是语句的结果集本身就比较大;还是SQL SERVER没有办法有效地seek,而

65、是像大炮打苍蝇一样从大量的原始数据里找出需要返回的结果;还是因为数据页面里有很多碎片,导致SQL SERVER读了很多页面,但是每个页面里的数据量不多。这些都是要考虑的因素。2)在内存没有压力的前提下(语句所访问的页面都事先缓存在内存里),语句运行的时间还是很长。语句的运行时间一般会主要花在这3步上:语句编译、语句执行和结果集返回。结果集返回的速度和SQL SERVER自身没有太大关系,所以一般不会在语句调优的时候来考虑。语句调优时要搞清楚编译和执行各花了多少时间,哪 一段时间有优化的空间,以及怎么来优化。3)单个语句执行时间可以接受,但是苦CPU使用量比较大,多个语句并发执行会造成SQL S

66、ERVER CPU高。有些语句单句执行可能一两秒钟就能执行完毕,对用户来讲还在可接受的范围。但是它的CPU间可能也是在一两秒,甚至更长。如果同时有十几个用户在跑 同样的语句,SQL SERVER 就会满负荷了。语句的CPU时间也分编译阶段和执行阶段。优化者要先搞清楚这两个阶段各用了多少CPU资源,然后再看看有没有优化降低CPU使用量的可 能。4)语句单独执行看不出有大问题,但是并发执行就容易遇到阻塞和死锁。  这个也是语句调优的一个重要任务。很多语句执行速度很快,使用资源量SQL SERVER也能够承受,但是就是容易引起阻塞和死锁。这种现象往往是由于应用在某个表或者索引上的

67、并发度特别高,而问题语句申请的锁数量比较大造成的。 当然有时候可以使用Query Hint 来强制 SQL SERVER使用粒度比较小的锁。但是这往往不是最好的解决办法,也可能解决不了问题。最理想的方法,是通过调整语句运行方式,引导它申请尽可能少的、粒 度尽可能小的锁。这里也要做语句调优。  在做这些调优的时候,首先要对目标语句做估算,看看它优化的空间有多大。有些语句本身比较简单,可以通过调整索引的方法迅速提高性能,这样的调优是很值得 做的。有些语句非常复杂,或者返回的结果集很大,通过调整SQL SERVER这里的设置,提高性能的空间往往不大。这个时候就要考虑,语句本身是不

68、是能够换一种方法实现。很多时候改一下语句,把一条大的语句拆分成若干 条小的语句,或者去掉一些不必要的逻辑,会达到事半功倍的效果  在谈论如何做语句调优的具体方法之前,必须先介绍一下最必需的背景知识。不了解这些知识 ,做语句调优就只能基本靠猜。所需要的背景知识主要包括理解索引和统计信息,理解什么是统计和重编译,并且能够基本读懂语句的执行计划。以下为例子,借助 MS示例数据库AdventureWordks来介绍。-测试用例USE AdventureWorks2008GOIF OBJECT_ID ('SalesOrderHeader_TEST') IS NOT N

69、ULL DROP TABLE dbo.SalesOrderHeader_TESTGOIF OBJECT_ID ('dbo.SalesOrderDetail_TEST') IS NOT NULL DROP TABLE dbo.SalesOrderDetail_TESTGO- (31465 行受影响)SELECT * INTO dbo.SalesOrderHeader_TESTFROM Sales.SalesOrderHeader- (121317 行受影响)SELECT * INTO dbo.SalesOrderDetail_TESTFROM Sales.SalesOrderDe

70、tail- 建立聚集索引CREATE CLUSTERED INDEX SalesOrderHeader_TEST_CL ON dbo.SalesOrderHeader_TEST(SalesOrderID)- 建立非聚集索引CREATE NONCLUSTERED INDEX SalesOrderDetail_TEST_NCL ON dbo.SalesOrderDetail_test(SalesOrderID)goSalesOrderHeader_TEST 里存放的是每一张订单的头信息,包括订单创建日期、客户编号、合同编号、销售员编号等,每个订单都有一个单独的订单号。在订单号这个字段上,有一个聚集索引。SalesOrderDetail_TEST 里存放的是订单的详细内容。一张订单可以销售多个产品给同一个客户,所以

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论