摘要:本文介绍了在客户机上处理 Microsoft SQL Server 查询的方式,各种客户机与 SQL Server 的交互方式,以及 SQL Server 在处理客户机程序的请求时需要完成的工作。
简介
Microsoft(R) SQL Server(TM) 内部机制和结构是一个非常大的主题,因此本文仅限于程序开发人员感兴趣的问题,集中研究其他源中没有彻底讨论的问题。在讨论 SQL Server 的结构时,我们主要观察客户机的处理过程,研究不同的客户机程序与 SQL Server 的交互方式,以及 SQL Server 如何处理客户机的请求。还有一些讨论 SQL Server 其他方面的信息源,特别是 Microsoft Press 出版的 Inside SQL Server 7.0,作者是 Ron Soukup 和 Kalen Delaney,这本书非常详细地讨论了 SQL Server 存储引擎的内部机制和处理方法,不过对查询处理器的讨论不够深入。本文正填补了这个空白。
我们期望本文有助于读者编写出更好的应用程序。通过本文,读者会在提高程序性能方面得到新的启发,产生新的理解。
SQL Server 是一种客户机/服务器系统
多年来,SQL Server 一直被认为是一种客户机/服务器系统。事实上,Sybase DataServer(以此为基础开发了原始的 SQL Server)正是第一个作为客户机/服务器系统开发的商用关系数据库系统。那这又说明了什么呢?这不只意味着 SQL Server 是一个双层系统。从传统上看,双层系统意味着客户机应用程序运行在一台机器上,向另一台计算机上的服务器发送请求。而对于 SQL Server,客户机/服务器意味着 SQL Server 的组成部分,即客户机 API 部分,驻留在处理结构中的远端,与服务器组件本身是分开的。
在典型的双层模型中,客户机程序部分驻留在台式机上,具有大量客户机应用程序逻辑和业务逻辑,并且会直接向数据库系统发出请求。然后,客户机得到服务器响应这些请求所返回的数据。
三层系统也采用了同样的模型。多年以来,SQL Server 一直用在事务处理监视系统中,例如 BEA 的 Tuxedo 以及 Compaq 的 ACMSxp,这些系统早在二、三十年前就采用了典型的三层模型。三层模型在今天基于 Web 的应用系统中占据了支配地位,这类系统以 Microsoft 的 MTS 以及新的 COM+ 1.0 为代表。从 SQL Server 的角度看,三层解决方案中的客户机程序是放在中间层的。中间层直接与数据库交互。实际的桌面,或瘦客户机(Thin Client),使用其他机制并通常直接与中间层交互,而不是直接与数据库系统交互。图 1 描述了这种结构。
图 1. 三层系统模型
客户机结构
从结构的角度看,SQL Server 关系服务器组件本身并不真正关心客户机程序运行的位置。事实上,就 SQL Server 而言,即使在运行 SQL Server 的同一台机器上运行应用程序,仍然还是客户机/服务器模型。服务器运行一个单独的多线程进程,为来自客户机的请求提供服务,不管客户机的位置在哪里。客户机程序代码本身是单独的运行在客户机应用程序内部的 DLL,与 SQL Server 的实际接口是在客户机和服务器之间对话的“表格数据流”(Tabular Data Stream, TDS) 协议。
一个常见的问题是“什么是 SQL Server 的本机接口呢?”很长时间以来,很多开发人员一直都不愿意使用 ODBC 这样的接口,因为他们认为由 Sybase 开发的客户机 API,也就是 DB-Library,是 SQL Server 的本机接口。实际上,SQL Server 关系服务器本身并没有本机 API,它的接口就是在客户机和服务器之间的通信流协议 TDS。TDS 把客户机发送给服务器的 SQL 语句封装起来,也把服务器返回给客户机的处理结果封装起来。任何直接处理 TDS 的 API 都是 SQL Server 的本机接口。
让我们来看一下客户机的组件,如图 2 所示。客户机结构中的某些部分就不在这里讨论了,因为它们不属于 SQL Server 的范畴。但如果您在编写应用程序的话,就必须了解这些部分。大家知道得最多的应该是各种对象模型,如果您正在编写 ASP 或 Microsoft Visual Basic(R) 应用程序,就需要通过 ADO 与数据库系统交互,而不是直接调用底层的 API,例如 ODBC 或 OLE-DB。ADO 映射到 OLE-DB,而 RDO 映射到 ODBC。因此,作为这种最常用的编程模型的对象模型,并不是 SQL Server 客户机结构中的严格意义上的组件。此外,还有另外一些组件可以插接到 SQL Server 基础结构上面的这一层。OLE-DB 的“会话池服务提供程序 (Session Pooling Service Provider)”就是这种组件的一个例子。
图 2. 客户机结构
客户机接口
SQL Server 有两个接口可以认为是 SQL Server 7.0 的本机接口,即 OLE-DB 和 ODBC。DB-Library 接口也是本机的,它与 TDS 通信,但是 DB-Library 使用的是 TDS 较老的版本,需要在服务器上进行一些转换。现有的 DB-Library 应用程序仍然可以继续与 SQL Server 7.0 协同使用,但是很多新的功能和性能提高等好处只能通过 ODBC 和 OLE DB 才能利用。更新 DB-Library 使其支持 SQL Server 7.0 的新能力,将会导致与现有应用程序的很多不兼容性,因此需要修改应用程序。ODBC 在五年之前就替代了 DB-Library,是新的 SQL Server 应用程序更理想的 API,因此引入不兼容的 DB-Library 新版本并不明智。
从图 2 可以看到,所有这些客户机 API 都有三个部分。最上面的部分实现 API 的细节,例如行集和游标应该是什么样等等。TDS 格式化程序负责处理实际请求,例如 SQL 语句,并将其封装成 TDS 消息包,发送给 SQL Server,获得返回的结果,然后再把结果反馈到接口实现。
还有一些供所有提供程序使用的公共库代码。例如,BCP 设备就是 ODBC 和 OLE-DB 都可以调用的库。DTC 也是这样。第三个例子是 ODBC 规范的 SQL 语法,即带有参数标记的 CALL 语法,这些对于所有提供程序都是通用的。
除了我们在前面已经提到的局限性,即 DB-Library 仍然只能使用 SQL Server 6.5 版,TDS 协议对于所有 API 都是相同的。ODBC 和 OLE-DB 在与 SQL Server 7.0 通信时使用 SQL Server 7.0 版,但也能够与 6.5 或 6.0 服务器通信。另一个是 Net-Library,这是一个抽象层,客户机和服务器都在此层上同网络抽象接口通信,不必为 IPX 还是 TCP/IP 困扰。在这里我们将不讨论 Net-Library 的工作细节;只要知道它们的工作基本上是将来自的网络通信底层的细节隐藏起来不让软件的其他部分看到就可以了。