如果所处理的数据会一直保留在应用的逻辑工作单元中,可以考虑使用全局临时表(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
;