SQL优化技巧
每当查询优化器无法自动生成有效的执行计划时,就需要手工优化了。表11-1总结了Oracle数据库为此提供的一些技术手段。本章目标不仅是详细介绍这些技巧,而且还会解释每个技巧的作用及其适合的场景。你需要问自己下面三个基础问题来决定使用哪种技巧。
Ø SQL语句是否为已知的和静态的?
Ø 针对单个会话(或者整个系统),获取到的测量值会影响单条SQL语句还是所有SQL语句?
Ø SQL语句可以修改吗?
让我来解释下这三个问题的重要性。首先,SQL语句有时无法简单获取到,因为它们是在运行时生成的,并几乎在每次执行时都在改变。其他情况下,查询优化器无法正确处理许多SQL语句使用的特殊模式(比如WHERE条件的限制而不能使用索引)。在这些情况下,你需要利用技巧来解决会话或系统级别的问题,而不是SQL语句级别。
但这会带来两个问题。一方面,就像表11-1总结的那样,一些技巧只能用在特定的SQL语句上。它们无法在会话或系统级别使用。另一方面,就像第9章解释的那样,当数据库设计良好并且查询优化器正确配置时,通常只需要优化一小部分SQL语句。
因此,需要避免技巧影响到由查询优化器自动提供高效执行计划的SQL语句。其次,每当处理不可控的SQL语句应用时(要么是因为代码无法访问,比如包的应用,要么就是SQL语句是在运行时生成的),你都无法使用需要更改代码的技巧。总之,通常你的选择是受限的。
修改访问结构
该技巧不是某一特定特性。SQL语句的响应时间不仅非常依赖于存储数据处理的方式,同时也依赖于处理数据的访问方式。
工作原理
怀疑一个SQL语句有性能问题时,首先要做的是确定当前使用的访问结构。基于在数据字典里找到的信息,可以获得以下反馈。
Ø 涉及的表的组织类型是什么?是堆表、索引组织表还是外部表?或者是存储在群集中的表?
Ø 物化视图包含的数据是否可用?
Ø 表、群集和物化视图上存在什么索引?索引都包含了哪些列以及列的排列顺序如何?
Ø 这些段是如何分区的?
接下来需要评估可用的访问结构是否能够高效处理你要优化的SQL语句。例如,分析期间,你可能会发现对SQL语句的WHERE条件增加索引可以提高效率。假设你在研究以下查询的性能:
select * FROM emp WHERE empno = 7788;
基本上,查询优化器会运行下面的执行计划。第一个执行计划执行一次全表扫描,而第二个通过索引访问表。当然,第二个只有在索引存在时才会生成:
何时使用
在适当的位置没有必要的访问结构,或许就不可能优化SQL语句。因此,你需要在任何可以改变访问结构的时候使用该技巧。不幸的是,这并不总是可行,比如当你处理封装的应用并且供应商不支持修改访问结构的时候。
陷阱和谬误
修改访问结构时,必须谨慎处理可能产生的影响。一般来说,每次修改访问结构都会带来正面与负面的影响。实际上,这种影响不太可能只局限于单条SQL语句。只有在少数情况下才不会产生影响。例如,在前面类似例子中要增加索引,就需要考虑索引会减慢索引表上每条INSERT和DELETE语句的执行速度,同样修改索引列的每条UPDATE语句也会产生同样的结果。还应该检查是否有足够的空间来增加访问结构。总的来说,在修改访问结构之前需要仔细判断是否利大于弊。