1.3 查找式查询

查找式查询(lookup query)一般用于填充某些变量或执行数据的合法验证。但在循环中执行查找式查询会导致性能问题。

在代码清单1-5中,高亮显示的部分就是使用查找式查询来得到country_name值。程序对游标c1中的每一行都要执行一个查询来取得country_name的值。当从游标c1中取得的行数增加时,执行查找式查询的次数也增加了,这导致代码的效率低下。

代码清单1-5 查找式查询,对代码清单1-1的副本的修改


代码清单1-5的代码是过分简化的,对country_name的查找式查询实际上可以重写为主游标c1本身中的一个连接。第一步,应将查找式查询修改为连接,可是在实际的应用程序中,并不一定可以实现这种改写。

如果无法利用改写代码来减少查找式查询的执行次数,那么还有另一个选择。你可以定义一个关联数组来缓存查找式查询的结果,以便在随后的执行中重用这个数组,这样也能有效地减少查找式查询的执行。

代码清单1-6演示了数组缓存技术。不必再在游标c1返回的每一行中执行查询来得到country_name,而是用一个名为l_country_names的关联数组来存储本例中的country_id和country_name键—值对。关联数组和索引类似,任意给定的值都可以通过一个键值来访问。

在执行查找式查询前,通过EXISTS操作对一个数组中是否存在一个匹配country_id键值的元素做一个存在性验证,如果数组中存在这么一个元素,那么country_name就从数组中获取而不需要执行查找式查询。如果没有这样的元素,那么就执行查找式查询,并且把查到的结果作为一个新元素存入数组。

你还需要理解,这种技术非常适用于不同的键值很少的语句,在本例中,当country_id列的唯一值个数越少时,查找式查询的执行次数可能也越少。如使用示例模式,执行查找式查询的次数最多是23,因为country_id列只有23个不同的值。

代码清单1-6 用关联数组实现的查找式查询

注意 关联数组所需内存是在数据库服务器中专用服务器进程的PGA(Program Global Area,程序全局区)中分配的,如果数千个连接都要把程序的中间结果缓存到数组中,那么内存的占用将会大幅增加。你应当掌握每个进程的内存使用增加情况,并设计数据库服务器以适应内存的增长。

利用基于数组的技术也可在其他场景中消除不必要的工作。例如,可以通过把函数结果值存入关联数组来减少执行代价高昂的函数调用。1.5节讨论了减少执行次数的另一种技术。

注意 将函数结果存入一个关联数组仅适用于确定性函数。也就是说,这种函数对给定的输入集合,总是返回相同的输出。

目录