4.2.3 共享池
数据库中的数据是以表的形式组织在一起的。当用户访问数据时,数据库服务器首先检查对应的表是否存在,然后检查指定的列是否存在,还要检查权限和加锁等信息。当这些检查都通过时,数据库服务器将对用户的命令进行分析,产生分析代码和执行计划,然后按照这样的执行计划访问数据,并将执行结果返回给用户。
为了提高数据库的性能,Oracle在SGA中开辟了一个共享池,用于存放与SQL语句的执行有关的信息。共享池主要由三部分组成,即数据字典高速缓存、库高速缓存和服务器结果缓存。共享池的大小由初始化参数SHARED_POOL_SIZE指定。总的来说,共享池几乎和数据库中的所有操作都有关。
当用户访问数据库中的数据时,数据库服务器首先要查询相关的数据字典,确定要访问的对象是否存在,如表、视图等,以及表和视图上的列等。然后检查权限等信息,最后才执行这样的命令。数据字典信息存储在SYSTEM表空间中,也就是说,存储在磁盘上的数据文件中。如果数据库服务器进程每次都要从磁盘上读数据字典信息,那么SQL语句的执行效率是很低的。
为了加快这个SQL语句的执行速度,Oracle在共享池中开辟了数据字典缓存,用来存放最近访问的数据字典的信息。这样查询相关的数据字典时,可以直接在数据字典缓存中进行。
库高速缓存用于存放最近执行的SQL命令的相关信息。我们知道,数据库服务器在执行SQL命令时,首先要对SQL命令进行解析,产生分析代码,并生成执行计划,然后才按照执行计划执行SQL命令,最后把命令的执行结果返回给用户。在整个执行过程中,分析阶段所用的时间是最长的。如果能减少分析所用的时间,那么整个SQL命令的执行效率将大大提高。Oracle的做法是:在执行一条SQL命令时,服务器进程对它进行分析,然后把SQL命令文本、解析结果和执行计划就存储在库高速缓存中。
服务器进程在执行一条SQL命令时,首先要到库高速缓存中查看是否存在这条SQL命令的信息,如果发现SQL语句相关信息已经存储在库高速缓存中,就直接取出执行计划并执行它,这样就省去了分析所用的时间,可以大大加快SQL命令的执行速度。否则,服务器进程需要按部就班地对SQL命令进行解析,然后生成执行计划,并将这些信息存储在库高速缓存中。
当两条SQL命令的文本完全相同时,我们认为它们是同一条命令,这时它们可以共享库高速缓存中的信息。如果命令文本中的大小写、空格个数或参数的数值不同,就认为是两条不同的命令,它们在执行时需要单独进行分析,最终将生成不同的分析代码和执行计划。例如,考虑以下两条命令:
SELECT ename, sal FROM emp WHERE eno=7902
SELECT ENAME, SAL FROM EMP WHERE ENO=7902
这两条命令看似相同,实际上是有差别的。首先,命令中的大小写不同。其次,两个列之间的空格个数不同,所以它们将生成不同的分析代码和执行计划。由此可见,命令的书写风格对命令的执行结果没有什么影响,但对命令的执行效率却大有影响。
在这里,给程序员一个建议:开发程序时要考虑编程的风格和程序的执行效率。虽然每个程序员都会编程,但是不同的程序员编写的程序的执行效率是大不一样的。实践证明,在很多生产系统中,程序员编写的程序就是整个系统性能的瓶颈,这样的系统在提交客户后,管理员对此是无能为力的。