13. 考虑使用全局临时表
如果所处理的数据会一直保留在应用的逻辑工作单元中,可以考虑使用全局临时表(global temporary table,GTT),而不要反复建立或物化数据。如果在程序执行期间多次获取或物化同样的数据,可以把这些数据在一个GTT中加载一次,然后在代码的其他地方引用这个表。
例如,一个程序有多个游标,每个游标包含多个表联接。另外,每个游标都包含同样的表Table1,而这恰好是各个查询的驱动表。处理各个游标时,可能必须从数据库获取相同的行来完成Table1处理。这样一来,就会导致对相同数据额外的I/O处理。
所以,更好的做法是先获取Table1数据,把它插入到一个GTT中,然后在各个游标中引用这个GTT。这会消除对Table1的重复I/O。GTT也很适合创建一个概要数据表,可以在逻辑工作单元中的其他查询中引用。
警告:有两类GTT:一类是DBA创建的GTT,另一类是应用代码中声明的GTT。使用DBA创建的全局表时要特别当心,因为它们不能有索引。把这些表加入一个多表联接时,可能会导致性能问题。不过,如果在应用代码中声明一个全局表,在其中加载数据之前,应用代码可以在这个表上创建索引。如果是这样,会随着数据的插入收集动态统计信息,而且由于可以使用这个索引和统计信息,联接通常会更高效。另外,要记住由于应用代码中声明的全局表有更大的灵活性,所有引用这些全局表的SQL语句会作为动态SQL执行,而引用DBA创建的全局表的SQL则作为静态SQL执行。
下面的例子展示了代码中如何声明和创建一个全局临时表。在应用代码中声明全局临时表时,所有者必须使用SESSION:
- DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMP_EMP
- (EMPNO CHAR(6) NOT NULL,
- FIRSTNME VARCHAR(12) NOT NULL,
- MIDINIT CHAR(1) NOT NULL,
- LASTNAME VARCHAR(15) NOT NULL,
- WORKDEPT CHAR(3),
- PHONENO CHAR(4)
- )
- ON COMMIT DROP TABLE or
- ON COMMIT DELETE / PRESERVE ROWS
- ;
- CREATE INDEX SESSION.EMPX1 ON SESSION.TEMP_EMP
- (LASTNAME ASC)
- ;
- INSERT INTO SESSION.TEMP_EMP
- SELECT EMPNO,
- FIRSTNME,
- MIDINIT,
- LASTNAME,
- WORKDEPT,
- PHONENO
- FROM EMP
- ;
- SELECT *
- FROM SESSION.TEMP_EMP
- ;