为了进一步增强性能,每个包装器实现使用数据源的本机 API 来利用每个数据源所提供的可操作的调节器。例如,将多个生成的行组成一条消息(又名为块存取)是一种常见的性能调整。查询编译器与包装器进行通信以指出哪些查询段可以利用块存取,因而在没有丧失查询语义的情形下,在运行时达到最佳性能。
IBM 的联邦技术是如何工作的
图 1显示了 IBM 联邦数据库的体系结构。应用程序可以使用任何受支持的接口(包括 ODBC、JDBC 或 Web 服务客户机)与联邦服务器交互。联邦服务器通过称为包装器的软件模块与数据源进行通信。
图 1. IBM 联邦系统的体系结构
配置联邦系统
通过安装联邦引擎,然后配置它以与数据源通信,从而创建联邦系统。向联邦系统添加新的数据源包括以下几步。首先,必须安装用于数据源的包装器,然后必须告诉 IBM 的联邦数据库在何处可找到包装器。通过 CREATE WRAPPER 语句可以做到这一点。如果期望添加的多个数据源属于同一类型,则只需一个包装器。例如,即使联邦系统将包含五个可能在不同机器上的 Oracle 数据库实例,也只需要一个 Oracle 包装器,因此只需要一条 CREATE WRAPPER 语句。然而,还必须向系统标识每个单独的数据源。通过 CREATE SERVER 语句可以做到这一点。如果有五个 Oracle 数据库实例,则必须发出五条 CREATE SERVER 语句。
例如,假定有一个用于访问网站的包装器和一个用户希望访问其数据的特定站点。可以通过以下语句通知联邦数据库有关包装器的信息:
CREATE WRAPPER web_wrapper LIBRARY "/u/haas/wrappers/libweb.a"
这条语句实质上告诉联邦数据库到哪里去查找 web_wrapper 的代码。接下来,将实际要使用的网站标识为与 web_wrapper 相关联的服务器,从而告诉联邦数据库关于该网站的信息。
CREATE SERVER weather_server WRAPPER web_wrapper OPTIONS (URL 'http://www.weatherforecast.com')
OPTIONS 子句的作用是,用该包装器为访问这个数据源类型的实例所需的信息来定制基本的 CREATE SERVER 语句。
在定义好包装器和服务器之后,必须根据联邦中间件的数据模型来描述位于远程数据源中的数据。由于这里所描述的联邦数据库支持对象关系数据模型,因此必须向联邦引擎描述来自外部数据源的每个数据集,并将其描述为具有相应类型列的表。建模为表的外部数据集称为别名(nickname),应用程序向联邦体提交的 SQL 中会用到这个表名和列名。通过 CREATE NICKNAME 语句来定义别名。下面这条语句为有关天气的信息集合设置一个别名,并定义了一些可以在查询中使用的“列”。
CREATE NICKNAME weather (zone integer, climate varchar(10), yearly_rainfall float) SERVER weather_server OPTIONS (QUERY_METHOD 'GET')
“OPTIONS”子句再次起到传递包装器所需信息的作用,这次是为了处理针对别名的查询。
除了存储数据,许多数据源还能够执行特殊的搜索或其它计算。可以在 SQL 中以用户定义的函数表示这些能力。例如,用户可能希望根据地域和日期来预报天气,从而确定购买空调的客户。
SELECT c.Name, c.Address FROM customers c, stores s, weather w WHERE temp_forecast(w.zone, :DATE) >= 85 AND c.ShopsAt = s.id and s.location = w.zone
这里,用 temp_forecast 函数来表示数据源能够预报别名为 weather 的气温。我们称这种由外部数据源实现的用户定义的函数为 映射函数。同样,通过 DDL 语句向联邦系统标识映射函数。CREATE FUNCTION 语句告诉联邦数据库可以在 SELECT 语句中使用该函数。
CREATE FUNCTION temp_forecast (integer, date) RETURNS float AS TEMPLATE DETERMINISTIC NO EXTERNAL ACTION
AS TEMPLATE 子句告诉联邦数据库这个函数没有本地实现。接下来,CREATE FUNCTION MAPPING 语句告诉联邦数据库哪个服务器可以对这个函数求值。可以为同一个函数创建几个函数映射。例如,下面这条语句可以完成这样的映射:
CREATE FUNCTION MAPPING tf1 for temp_forecast SERVER weather_server
上面这些 DDL 语句会产生元数据,这个元数据描述了有关映射函数的别名和特征符的信息。联邦查询处理引擎要使用这个元数据,这个元数据存储在联邦数据库的全局目录中。
查询处理
配置好联邦系统之后,应用程序可以向联邦服务器提交用 SQL 编写的查询。联邦服务器优化该查询,产生一个执行方案,其中这条查询被分解为可以在各个数据源上执行的片段。正如上面所提到的,对这条查询可能存在多种分解,优化器根据最少资源总耗估计值从多种可能中做出选择。一旦选定一个方案,联邦数据库就开始执行,调用包装器来执行分配给它们的片段。为了执行某个代码段,包装器会执行任何所需的数据源操作,这些操作也许是一系列函数调用,或者是提交给数据源用其本机查询语句执行的查询。生成的数据流被返回给联邦服务器,由联邦服务器来组合它们,执行任何其它的由数据源无法完成的处理,然后将最终结果返回给应用程序。
IBM 联邦查询处理方法的核心是,联邦服务器的优化器和包装器一起为执行某个查询而形成方案所采用的方式 [4]。优化器负责研究这些可能的查询方案的空间。在连接枚举中,动态编程是缺省方法,优化器首先生成单表访问的方案,然后生成双向连接等。在每一级别,优化器都会考虑各种连接顺序和连接方法,如果所有表都位于一个公共的数据源,则它认为执行这个连接可以在数据源中进行,也可以在联邦服务器上进行。 图 2 显示了这一过程。
图 2. 用于连接的查询方案
优化器的工作方式因使用关系和非关系包装器而有所不同。优化器详细地对关系数据源建模,建模所使用的信息由包装器提供,这些信息是用来生成执行计划,而这些计划表示优化器期望数据源如何执行。
然而,由于非关系数据源确实没有公共的操作集或公共的数据模型,因此对于这些数据源需要更灵活的安排。因而优化器这样使用非关系包装器:
- 如果称为“请求”的候选查询段适用于单个数据源,则 IBM 联邦数据库向包装器提交该查询段。
- 在非关系包装器接收到一个请求之后,它确定相应的查询段中哪部分(如果有的话)可以由数据源执行。
- 包装器返回一个应答,其中描述了查询段已接受的部分。应答还包括对将要产生的行数的估计、对整个执行时间的估计以及包装器方案:包装器将需要知道所有内容的封装表示,才能执行查询段已接受的部分。
- 联邦数据库优化器将这个应答合并到全局方案中,同时引入其它必要的运算符以弥补包装器不能接受的查询段部分。使用应答中的成本和基数信息来估计这个方案的总成本,从所有候选方案中选出总成本最低的方案。在选定方案之后,不需要立即执行该方案;可以将它存储在数据库目录中,在以后执行该查询时,一次或多次使用该方案。即使立即使用该方案,也不需要在创建该方案的同一过程中执行它,如 图 3所示。
例如,考虑一个播报有关股票信息(包括成交价、开盘价和收盘价以及交易量)的网站。可以通过表单来搜索该网站,这种情况很常见,在表单中可以约束部分属性的值,但不能约束所有属性的值。考虑下面这条查询:
SELECT TickerSymbol, StockName FROM Stocks WHERE Exchange='NYSE' AND Closing - Opening > 5
由于这是一条单表查询,因此不需要考虑连接方法或顺序,只有一段包含了整个查询,它将作为对 web 数据源包装器的请求而提交。如果这个表单允许用户指定与底层数据的“Exchange”属性相匹配的值,而没有提供一种方式来指定开盘价和收盘价之间的差价,则包装器会产生一个应答,接受有关“Exchange”的谓词,但拒绝谓词 Closing - Opening > 5 。优化器将通过引入一个运算符在联邦服务器上对后面的谓词求值,以弥补数据源不能完成的工作。通常,包装器必须能够返回 SELECT 列表中所请求的任何单列的值,但可以拒绝任何谓词或更复杂的 SELECT 列表表达式。
除了指出数据源将只对“Exchange”谓词求值外,应答将包括包装器方案,该方案包含足够的信息以执行由该应答所表示的查询。例如,包装器方案可能包含带参数的 URL,这相当于如果用户手工填写好该查询表单之后,浏览器将产生的 URL。在执行时,联邦服务器将该方案返回给包装器,包装器将抽取出 UR






