正如我们在前面对自动调优的分析所说的那样,物理设计不能单纯从单条语句的角度来考虑。在我们进行快速调优时,需要开发人员或 DBA 能掌握系统中的物理对象的使用情况,从而权衡物理设计的改变带来的收益与维护代价。例如,如果是业务数据表,则会存在频繁的、高并发的数据 修改(增、删、改)操作,而对其查询则主要基于键值;而如果是日志表,则可能仅有插入操作和 定期的批量删除操作,对其查询则可能大批量数据的扫描(如,用于报表或历史记录检索)。
“高效的性能,源自高效的设计”。一个良好的数据库的设计,包括逻辑设计和物理设计,需要有一个完善的设计思想、全面的设计方法和规范的设计流程,并且能结合业务灵活的运用数据库管 理系统的各项特性。因此,数据库的设计不是简单的三言两语可以概括出来,而是一个更加复杂和 全面的话题。在本章节当中,我们仅读者介绍利用物理设置进行优化时,需要注意的问题,以及简 要的分析思路。
9.3.1 索引
索引访问是提高数据访问效率的常用方法。我们在创建或管理索引时,可以从以下几个方面对 索引进行分析,提高索引的性价比。
o 索引的效率
一个高效的索引,与其包含的字段的选择率有直接关系。如果索引中存在多个字段,其选择率则为多个字段选择率的乘积。我们在选择索引字段时,从选择率的角度考虑,需要注意以下两点:
• 索引的最终选择率不应当低于表的最小选择率(1/TABROWS),除非是从索引的包容性角 度考虑,需要冗余字段来消除排序或对表数据的访问;
• 在多字段索引当中,选择率越低的字段在索引中的位置越前,除非是为了兼容多个查询;
但是,值得注意的是,用字段选择率乘积的方法计算索引的选择率存在缺陷。举个简单例子, 以下含有两个字段的组合索引,存在以下数据记录:
(A, 1)
(A, 1)
(A, 2)
(B, 2)
(B, 3)
(B, 3)
按照传统的乘积算法,得出的选择率为 1/2*1/3 = 1/6。但其实际选择率为 1/4。在 11g 当中, 可以通过创建扩展统计数据来消除这一缺陷,提高优化器选择索引的正确性。
o 索引的兼容性
对于新索引的设计,要从相关的业务需求做整体考虑,创建出兼容性较强的索引————既满 足多项业务需求的性能要求,又能最大限度的建设索引带来的维护代价。
• 当多项业务需求需要对某些字段做匹配查询时,应该考虑将这些字段按照它们的选择率高 低,放置在索引的前导位置;
• 如果向索引中添加少量字段能够消除访问表的操作时,可以考虑将这些字段冗余到索引的 尾部;
o 对索引的有效管理
在对索引进行管理时,利用一些方法和 Oracle 提供的一些特性,能保证我们提供管理的有效性, 较早发现潜在的性能问题。此外,对于一些复杂系统的 DBA 来说,可能无法做到对所有物理设计
改变进行全面审核(Review)。定期检查是发现未被审核到的物理设计存在的潜在问题的有效手段。例如,在生产环境中宏实施创建索引行为进行快速调优之前,可以先创建“空索引”(指定
NOSEGMENT 关键字)、解析目标语句执行计划(需要设置参数"_use_nosegment_indexes"为
TRUE),更加直观的确认实际优化效果;
此外,作为数据库管理员,应该定期检查现有索引:
• 定期查看段建议器(Segment Advisor)的定期任务找到的问题和给出的建议;
• 对重点索引(与其它索引前导字段重复或者选择率低)打开监控(MONITOR)开关,定期 查看它们的使用情况。长期没有被使用的索引可以考虑删除;或者设置为“不可见”
(INVISIBLE,11g 特性),确认其属于多余索引后再删除;
• 定期检查是否存在状态异常的索引;
9.3.2 分区
分区使得数据能按照分区键值进行物理划分,结合分区裁剪(Partition Prun),能减少对物理数据的访问。对于分区设计,比较重要的是分区键的选择和本地索引的使用情况。
分区键的选择
• 选择分区键时,一项参考原则就是分区键是该表整体业务的划分标准;
• 同时,尽量避免选择存在更新操作的分区键;
例如,一个向多家公司提供服务的商务系统中,各个公司在使用服务时都是相对独立,那么数 据库系统中的公司键值(Company ID)就是一个比较理想的候选分区键。
分区裁剪
对于已经存在的分区表,可以检查相关语句的执行计划中是否有对分区进行裁剪,重审其键值 的选择是否合理。例如,对于列举分区(List Partition)表,如果相关执行计划中列举全部分区
(PARTITION LIST ALL)操作的比例相当高,我们就需要重审该分区表的设计。
本地索引的使用情况
分区表能帮助语句提高性能的另外一个因素就是能创建本地分区索引————索引数据的物理位置也按照分区键划分。如果分区表不能创建有效的本地索引、或者本地索引在相关执行计划当中 被引用的频率非常低,那么我们也要重审该分区表的设计。
9.3.3 物化视图
物化视图是通过将负责查询的结果存储在物理对象当中,从而减少对多表的关联查询、减少物理数据的读取的一种物理设计方法。物化视图的维护成本比较高,系统需要创建多个数据库对象来 实现物化视图,例如引用表的物化日志、定时刷新日志的后台任务等。通常来说,物化视图仅被推 荐创建在数据仓库(Warehouse)的数据库系统中、或者具有 DSS 特性的模块当中。高效的物化视图设计是一个更为复杂的话题,需要结合更多的数据仓库知识进行阐述,因此我们不打算将该话题 包含在本书当中。
9.3.4 约束
约束的设计是一项很容易被数据库设计者或者 DBA 所忽视的一项设计内容。例如,我在审核一些物理设计时,经常发现一些这样的情况:表中所有字段处理主键字段以外,全部允许为空;整个
OLTP 的数据库系统当中不存在任何外键关系,等等类似情况。而实际上,通过我们前面对优化器的优化过程分析,我们知道合理的约束能使优化器做出更好的优化行为。因此,在做物理设计时, 不能忽视对约束的设计。回顾优化器的查询转换技术,能够影响到优化器行为的约束有:
• CHECK:数值检查约束影响到的优化技术有:
o 由约束生成过滤谓词;
• NOT NULL:非空约束影响到的优化技术有:
o 由约束生成过滤谓词;
o 子查询反嵌套;
o 是否选择索引快速完全扫描操作;
• FOREIGN KEY:外键约束影响到的优化技术有:
o 表消除
• UNIQUE/PRIMARY KEY:唯一约束或主键约束影响到的优化技术有:
o Distinct 消除
o 表消除
此外,CHECK、NOT NULL、UNIQUE 等约束还会影响统计数据的计算和执行计划代价计算过程中选择率的技术。
结束语
本书写到这里,基本上已经结束。但是,SQL 优化与调优的这一话题远未结束。从纵向来说, 正如我们在本书的开始部分所强调的,本书的内容是针对 Oracle 10g 和 11g 的特性而展开的,而随着数据库管理系统的版本更新,会有更多的优化与调优技术本引用进来,也可能会有一些过时的技术被抛弃(如 8i 时代的 RBO);从横向上说,SQL 优化与调优所涉及的话题也不是仅仅围绕执行计划或者语句执行过程本身,还有一些更广泛的关联知识是需要掌握,例如数据库的并发控制、资源
管理方法等。本书的主要目的是帮助读者理解现有的优化与调优技术、掌握基本的调优技术与思路。希望读者在阅读完本书之后,并且运用本书当中学到的内容以及相关数据库的综合知识,更加彻底 地解决 SQL 性能问题。同时也希望读者在对一条 SQL 语句的性能感到一筹莫展时,能借助本书当中 的内容分析出性能的瓶颈所在;从本书当中找到解决问题的思路与方法。




