图35-3 完整的 Query Analyzer 查询
检视执行计划和修改 T-SQL 陈述式
Query Analyzer 也可以用来检视执行计划,这个执行计划是 Query Optimizer 为您的 T-SQL 陈述式所做的选择。这个特性可帮助您判断 T-SQL 陈述式是否有效率,并确定应该选择哪条执行路径和数据存取路径。然后您可以修改 T-SQL 陈述式和数据库架构,检查效能是否得以提高。要使用 Query Analyzer 来检视 T-SQL 陈述式的评估执行计划,请按照下列步骤操作:
1. 在 Query Analyzer 窗口键入需要 Query Analyzer 评估的 T-SQL 陈述式后,按下 显示评估的执行计划 按钮(这个按钮在数据库选择下拉式清单的右边),或者按Ctrl+L,显示 评估的执行计划 窗格,如图35-4。在这个窗格中,查询透过图形来描述,每个操作的消耗与资料存取的方法都在此显示。在图35-4的窗格中,出现索引名称 Customers.PK_Customers,表示丛集索引 Customers.Pk_Customers 被用来存取资料。
图35-4 评估的执行计划窗格
2. 评估的执行计划 窗格中还提供其它附加数据。要检视操作的附加数据,请将鼠标光标移动到操作图标上。就会出现一个弹出窗口,其中包含附加数据,如图35-5所示。
图35-5 检视关于操作的附加数据
这个弹出窗口包含下列信息:
o 实体作业 查询所执行的操作,例如索引扫描、联结和总计等等。如果实体操作被显示为红色,那是 Query Optimizer 发出的警告,这时您应该固定 T-SQL 陈述式。
o 估计的数据列记数 预估由操作检索的列数。
o 估计的数据列大小 需要检索的列的估计大小。
o 估计的I/O耗用/估计的CPU耗用 由该操作占用的估计 I/O 资源和 CPU时间。越低的值意味着该 T-SQL 陈述式越有效率。
o 估计的执行数 该操作在 T-SQL 陈述式中执行的次数。
o 估计的耗用 由 Query Optimizer 决定的操作消耗。这个消耗显示为T-SQL 陈述式的总消耗百分数。
o 估计的子树耗用时间 执行前面部分和这一部分 T-SQL 陈述式的消耗。如果存在多个子树,这个选项允许您检视执行每个子树的消耗。
o 自变量 T-SQL陈述式使用的自变量。
________________________________________
说明
执行计划(execution plan)描述了 Query Optimizer 如何选择执行 T-SQL 陈述式,并包括步骤的次序和所使用的操作类型。数据存取方法(Data Access Method)是描述数据库对象(数据表、索引等)如何被存取的一种对象。这两者是相关联的,因为在有些时候,数据存取方法被考虑为执行计划的一部分。当然也可以单独的考虑。
________________________________________
接下来将看到使用 Query Analyzer 较为复杂的范例。范例显示低效率的 T-SQL陈述式对效能的影响:减慢响应时间,并占用其它程序的系统资源。现在先看一个使用 Query Analyzer 检视和修改 T-SQL 陈述式执行计划的范例。修改 T-SQL 陈述式能达到较好的效能。在许多情况下,可以建立更有效、功能更佳的 T-SQL 陈述式。接下来会说明几种 T-SQL 陈述式,它们属于较复杂的预估执行计划类型。
这些范例使用 Northwind 数据库中的 Orders 数据表。现在来检视这个数据表的组织。这个信息会帮助确定 Query Optimizer 是否选择了适当的执行计划。Orders 数据表在 OrderID 一栏中有一个名为 PK_Orders 的丛集索引,另外还有八个其它的索引,如图35-6中的 Manage Indexes 对话框所示。(要存取这个对话框,请在 Enterprise Manager中,展开一个服务器组,展开一个服务器,展开 数据库 数据夹,展开 Northwind 数据库,然后选取 数据表 数据夹。在右侧窗格中的 Orders 数据表上按鼠标右钮,并从快捷菜单中选择 所有工作 ,接着选择 管理索引 。或者只要从 Query Analyzer 工具 菜单中直接选择 管理索引 ,接着从下拉式菜单中选择 Orders 数据表。)
图35-6 管理索引对话框
检视计划和修改 SELECT 陈述式
本节中,这个查询的范例要求获得关于订单的信息,这些订单是由职员 ID 为 4的职员储存的。请在 Qery Analyzer 输入以下查询,并执行 显示评估的执行计划 :
SELECT OrderID, CustomerID, EmployeeID, OrderDate
FROM orders
WHERE EmployeeID = 4
在该职员的组织中,每个职员处理订单的一小部分,因此可能需要 SQL Server在进行查询时使用 EmployeeID索引。但是,Query Analyzer 显示的却是 SQL Server 使用的存取方法是 PK_Orders 丛集索引,如图35-7中的 评估的执行计划 窗格所示。
图35-7 评估的执行计划窗格显示了使用 PK_Orders 丛集索引。
要 Query Optimizer 使用 EmployeeID 索引,可以使用 SELECT 陈述式的提示(hint),程序代码如下(提示将在本章的 <使用提示> 一节中讨论。):
SELECT OrderID, CustomerID, EmployeeID, OrderDate
FROM orders WITH (INDEX ( EmployeeID))
WHERE EmployeeID = 4
________________________________________
说明
在 SQL Server 7 中,较好用的索引提示是 INDEX=index_name。
在 SQL Server 2000 中,较好用的索引提示是 INDEX(index_name)。
________________________________________
透过这个信息,可以指示 Query Optimizer 使用所需要的执行计划,而不是 Query Optimizer 选择的计划。调整过的评估执行计划窗格如图35-8所示。可以从显示的数据存取方法中看到,使用的是 EmployeeID 索引,然后传回一个书签搜寻(bookmark lookup),该查询将获得来自数据库的数据。(书签搜寻搜索一列数据的内部识别码。)
图35-8 调整过后的评估执行的计划窗格
Query Optimizer 是一个有效率的工具,以不断的更新统计数据,提供选择最佳的执行计划。由于不同的公司行号可能更清楚自己的组织和数据,所以某些情况下,公司可以选择比 Query Optimizer 更有效率的最佳执行计划。
________________________________________
注意
使用提示代替 Query Optimizer 的选择时,必须承担变更可能带来的风险。虽然数据遗失或损毁的机率不大,不过可能对系统的执行效能产生的是负面的影响。
________________________________________
检视联结操作
执行联结操作比执行选取操作多出了更过的执行过程,稍后会在评估执行的计划窗格中看到。联结操作会对数个数据表进行存取的动作,并在存取后组合所搜寻的数据。(联结在 第 14 章 中讨论)。请在 Query Analyzer 输入以下的联结操作范例:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
LastName, OrderDate
FROM Orders Join Employees ON Orders.EmployeeID = Employees.
EmployeeID
之前的陈述式包括 SQL-92 JOIN 操作元。建议使用此操作元在 SQL Server 2000中执行连结。下面的陈述式使用较传统的连结语法:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
LastName, OrderDate
FROM Orders, Employees
WHERE Orders.EmployeeID = Employees.EmployeeID
T-SQL 陈述式在 EmployeeID 资料行中联结了 Orders 和 Employees 资料表。评估执行计划结果如图35-9所示。
图35-9 显示在评估执行的计划窗格的联结操作
在窗格中可以看到两个子树中哪个的消耗较大,也可以看到规划联结操作的类型。SQL Server 支持多种不同的联结操作,包括杂凑联结(hash join)、巢状循环联结(nested loops join)和合并联结(merge join)。复杂的联结操作,执行计划会相对的变得复杂。由于您的目的是要减少占用 CPU 时间总量,以及减少执行 I/O 操作的数目,所以必须判断是否使用了好的执行计划。有时可以使用提示来指定需要使用的特殊索引,从而减少 CPU 和 I/O 行为。在这个查询中,由于联结是指定在 WHERE 子句中的唯一操作,这个执行计划应该是最适合的。
检视总计操作
下面显示的 T-SQL 陈述式执行连结操作和总计操作,请在 Query Analyzer 中输入:
SET QUOTED_IDENTIFIER ON
GO
SELECT CustomerID, SUM("Order Details".UnitPrice)
FROM Orders JOIN "Order Details" ON Orders.OrderID = "Order
Details".OrderID
GROUP BY CustomerID
________________________________________
说明
因为数据表名称 Order Details 包含了一个关键词和一个空格,所以必须使用选项 SET QUOTED_IDENTIFIER ON。要获得更多关于这个选项的信息,请参阅《在线丛书》索引中的 SET QUOTED_IDENTIFIER。
________________________________________
这个复合操作的评估执行的计划窗格显示在图35-10。
图35-10 显示在评估执行的计划窗格中的总计操作
检视预存程序
要显示预存程序的执行计划,可以简单的在 Query Analyzer 中呼叫预存程序。Query Analyzer 会显示所呼叫预存程序的评估执行计划,如图35-11所示的 sp_who。(需要注意的是,预存程序的执行计划相当复杂)。即使不确定组成预存程序的 T-SQL 陈述式,也可以显示该预存程序的执行计划。
图35-11 在评估执行的计划窗格中的预存程序
使用对象浏览器
对象浏览器(Object Browser)包含在 SQL Server 2000 中,用来提升 Query Analyzer 的功能。启动 Query Analyzer 时,会在左边窗口看到 对象浏览器 。 对象浏览器 分成数据库对象区和通用对象区两部份。在数据库对象区,可以浏览像数据表和检视表等对象;在通用对象区,可以存取系统对象和菜单。可以利用 物件浏览器 找出所提供的信息后,然后决定用的信息。
数据库对象
对象浏览 顶端部份含有数据库对象,可以立即看到预设数据库以及所建立的数据库,并显示所属的 SQL Server。想要知道在 对象浏览 之中有哪些可用信息,只要展开对象即可。先展开 Northwind 数据库,然后展开 使用者数据表 。现在可看到 Northwind 数据库中可用的数据表,如图35-12所示。
图35-12 检视对象浏览中的数据表
接着展开一个使用者定义数据表,然后展开包含关于字段、索引、条件约束、资源依存性、触发程序信息的数据夹。图35-13显示展开的 Orders 数据表。或者可以展开数据夹,检视关于系统数据表、检视表、预存程序、功能和使用者定义数据类型的信息。
在 Query Analyzer 中提供对象信息,是相当方便的,这样在建立 SQL 陈述式和预存程序时,就不需要再检查 Query Analyzer 以外的对象信息。不但可以在 对象浏览 中检视信息,还可以编辑对象、拖曳对象,甚至可以建立指令码和修改对象,将功能加在一个已经很实用的工具中。
图35-13 展开在对象浏览中的数据表
通用对象
在 对象浏览 较下面的部份是名为通用对象(Common Objects)的数据夹,这个数据夹中包含了如设定功能、光标功能、日期和时间功能以及数学功能等对象信息的数据夹。因此您可以很快地存取一个要使用的功能而不须查询语法。在这个区域展开数据夹的话,将显示设定选项,如图35-14所示。将这些功能拖曳到 Query 窗格中,或者用鼠标点选这个功能以显示一个简要描述。这对于 ad-hoc 查询过程是相当方便的。
图35-14 在对象浏览的通用对象中展开一个数据夹
除了存取全域变量之外,您还可以存取很多其它有用的快捷菜单,如数学和字符串功能。继续展开对象,您可以用这些菜单得到参数要求的信息。例如,图35-15显示展开 数学函数 中的 参数 数据夹。
图35-15 检视对象浏览中的参数数据夹
使用SQL Profiler
除了 Query Analyzer 以外,SQL Profiler 工具也可以帮助找出低效率的 T-SQL陈述式。Profiler 可以显示所有系统中执行的 T-SQL 陈述式,并用图形加以显示。您也可以使用多种排序和筛选选项,找出使用了最多 CPU 和 I/O 资源的 T-SQL 陈述式。有了这些信息就可以确定在调整系统时需要集中焦点在哪些 T-SQL 陈述式上。对于透过应用程序呼叫的 T-SQL 陈述式,可以检视 T-SQL 陈述式,并决定利用存取应用程序来源程序代码时的效率如何。
SQL Server 2000 中的 Profiler 工具类似 SQL Server 7 中的 Profiler 工具,当然有些加强的功能。其中一项新功能是引用追踪模板,用来建立追踪档案。(在确定能够使用这个功能追踪 SQL Server 之后,追踪才能建立)。在 SQL Server 7 中,追踪功能只能以手动建立。
要呼叫 Profiler 工具并执行追踪,请遵循下列步骤:
1. 按一下 开始 / 程序集 / Microsoft SQL Server / Profiles 。在 Profiler 刚出现时,会看到一个空的 Profiler 窗口。在 Profiler 中如果没有打开任何窗格,就不会剖析任何陈述式。
2. 要开始分析,必须选择已存在的追踪模式,或是建立一个新的追踪模式。(启动过程将在步骤4介绍)。SQL Profiler 提供数种追踪模式。使用这些功能由于不必从 scratch 建立追踪,因此节省不少时间。要检查追踪清单,请在 档案 菜单中点选 开启旧档 ,选择 追踪模板 ,显示 开启旧文件 对话框,如图35-16所示。
图35-16 开启旧文件对话框中显示可用的追踪
SQL Server 中的追踪描述如下:
o SQLServerProfilerSP_Counts.tdf 统计已经执行预存程序的数量。这个结果将根据预存程序的名称进行分组,其中包括程序所执行的次数。
o SQLServerProfilerStandard.tdf 收集关于连结点的信息,执行预存程序,以及依序执行 SQL 批次檔。
o SQLServerProfilerTSQL.tdf 收集所有的 T-SQL 陈述式传送至 SQL Server 的次序且依使用者团体分类传送。这个追踪包含了 T-SQL 陈述式以及它所执行的时间。
o SQLServerProfilerTSQL_Duration.tdf 显示执行的 T-SQL 陈述式,以及这些 T-SQL 陈述式执行所用的时间(一千分之一秒为单位)。
o SQLServerProfilerTSQL_Grouped.tdf 收集与 SQLServerProfilerTSQL 追踪类似的数据,但是根据传送陈述式的使用者来将数据分组。
o SQLServerProfilerTSQL_Replay.tdf 提供关于已经执行的 T-SQL 陈述式的详细信息。该追踪提供可以用来重新执行 Query Analyzer 中 T-SQL 陈述式的数据。
o SQLServerProfilerTSQL_SPs.tdf 显示预存程序以及预存程序中的 T-SQL指令。该结果根据陈述式执行的时间依序显示。
o SQLServerProfilerProfilerTuning.tdf 收集关于预存程序和执行 SQL 批次文件的数据。
这些追踪相当有用。例如 SQLServerProfilerTSQL_Duration 追踪可找出哪些T-SQL 陈述式花费了大量的执行时间。这些信息使您可以开始最佳化查询。一个陈述式执行得很慢,可能是因为它的工作量很大,或者效率很低。在下一个步骤中将说明,必须使用每个追踪的预设定义。
3. 要启动追踪,请选取 档案 / 新增 ,接着选择 追踪 。显示 联机到SQL Server 对话框,如图35-17所示。在这个对话框中,选择要追踪的 SQL Server 系统,然后按 确定 。
图35-17 联机到SQL Server对话框
4. 进入 追踪属性 窗口,如图35-18所示。在 一般 页签,可以命名并选择追踪的起始点。本范例是选择 SQLServerProfilerTSQLDuration 追踪。在页签下面的部份,可以指定是否要将获得的追踪内容输入到档案或 SQL Server 数据表中。如果没有选择这些选项,那么追踪将只在屏幕上出现。另外,可以指定追踪完成的时间,这在执行长时间追踪时相当有用。
图35-18 追踪属性窗口的一般页签
5. 接着选择 事件 页签,如图35-19所示。这里可以选取一个或多个追踪记录的事件。大量的类型和特殊的事件可以被追踪,列在 可用的事件类别 清单中的数据均可追踪。
图35-19 追踪属性窗口的事件页签
6. 选择要追踪的事件后,点选 数据行 页签,如图35-20所示。在这个页签中,指定在追踪过程中要收集哪些数据。这个数据包括终止时间、对象 ID 等等。
图35-20 追踪属性窗口的数据行页签
7. 选取 筛选器 页签,如图35-21所示。这个页签中可以指定是否要撷取事件所需的条件。例如,排除追踪 Profiler(默认值)。透过排除 SQL Server 过程,可以避免 Profiler 窗口的混乱,增加阅读性。
图35-21 追踪属性窗口的筛选器页签
8. 完成设定选项后,按 执行 启动追踪。如果要修改追踪,建议使用 档案 菜单中的 另存新文件 选项来保存追踪修改(用不同的名称)。一旦开始追踪,事件将会出现在 Profiler 窗口。使用本例中所选的追踪,事件将会用 Duration 排序(千万分之一秒)。图35-22显示 Profiler 窗口执行中的追踪。
________________________________________
注意
在繁忙的环境中,Profiler 可能会使用重要的系统资源。追踪越多的事件,会占用越多的系统资源。
________________________________________
最佳化 T-SQL 陈述式
在前面的章节中学到了使用 Profiler 检视系统中所执行的 T-SQL 陈述式,以及利用 Query Analyzer 确定执行计划和数据存取。也可以利用修改 T-SQL 陈述式来改善效能。拥有这些工具,就有能力修改 T-SQL 陈述式,改善陈述式的执行效能。在本节中,会看到最佳化 T-SQL 陈述式的多种途径,使其能够提供更好的效能或占用更少的系统资源。
图35-22 执行中的追踪
最佳化执行计划
修改执行计划是相当困难的,要建立一个比 Query Optimizer 的计划更佳的执行计划更不容易。有些操作更可能在执行计划的修改中获益,它们是 JOIN、GROUP BY、ORDER BY 和 UNION。对于这些操作的修改可以容易的透过使用提示来达成,这将在稍后的 <使用提示> 一节中提到。透过更改提示和显示 Query Analyzer 的输出,可以看到获得了一个比较有效的操作。
不过,对于最佳化 T-SQL 陈述式并没有一个特定的模式。因为每个数据库都是独一无二的,且应用程序也不相同,因此修改皆根据不同的情况进行。
选择数据存取方法
正如本章前面所述,数据存取方法实际上就是一组对象,SQL Server 使用这些对象从数据库中获得数据。透过分析数据库和数据库中包含的数据,可以最佳化数据存取方法,减少 I/O 操作的数量。
和修改执行计划一样,修改最佳的数据存取方法也没有一定的公式。下面的指导方针有助于选择最佳的数据存取方法:
• 使用最佳的索引 为一个操作使用最佳的索引,这在获得可能的最佳效能时是必须的。对于特定操作的最佳索引是最快速的找到数据,且最少 I/O 操作的一种方法。可以利用您对数据库和数据的深入了解或使用 Query Analyzer 来确认最佳的索引。Query Analyzer 让您尝试不同的模拟状况以确定哪个索引可以传回最少的列数。(记住,Query Analyzer 只是简单的估计了所要传回的列数;要确定精确的列数,必须使用 Profiler。)
________________________________________
说明
正如 第 17 章 所提到的,索引对于 SQL Server 有很大的好处,但是如果使用不正确,可能会反过来影响效能。监控每个数据表的索引数目,特别是在执行了很多 INSERT、UPDATE 和 DELETE 陈述式操作的时候。太多的索引可能会导致这种类型操作的效能降低,这是由于修改索引的额外系统资源占用所引起的效能降低。
________________________________________
• 使用覆盖式索引 (covering indexes) 正如 第 17 章 所述,使用覆盖式索引可以帮助您避免额外的 I/O 步骤。不必存取底层数据表,您可以从索引中获得所需的数据。
• 减少传回的数据列 决定是否需要从查询传回实际需要的所有数据。修改T-SQ L陈述式,以便于只存取需要存取的数据,不要传回将被丢弃的资料列。减少从数据库中获得的数据列,这可以透过增加查询的选择性来达成。
使用提示
可以修改 T-SQL 陈述式来更改资料存取方法和执行计划,但是如果执行时不够不谨慎,反而会变更 T-SQL 陈述式的功能。较安全的最佳化 T-SQL 陈述式的方法是使用提示。提示可指定 Query Optimizer 要执行哪些操作和需要使用哪些对象。在本节中,将学习很多不同的 SQL Server 提示,以及它们的使用方法。
联结提示
联结提示(join hints)是用来指定 Query Optimizer 应该执行哪些类型的联结操作。(如果在查询中没有指定类型,Query optimizer 会自己选一个。)在 SQL Server 中,您可以执行巢状循环联结(nested loops joins)、杂凑联结(hash joins)、合并联结(merge joins)和远程联结(remote joins)。使用下列提示指定联结的方法:
• LOOP 指定巢状循环联结。在巢状循环联结中,将会检查外部数据表中的每一列和内部数据表中的每一列,检查值是否相等。
• HASH 指定杂凑联结。在杂凑联结中,一个数据表会被重新组织为一个杂凑数据表。其它的数据表每次被扫描一列,杂凑函数就被用来搜寻相同的内容。
• MERGE 指定一个排序合并联结。在排序合并联结中,每个数据表都被排序,然后按照降序每次比较一列。
• REMOTE 指定远程联结。远程联结是至少有一个联结的数据表在远程。
看看连结提示的范例,使用我们前面的范例(请参阅本章中的 <联结操作> 一节),我们按照下列陈述式使用提示来指定一个杂凑联结:
SELECT OrderID, CustomerID, Employees.EmployeeID, FirstName,
LastName, OrderDate
FROM Orders, Employees
WHERE Orders.EmployeeID = Employees.EmployeeID
OPTION (HASH JOIN)
________________________________________
说明
联结提示是彼此独立的-每次只能使用其中的一种。
________________________________________
如果选择使用 SQL-92 语法作为连结,您也能用提示来指定连结类型。使用SQL-92 语法,您可以重写之前的查询,如下:
SELECT OrderID, CustomerID, Employees.EmployeeID, Firstname,
LastName, OrderDate
FROM Orders INNER HASH JOIN Employees
ON (Orders.EmployeeID = Employees.EmployeeID)
联结提示是进阶的主题,我们并不能提供使用的经验方法。有很多不同的选择特殊联结操作的原因,例如同等运算子的数目、在联结中每个数据表的大小,以及联结的多少数据表。有一种最佳的途径可以确定更改联结操作是否将提供额外的效能,就是在 Query Analyzer 中尝试每一种类型的联结,看看哪种可以提供最小的消耗。当然,Query Optimize r通常会为帮助选择最佳的联结操作。
查询提示
共2页: 上一页 1 [2] 下一页