Understanding How EXPLAIN PLAN can Miss the Mark
理解解释计划怎么会错误标记
One of the most frustrating things about EXPLAIN PLAN output is that it may not always match the plan that is used when the statement is actually executed. There are three things to keep in mind about using EXPLAIN PLAN that make it susceptible to producing plan output that won’t match the actual execution plan:
• EXPLAIN PLAN produces plans based on the environment at the moment you use it.
• EXPLAIN PLAN doesn’t consider the datatype of bind variables (all binds are VARCHAR2).
• EXPLAIN PLAN doesn’t “peek” at bind variable values.
For these reasons, it is very possible that EXPLAIN PLAN will produce a plan that won’t match the
plan that is produced when the statement is actually executed. Listing 6-4 demonstrates the second
point about bind variable datatypes.
(解释计划)EXPLAIN PLAN输出最让人郁闷的事情就是它可能不总是能匹配(SQL)语句实际执行计划。关于使用EXPLAIN PLAN有3件事值得怀疑,可能生成的计划输出不能匹配实际执行计划:
• EXPLAIN PLAN 生成的计划是基于你当时使用的环境。
• EXPLAIN PLAN 不考虑绑定变量的数据类型(所有的绑定变量都是VARCHAR2)。
• EXPLAIN PLAN 不会“窥视”绑定变量的值。
就以上这些原因,EXPLAIN PLAN非常有可能生成的计划不匹配SQL语句实际执行的计划。列表6-4演示了第二点,关于绑定变量类型。
Listing 6-4. EXPLAIN PLAN and Bind Variable Datatypes
SQL>-- Create a test table where primary key column
SQL>-- is string datatype
SQL>create table regions2
2 (region_id varchar2(10) primary key,
3 region_name varchar2(25));
Table created.
SQL>
SQL>-- Insert rows into the test table
SQL>insert into regions2
2 select * from regions;
4 rows created.
SQL>
SQL>-- Create a variable and set its value
SQL>variable regid number
SQL>exec :regid := 1
PL/SQL procedure successfully completed.
SQL>
SQL>-- Turn on autotrace explain plan
SQL>set autotrace traceonly explain
SQL>
SQL>-- Execute query and get explain plan
SQL>select /* DataTypeTest */ *
2 from regions2
3 where region_id = :regid;
Execution Plan
----------------------------------------------------------
Plan hash value: 3821806520
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 21 | 1 (0) |
| 1 | TABLE ACCESS BY INDEX ROWID | REGIONS2 | 1 | 21 | 1 (0) |
|* 2 | INDEX UNIQUE SCAN | SYS_C0011282 | 1 | | 1 (0) |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("REGION_ID"=:REGID)
SQL>
SQL>set autotrace off
SQL>
SQL>-- Execute query again
SQL>select /* DataTypeTest */ *
2 from regions2
3 where region_id = :regid;
REGION_ID REGION_NAME
---------- -------------------------
1 Europe
SQL>
SQL>-- Review the actual execution plan
SQL>-- This script uses dbms_xplan.display_cursor
SQL>@pln DataTypeTest
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------
SQL_ID 2va424cgs3sfb, child number 0
-------------------------------------
select /* DataTypeTest */ * from regions2 where region_id = :regid
Plan hash value: 670750275
--------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | Buffers |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 | 8 |
|* 1 | TABLE ACCESS FULL | REGIONS2 | 1 | 1 | 1 | 8 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("REGION_ID")=:REGID)
Note
-----
- dynamic sampling used for this statement (level=2)
Did you notice how the EXPLAIN PLAN output indicated that the primary key index would be used but the actual plan really used a full table scan? The reason why is clearly shown in the Predicate
Information section. In the explained plan output, the predicate is “REGION_ID"=:REGID, but in the actual plan, the predicate shows TO_NUMBER("REGION_ID")=:REGID. This demonstrates how EXPLAIN PLAN doesn’t consider the datatype of a bind variable and assumes all bind variables are string types. For the EXPLAIN PLAN, the datatypes were considered to be the same (both strings). However, the datatypes were considered when the plan was prepared for the actual execution of the statement and Oracle implicitly converted the string datatype for the REGION_ID column to a number to match the bind variable datatype (NUMBER). This is expected behavior in that when datatypes being compared don’t match, Oracle will always attempt to convert the string datatype to match the non-string datatype. By doing so in this example, the TO_NUMBER function caused the use of the index to be disallowed. This is another expected behavior to keep in mind: the predicate must match the index definition exactly or else the index will not be used.
你注意到了么?EXPLAIN
PLAN输出指出主键索引将被使用,但是实际计划用的却是全表扫描?原因在谓词信息那节中讲过。在解释计划输出中,谓词是
“REGION_ID”=:REGID,但是在实际的计划中谓词显示是TO_NUMBER("REGION_ID")=:REGID。这演示了
EXPLAIN PLAN怎么会不考虑绑定变量的数据类型且假设所有的绑定变量是字符串类型的。对于EXPLAIN
PLAN而言,数据类型都被认为是一样的(都是string)。然而,为实际执行所准备的计划是要考虑数据类型的,且Oracle隐式的转换字符串类
型,REGION_ID列,成数字(NUMBER)型。当数据类型不匹配时这是期望的行为。Oracle总是企图转换字符串数据类型成非字符串数据类型。
在本例中也是这样做的,TO_NUMBER函数使得索引不允许使用。这是另外一个必须记住的期望的行为:谓词必须准确的匹配索引的定义否则索引将不能被使用。
If you were testing this statement in your development environment and used the explain plan
output to confirm that the index was being used, you’d be wrong. From the explain plan output, it would appear that the plan was using the index as you would expect, but when the statement was actually executed, performance would likely be unsatisfactory due to the full table scan that really would occur. Another issue with using explain plan output as your sole source for testing is that you never get a true picture of how the statement uses resources. Estimates are just that—estimates. To really confirm the behavior of the SQL and to make intelligent choices about whether or not the statement will provide optimal performance, you need to look at actual execution statistics. I’ll cover the details of how to capture and interpret actual execution statistics shortly.
如果你在开发环境测试这个语句,且用解释计划确认使用了索引,你就错了。从解释计划的输出,它显示如你所愿的用了索引,但是当语句实际执行,性能将不能满
足,由于实际发生的是全表扫描。另一个问题,因为使用解释计划输出作为你单独的测试来源,你不可能获得语句怎么使用资源的真实图画。评估只是评估。为了真
正的确认SQL的行为,做出智能的选择,是否语句提供优化的性能,你需要查看实际执行的统计。等会我将详细讨论如何捕捉和解释实际执行的统计。
分享到:
相关推荐
《Pro Oracle SQL》是Oracle数据库查询优化的经典之作,第六章主要聚焦在Execution Plans(执行计划)上,这是数据库查询性能优化的关键。本章节的第四部分深入探讨了如何理解和解析执行计划,以及它对SQL性能的影响...
《Pro Oracle SQL》一书的第10章深入探讨了SQL优化,特别是10.2节,重点关注如何测试执行计划,这是SQL性能调优的关键环节。在这个部分,作者旨在帮助读者理解如何有效地评估和改进SQL查询的性能,以提高数据库系统...
《Pro Oracle SQL Development》这本书是Oracle SQL开发的专业指南,它深入探讨了Oracle数据库系统中的SQL语言使用和优化。Oracle SQL是用于管理和操作Oracle数据库的强大工具,对于任何在Java开发中涉及Oracle...
《X-Pack SQL JDBC驱动在Elasticsearch中的应用与详解》 Elasticsearch作为一个强大的开源搜索引擎,广泛应用于数据存储和检索领域。为了方便开发者利用传统SQL语法进行查询操作,Elasticsearch引入了X-Pack SQL ...
《Pro Oracle SQL》是Oracle SQL领域的一本权威指南,尤其针对11gR2版本进行了深入探讨。本书全面覆盖了Oracle SQL的各种概念、语法和高级特性,旨在帮助读者从初级到高级逐步提升对Oracle数据库查询语言的理解和...
《Pro Oracle SQL 2》是面向数据库管理员(DBA)和Oracle开发人员的专业SQL指南,第二版的内容在原基础上进行了更新和扩充,旨在提供更深入、更全面的Oracle SQL使用技巧和最佳实践。这本书深入探讨了Oracle SQL的...
《Pro Oracle SQL》是Oracle数据库查询的一本权威指南,其中第二章主要讲解SQL查询的高级技巧。在2.8节“子查询展开(Subquery Unnesting)”中,我们将会深入探讨Oracle SQL中一种优化查询性能的重要策略。这一部分...
《Pro Oracle SQL》是Oracle数据库查询优化的一本权威著作,其中第三章着重讲解了全面扫描(Full Scan Access Methods)这一重要的访问方法。在数据库查询优化中,了解并掌握不同的访问方法对于提高SQL查询性能至关...
### Oracle SQL Tuning详解 #### 一、Oracle SQL性能调优概述 在Oracle数据库管理中,SQL性能调优是一项至关重要的任务,它直接影响到应用程序的响应时间和系统的整体性能。SQL性能调优通常涉及对SQL语句进行分析...
《Oracle Press - Oracle Database 11g SQL》是专门针对Oracle数据库系统中SQL语言的一本详细教程,适合数据库管理员(DBA)、开发人员以及对Oracle SQL感兴趣的初学者学习。本书全面覆盖了Oracle 11g版本中的SQL...
"Oracle SQL Performance Tuning 39Tips" 提供了由Oracle专家Tom Kyte精心总结的30个SQL优化技巧,这些技巧旨在帮助用户提升数据库查询速度,减少资源消耗,提高系统整体性能。 1. **索引优化**:Tom Kyte强调了...
### ORACLE-SQL性能优化大全知识点详述 #### 一、优化基础知识概述 - **性能管理**: - **尽早开始**:性能优化应该在项目的早期就开始考虑,而不是等到后期出现性能瓶颈时才去处理。 - **设立合适目标**:设定...
- 解决慢查询:针对耗时较长的SQL语句,使用EXPLAIN PLAN分析执行计划,优化索引或重构查询语句。 7. **学习与实践**: - 学习如何正确解读STATSPACK报告,理解各种性能指标的含义。 - 实战演练,模拟性能问题并...
《Oracle相关SQL葵花宝典》是一本专为学习Oracle数据库管理系统中SQL语言及PL/SQL编程设计的综合指南。本书全面涵盖了从基础到高级的Oracle SQL知识,旨在帮助读者熟练掌握在Oracle环境中进行数据查询、操作、分析...
Oracle SQL优化是数据库管理员和开发人员提升系统性能的关键技能。Oracle数据库系统因其高效、稳定和功能强大而被广泛使用,但随着数据量的增长,SQL查询的优化变得至关重要。本资源"Oracle_SQL优化.PDF"虽然内容...
1. 使用EXPLAIN PLAN分析查询:Oracle提供EXPLAIN PLAN工具,用于分析SQL执行计划,帮助找出潜在的性能瓶颈。 2.绑定变量:使用绑定变量可以减少硬解析,提高SQL执行效率。 3. 优化连接顺序:JOIN操作中,优化连接...
Oracle PL/SQL是Oracle数据库系统中的重要组成部分,用于创建复杂的业务逻辑和数据库处理。以下是对题目中提到的一些关键知识点的详细解释: 1. **冷备份与热备份**:冷备份是在数据库关闭状态下进行的,简单且可靠...
Oracle SQL疑难解析是一本专为解决数据库操作中遇到的实际问题而编写的书籍,它涵盖了大量SQL查询、数据处理和性能优化的实用技巧。在"oracle-sql-recipes-master"这个压缩包中,很可能是包含了书中的示例代码和练习...
Oracle Instant Client是Oracle公司提供的一款轻量级的数据库连接工具,它允许用户在不安装完整Oracle数据库的情况下,进行Oracle数据库的连接、查询和管理。在本案例中,我们讨论的是Oracle Instant Client的11.2...
Oracle SQL编写规范 Oracle SQL编写规范是指在编写SQL语句时的一些基本原则和方法,旨在提高SQL语句的执行效率和可读性。以下是Oracle SQL编写规范的详细解释: 1. 尽量用索引,特别在从大量数据中返回小部分数据...