手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>VB>列表

Microsoft SQL Server 查询处理器的内部机制与结构

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

SQL 语句本身由典型的查询优化器来处理。优化器必须把基于集合的 SQL 语句的非过程化的请求,翻译成可以被高效执行并返回所需结果的过程。除非特别说明,我们在以下讨论编译时,均指 TSQL 的编译和 SQL 语句的优化。

上面已经提到,编译和执行是两个不同的查询处理阶段,因此,优化器完成的工作之一是基于相当稳定的状态进行优化。您可以注意到,SQL Server 可能会根据语句所满足的条件重新编译,所以状态并不是永远稳定的,但也不是处于不停的变化之中。如果优化器使用的信息变化太剧烈、太经常 — 并发处理器的数量和锁的数量不稳定 — 则必须不断重新进行编译,而一般来说编译是比较耗时的。例如,SQL 语句的运行时间为百分之一秒,而编译可能需要占用半秒。最理想的情况是,SQL Server 能够只编译语句一次,而执行成千上万次,不必每次执行该语句时都重新编译它。

编译阶段的最终产品是查询计划,放在过程缓存中。便宜的特定 SQL 计划并不放在缓存中,不过这只是个小问题。我们不希望缓存被不太可能重复执行的内容占满,一般来说,特定 SQL 语句的计划是最不可能反复使用的了。如果语句编译已经很便宜(小于百分之一秒),则没有必要再把计划放入缓存,用不太可能重新使用的计划占用缓存。

把计划放入缓存之后,SQL Manager 按照执行要求逻辑进行检查,确定是否有更改的内容,是否需要重新编译。即使编译到执行之间时间间隔只有几毫秒,也可能有人会执行一条数据定义语句 (DDL),为关键的表加了索引。这种可能性不大,但是确实存在,因此 SQL Server 必须考虑这一点。有几种情况 SQL Server 必须重新编译存储规划。元数据的修改,例如增加或删除索引,是重新编译的最主要的原因。服务器必须确信所使用的计划反映了索引的当前状态。

重新编译的另一种原因是统计情况发生变化。SQL Server 还维护不少数据使用频率的统计信息。如果数据使用频率分布情况变化很大,则可能需要另一个查询计划以便更有效地执行。SQL Server 跟踪表数据插入和删除的统计数据,如果数据修改的数量超过根据表的容量变化的某一阈值,则需要根据新的分布数据重新编译计划。

图 7 给出了编译和执行过程的流程。

图 7. 编译与执行

注意,实际参数的改变并不会导致重新编译,环境的改变,例如可用内存的增加或所需数据的增加,也不会导致重新编译。

执行是比较简单的,如果需要执行的查询很简单,如“插入一行”,或从带有唯一索引的表中查询数据,则执行处理会非常简单。但是,很多查询都要求大量的内存以提高运行效率,或至少从所增加的内存得到好处。在 SQL Server 6.5 中,每个查询能够使用的内存限制在 0.5MB 或 1MB 以下。有一个控制查询内存使用的参数,称为排序页。顾名思义,它主要是限制可能占用大量内存的排序操作。不管要处理的排序有多大,在 SQL Server 6.5 中,内存的使用不能超过 1MB。即使您使用的机器上配置了 2GB 内存,需要对数百万行数据排序,也不能突破限制。显然,复杂的查询不能高效执行,因此 SQL Server 开发人员增加了 SQL Server 7.0 的能力,使得单个查询可以使用大量的内存。

另一个问题随之而来。一旦您开始允许查询使用大量内存,就必须确定如何把内存分配给可能需要内存的很多查询。SQL Server 按照以下方法解决这个问题。当查询计划优化之后,优化器要确定有关给该查询使用的内存的两部分信息。第一,该查询有效执行所需要的最小内存,该参数与查询计划一起存放。优化器还要确定该查询可以获益的最大的内存量。例如,如果要排序的整个表只有 100MB,分配 2GB 内存就没什么帮助了。您需要的只是 100MB,这个最大有用内存参数随查询计划一起存放。

当 SQL Server 开始执行计划时,该计划被传递给一个所谓内存授权调度程序的例程中。这个授权调度程序要完成几项有趣的工作。首先,如果授权调度程序要处理的查询在计划中没有排序或杂凑操作,则 SQL Server 知道该查询不会需要很多内存。在这种情况下,不需要内存授权调度程序进行判断。该计划会立即执行,因此典型的事务处理请求会完全旁路这种判断机制。内存授权调度程序还设有多个队列处理不同容量的请求。内存调度程序优先处理较小的请求。例如,如果有一个查询要求“提取前 10 个”,并且只需要对 20 行排序,则虽然需要经过内存授权调度程序,但是要释放该查询并且很快调度。服务器需要并行或并发执行许多这种查询。

如果有很大的查询,您希望一次只运行几个查询,让它们占有所需的更多内存。SQL Server 确定一个由 4 X(系统中的 CPU 个数)得到的数。如果可能,SQL Server 会同时运行那个数量的查询,为它们分配高效运行所需要的最小内存。如果还剩有内存,则一部分查询会允许占用最大高效内存。SQL Server 试图既为查询分配尽可能多的内存,又让尽可能多的查询同时运行在系统中。

能够使用最大高效内存对某些操作很重要,例如夜间运行的批处理过程。您可能会生成很大的报表,或重新建立索引。这些查询可能使用大量内存,这种机制可以动态调整对内存的需求。因此,如果如果在队列中等待处理的查询不多,则内存授权调度程序会经常分配给查询最大需要的内存。如果白天的机器负载很重,则就不能同时运行太多的查询。这些查询会得到有效运行所需最小的内存,让内存为更多的查询共享。

一旦调度程序说现在可以为请求分配内存,则计划即被“打开”,开始实际运行。计划会一直运行直到完成。如果查询使用了默认结果集模型,则计划会一直运行到检索到所有结果为止,然后把结果返回给客户机。如果使用的是游标模型,则处理过程略有不同。每个客户机请求只提取一块数据,并不是所有数据。当每个结果块返回给客户机之后,SQL Server 必须等待客户机的下一个请求。在等待时,整个计划就会睡眠。这意味着要释放一些锁,要释放一些资源,并保留一些断点信息。这些断点信息使得 SQL Server 能够返回到睡眠之前的状态,使得执行可以继续。

过程缓存

我们在前面已经多次提到 SQL Server 的过程缓存。需要注意的是,SQL Server 7.0 的过程缓存与以前的版本有很大不同。在早期的版本中,有两个有效配置值用于控制过程缓存的容量:一个是定义 SQL Server 总可用内存的固定容量,另一个是供存储查询计划使用的内存百分比(扣除满足固定需要的内存)。在老版本中,特定 SQL 语句从不存入缓存,只有存储过程计划才存入其中。在 SQL Server 7.0 中,内存的总容量是动态的,用于查询计划的空间也是经常变化的。

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!