解决方法
包含Oracle的大多数企业数据库使用基于成本的优化器来确定给定sql语句的适当查询计划.这意味着优化器使用有关数据的信息来确定如何执行查询而不是依赖于规则(这是旧的基于规则的优化器所做的).
例如,想象一个简单的错误跟踪应用程序的表
CREATE TABLE issues ( issue_id number primary key,issue_text clob,issue_status varchar2(10) ); CREATE INDEX idx_issue_status ON issues( issue_status );
如果我是一家大公司,我可能在这张表中有100万行.其中,100个具有ACTIVE_status,10,000个具有QUEUED的issue_status,而989,900具有COMPLETE状态.如果我想对表运行查询以查找我的活动问题
SELECT * FROM issues WHERE issue_status = 'ACTIVE'
优化器有一个选择.它可以使用issue_status上的索引,然后在表中为匹配的索引中的每一行执行单行查找,也可以在问题表上执行表扫描.哪个计划更有效将取决于表中的数据.如果Oracle希望查询返回表中的一小部分数据,那么使用索引会更有效.如果Oracle希望查询返回表中大部分数据,则表扫描会更有效.
DBMS_STATS.GATHER_TABLE_STATS收集了允许Oracle做出此决定的统计信息.它告诉Oracle表中大约有100万行,issue_status列有3个不同的值,并且数据分布不均匀.因此Oracle知道使用查询索引来查找所有活动问题.但它也知道,当你转身并试图寻找所有已关闭的问题
SELECT * FROM issues WHERE issue_status = 'CLOSED'
执行表扫描会更有效率.
收集统计信息允许查询计划随着数据量和数据分布的变化而随时间变化.当您第一次安装问题跟踪器时,您将遇到很少的COMPLETED问题以及更多ACTIVE和QUEUED问题.随着时间的推移,COMPLETED问题的数量上升得更快.当您在表中获得更多行并且各种状态中这些行的相对分数发生变化时,查询计划将发生变化,以便在理想情况下,您始终可以获得最有效的计划.