select a.c3, sum(a.c100 ) as sum_c100 from rc9_card1 a, rc9_card2 b, rc8_card1 c, rc8_card2 d where a.superkey = b.superkey and b.superkey = c.superkey and c.superkey = d.superkey group by a.c3;
选中该查询是因为它使用的聚集级别与我们刚刚定义的 MQT 不一样。这给优化器增加了难度 - 我们想知道优化器是否智能到能够重写查询以使用 MQT 而不是抽取网络上的所有数据。
不使用 MQT 的查询计划类似于 图 12:
图 12. 不使用 MQT 时的查询计划现在让我们添加 MQT。毫无疑问,优化器非常智能,足以重写查询以使用汇总而不是依靠“蛮力”得出答案。成本急剧削减到只需 25 timeron( 图 13)。
图 13. 由于使用 MQT 查询性能大大改进再来看看使用 MQT 发生了什么:控制中心的可视化说明(Visual Explain)工具显示了提供给联邦者的 SQL 和实际执行的 SQL。
提交的 SQL 查询引用被联邦者上的远程表。在列 c3 上执行分组。这给优化器增加了难度,因为 MQT 是在列 c100 上进行聚集的。
图 14. 提交给联邦者(最优化之前)的查询现在,看看 图 15。最优化之后连接没有了!从 MQT 中进行单表 select 操作满足了查询。优化器使用系统元数据来确认表 card_mqt 需要进行简单的聚集而不是使用远程表。
图 15. 实际执行的查询使用了 MQT消除数据集市
优化器查询重写操作与联邦服务器上的 MQT 一起使用,这是一个功能非常强大的组合。无需构建数据集市的所有工作,MQT 为许多查询提供了另一种方法。在查询使用禁用汇总高速缓存的函数和大量数据的组合时,这不能替代数据集市。
应当在 MQT 闲暇时填充并刷新它,以最优化性能并将计算和通信流量的影响降到最小。
结束语
以上便是对联邦的简介。在下一篇文章中我们将研究应用联邦技术的其它方法,具体说来就是:
- 联邦插入
- 根据联邦连接产生的 XML,以及
- XML 和 Websphere® MQ:巧克力配花生酱。
附录 A
-- This SQL creates a federated environment -- for two different -- Federatees -- connect to the DB2 database connect to sample; drop wrapper "INFORMIX"; CREATE WRAPPER "INFORMIX" LIBRARY 'db2informix.dll'; -- create a server for a remote instance of Informix 9.3 CREATE SERVER "rcfliif" TYPE INFORMIX VERSION '9.3' WRAPPER "INFORMIX" OPTIONS ( NODE 'fliif', DBNAME 'stores_demo' -- , ADD CPU_RATIO '0.0000001' -- , ADD IO_RATIO '0.0000001' , ADD CPU_RATIO '1' , ADD IO_RATIO '1' , ADD COMM_RATE '1' -- no, still not pushing down join , ADD PUSHDOWN 'Y' , ADD DB2_MAXIMAL_PUSHDOWN 'Y' -- , ADD PUSHDOWN 'Y' ); -- create a server for a remote XPS Informix v8.3 instance CREATE SERVER "rc_xps" TYPE INFORMIX VERSION '8.3' WRAPPER "INFORMIX" OPTIONS ( NODE 'flxps', DBNAME 'stores_demo' , ADD CPU_RATIO '1.0' , ADD IO_RATIO '1.0' , ADD COMM_RATE '2' , ADD PUSHDOWN 'Y' ); -- CREATE USER MAPPING FOR "LURIE" SERVER "rcfliif" OPTIONS( REMOTE_AUTHID 'informix', REMOTE_PASSWORD 'useyourown'); CREATE USER MAPPING FOR "LURIE" SERVER "rc_xps" OPTIONS( REMOTE_AUTHID 'informix', REMOTE_PASSWORD 'useyourown2'); -- create nickname rc9_card1 for "rcfliif"."lurie"."card1"; create nickname rc9_card2 for "rcfliif"."lurie"."card2"; create nickname rc8_card1 for "rc_xps"."lurie"."card1"; create nickname rc8_card2 for "rc_xps"."lurie"."card2"; --create a materialized query table or MQT -- this will allow the optimizer to rewrite SQL to -- the remote servers drop table card_mqt; create summary table card_mqt as ( select a.c3, a.c10, sum(a.c100 ) as sum_c100, sum(a.c1000) as sum_c1000 from rc9_card1 a, rc9_card2 b, rc8_card1 c, rc8_card2 d where a.superkey = b.superkey and b.superkey = c.superkey and c.superkey = d.superkey group by a.c3, a.c10 ) data initially deferred refresh deferred; refresh table card_mqt; set current refresh age=any; -- run various queries and capture explain plans set current explain snapshot=yes; values current timestamp; select a.c3, a.c10, sum(a.c100 ) as sum_c100, sum(a.c1000) as sum_c1000 from rc9_card1 a, rc9_card2 b where a.superkey = b.superkey group by a.c3, a.c10; values current timestamp; select a.c3, a.c10, sum(a.c100 ) as sum_c100, sum(a.c1000) as sum_c1000 from rc9_card1 a, rc9_card2 b, rc8_card1 c, rc8_card2 d where a.superkey = b.superkey and b.superkey = c.superkey and c.superkey = d.superkey group by a.c3, a.c10; values current timestamp; select a.c3, sum(a.c100 ) as sum_c100 from rc9_card1 a, rc9_card2 b, rc8_card1 c, rc8_card2 d where a.superkey = b.superkey and b.superkey = c.superkey and c.superkey = d.superkey group by a.c3; values current timestamp; set current explain snapshot=no;
附录 B
-- (c) Copyright 2003 Martin Lurie and IBM Corp drop table card1; create table card1 ( superkey serial, c3 int, c10 int, c100 int, c1000 int ) in dbspc1; drop table card2; create table card2 ( superkey int, c3 int, c10 int, c100 int, c1000 int ) in dbspc1; -- Stored procedure to populate the -- table drop procedure pop_card; create procedure pop_card (tot_rows int) define rows_in integer; define c3cnt integer; define c10cnt integer; define c100cnt integer; define c1000cnt integer; let rows_in=0; for c1000cnt = 1 to 1000 step 1 for c100cnt = 1 to 100 step 1 for c10cnt = 1 to 10 step 1 for c3cnt = 1 to
上一篇教程: 成功是必然的(中)
下一篇教程: 从数据管理到信息集成: 自然的演变






