绝大多数输出都来自图中的执行端,而且输出结果也真正出自表达式服务。“表达式服务”库是进行数据转换、谓词评估(过滤)以及算法计算的组件。它还利用了 ODS 层,把输出结果格式化为 TDS 消息。
还有几个组件,我们只是在这里简单地提一下,这些组件在关系引擎内部提供附加服务。这些组件中的一个是目录服务组件,用于数据定义语句,例如 CREATE TABLE、CREATE VIEW 等。目录服务组件主要放在关系引擎中,但是实际上大约有三分之一的目录服务组件是在存储引擎中运行的,所以可以看作是共享组件。
关系引擎中的另一种组件是“用户模式调度程序 (UMS)”,这是 SQL Server 自己内部的纤程和线程规划器。把任务分配给纤程或线程是一种非常复杂的内部机制,取决于对服务器如何配置,以及在 SMP 系统中允许 SQL Server 进行处理器之间的适当的负载平衡。UMS 还可以避免 SQL Server 由于同时运行太多的线程而导致性能过低。最后,还有大家熟悉的系统过程,逻辑上它们也属于关系引擎的一部分。这些组件肯定不是服务器代码,因为可以很容易地使用 sp_helptext 检查定义这些过程的 Transact-SQL 代码。但是,系统过程被作为服务器的一部分来对待,因为系统过程的用途是显露重要的服务器能力,像系统表一样,以供应用程序在更高的层次上和更适当的层次上使用。如果应用程序开发人员将较高层次的系统过程 — 更容易使用 — 作为一种接口,即使随着版本的更新,原始层次上的系统表发生变化时,应用程序仍然可以继续使用。
处理 SQL 语句时的客户机/服务器交互
下面我们将讨论当客户机应用程序与 SQL Server 交互时客户机的动作。以下是一个 ODBC 调用的例子:
SQLExecDirect(hstmt, "SELECT * FROM parts where partid = 7", SQL_NTS)
(OLE-DB 也有一个与这个调用几乎直接等价的调用,此处不再讨论这个调用,因为这个调用实际上与 ODBC 调用相同。)该 ODBC 调用取一个 SQL 语句,然后将其发送给 SQL Server 来执行。
在这个具体的查询语句中,我们从零件表中提取具有特定零件标识号的所有行。这是特定 SQL 的一个典型例子。在 SQL Server 7.0 以前的版本中,特定的 SQL 与存储过程的一个显著差别是,查询优化器所生成的计划从不缓存。查询语句要被读入、编译、执行,然后再抛弃计划。在 SQL Server 7.0 中,正如稍后还要讨论的,实际上提供了可以缓存特定查询语句的计划的机制。
在这条语句被送往 SQL Server 之前,还必须要问几个问题。所有客户机程序都要提供某种游标说明,所以客户机程序在内部必须询问的一个问题是,程序员请求的是什么样的结果集或什么样的游标。最快的类型是在文档中被称为默认结果集的游标。这种游标由于历史上的原因被称为消防站游标,有时甚至根本不把它作为游标看待。当 SQL 请求被送到服务器之后,服务器开始把结果返回给客户机,这个返回结果的过程持续进行,直到把全部数据集发送完毕为止。这就像一个将数据抽给客户机的大型消防站。
一旦客户机程序确定了这是默认结果集,则下一步就是确定是否有参数标记。使用这个 ODBC SQLExecDirect(以及 OLE-DB 中等价的调用)调用的选项之一是,不是在 WHERE 从句中给出像 7 这样的具体值,而是可以用一个问号来传递参数标记,如下所示:
SQLExecDirect(hstmt, "SELECT * FROM parts where partid = ?", SQL_NTS)
请注意,您必须分别提供实际的参数值。
客户机需要知道 SQL 语句中是否有参数标记,或者它是否为真正特定的非参数化 SQL。这将影响到客户机将用这个语句在内部做什么,并确定将什么作为消息真正发送给 SQL Server。在没有问号时,很明显,客户机只想将这个请求作为 SQL Language TDS 消息发送,然后客户机将位于流水的末端,并将结果返回。然后客户机能将结果返回给基于应用程序参数的应用程序。客户机的内部处理选择会模糊一点,这取决于您通过 ODBC 或 OLE DB API 请求什么。例如,应用程序不直接请求默认结果集。相反,在 ODBC 中,如果请求一个只读的、只向前的且每次只给出一行的游标,那么对于客户机内部运行来说,这就是在定义流水游标(默认结果集)。
流水游标有一个主要问题。除非客户机已将所有的行全部接收完毕,客户机不能将任何其他 SQL 语句向下发送给服务器。因为结果集可能有很多行,所以有些应用程序使用流水游标时不能顺利运行。后面将要描述的只向前的快速游标,是 SQL Server 7.0 版的一个新特点,尤其适合于处理这种情况。
在 SQL Server 7.0 版之前,SQLExecDirect 调用在很大程度上是以相同方式处理的,而不管是否用参数标记来代替常数。如果您定义一个参数标记,客户机将实际取您通过不同调用提供的值(本节的开始示例中的值“7”),并将它插入问号处。然后,使用代替值的新语句被向下发送,作为一个特定的 SQL 语句。在服务器上使用参数化的 SQL 没有任何好处。
然而,在 SQL Server 7.0 版中,如果 SQLExecDirect 使用了参数标记,向下发送给 SQL Server 的 TDS 消息便不是 SQL 语言消息。相反,它被下发给使用 sp_executesql 过程的服务器,所以,就 TDS 协议来说,它是 RPC。在客户机上,结果基本上相同。客户机将取回数据流水。
如果您不想取回这个数据流水,则可以始终使用块游标或可滚动游标。在这种情况下,数据流变得大不相同。调用是对通过 SQL 文本中的 sp_cursoropen 输入点(这些虚拟存储过程之一)进行的。该 sp_cursoropen 利用 SQL 来增加附加逻辑,以使其滚动,它潜在地将某些结果重定向到一个临时表,然后用句柄给游标一个响应,表明游标现在是打开的。仍然在程序员的控制之外,客户机调用 sp_cursorfetch,将一行或多行转到客户机上,然后返回到用户应用程序。客户机还可使用 sp_cursor 来重新配置游标,或改变某些统计数字。在您处理完游标之后,客户机将调用 sp_cursorclose。
让我们看一个简单的情况,即只返回一行给客户机。至于默认的结果集,需要从客户机到服务器往返发送一次消息。SQL 消息(或 sp_executesql)向下发往服务器,然后结果返回来。在同一行(非流水)的游标情况下,您会看到传统情况下能用 SQL Server 看见的东西。一个往返行程用于打开,一个往返行程用于取得数据,一个往返行程用于关闭。这个过程使用消息的次数是默认结果集使用的三倍。在 SQL Server 7.0 中,有一种所谓只向前的快速游标, 它使用同样的游标结构。它与流水的表现不一样,因为在发送任何附加 SQL 消息之前,它不需要您处理全部结果行。所以,如果您带回 5 行,还有更多的数据,您仍能将更新向下发送给服务器。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




