`
micheal19840929
  • 浏览: 166242 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

恒等查询条件改变执行计划——SQL优化之Everything is Possible

阅读更多

有的时候开发人员为了方便会在WHERE语句后面添加一个1=1,这样在处理页面传入的条件是就可用不用判断直接添加AND 条件。
一直认为添加一个恒等条件,不会对Oracle的查询造成什么影响,最多不过影响一下Oracle的性能,但是今天突然发现,这个恒等的查询条件居然可以影响Oracle的执行计划。


首先看一个简单的例子:
SQL> CREATE TABLE T1 AS SELECT * FROM DBA_OBJECTS
2 WHERE OWNER = 'SYS'
3 AND OBJECT_TYPE NOT LIKE '%BODY'
4 AND OBJECT_TYPE NOT LIKE 'JAVA%';
Table created.
SQL> CREATE TABLE T2 AS SELECT * FROM DBA_SEGMENTS WHERE OWNER = 'SYS';
Table created.
SQL> CREATE TABLE T3 AS SELECT * FROM DBA_INDEXES WHERE OWNER = 'SYS';
Table created.
SQL> ALTER TABLE T1 ADD CONSTRAINT PK_T1 PRIMARY KEY (OBJECT_NAME);
Table altered.
SQL> CREATE INDEX IND_T2_SEGNAME ON T2(SEGMENT_NAME);
Index created.
SQL> CREATE INDEX IND_T3_TABNAME ON T3(TABLE_NAME);
Index created.
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T1', METHOD_OPT => 'FOR ALL INDEXED COLUMNS SIZE 100', CASCADE => TRUE)
PL/SQL procedure successfully completed.
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T2', METHOD_OPT => 'FOR ALL INDEXED COLUMNS SIZE 100', CASCADE => TRUE)
PL/SQL procedure successfully completed.
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T3', METHOD_OPT => 'FOR ALL INDEXED COLUMNS SIZE 100', CASCADE => TRUE)
PL/SQL procedure successfully completed.
SQL> SET AUTOT TRACE EXP
SQL> SELECT T1.OBJECT_NAME, T1.OBJECT_TYPE, T2.TABLESPACE_NAME
2 FROM T1, T2
3 WHERE T1.OBJECT_NAME = T2.SEGMENT_NAME
4 AND NOT EXISTS
5 (
6 SELECT 1 FROM T3
7 WHERE T3.INDEX_NAME = T1.OBJECT_NAME
8 AND T3.TABLE_NAME = 'OBJ$'
9 )
10 ;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=668 Bytes=58784)
1 0 HASH JOIN (ANTI) (Cost=12 Card=668 Bytes=58784)
2 1 HASH JOIN (Cost=9 Card=668 Bytes=39412)
3 2 TABLE ACCESS (FULL) OF 'T2' (Cost=2 Card=668 Bytes=21376)
4 2 TABLE ACCESS (FULL) OF 'T1' (Cost=6 Card=3806 Bytes=102762)
5 1 TABLE ACCESS (BY INDEX ROWID) OF 'T3' (Cost=2 Card=2 Bytes=58)
6 5 INDEX (RANGE SCAN) OF 'IND_T3_TABNAME' (NON-UNIQUE) (Cost=1 Card=2)

SQL> SELECT T1.OBJECT_NAME, T1.OBJECT_TYPE, T2.TABLESPACE_NAME
2 FROM T1, T2
3 WHERE T1.OBJECT_NAME = T2.SEGMENT_NAME
4 AND NOT EXISTS
5 (
6 SELECT 1 FROM T3
7 WHERE 1 = 1
8 AND T3.INDEX_NAME = T1.OBJECT_NAME
9 AND T3.TABLE_NAME = 'OBJ$'
10 )
11 ;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=668 Bytes=50768)
1 0 HASH JOIN (ANTI) (Cost=12 Card=668 Bytes=50768)
2 1 HASH JOIN (Cost=9 Card=668 Bytes=39412)
3 2 TABLE ACCESS (FULL) OF 'T2' (Cost=2 Card=668 Bytes=21376)
4 2 TABLE ACCESS (FULL) OF 'T1' (Cost=6 Card=3806 Bytes=102762)
5 1 VIEW OF 'VW_SQ_1' (Cost=2 Card=2 Bytes=34)
6 5 TABLE ACCESS (BY INDEX ROWID) OF 'T3' (Cost=2 Card=2 Bytes=58)
7 6 INDEX (RANGE SCAN) OF 'IND_T3_TABNAME' (NON-UNIQUE) (Cost=1 Card=2)

观察两个查询语句会发现,两个查询语句唯一的区别就是第二个查询语句中的NOT EXISTS子查询中包含了一个恒等查询条件1 = 1。
仅仅是这一点的区别,却造成了两个SQL语句的执行计划出现了差异。对于第二个查询Oracle居然多生成了一个临时的VIEW。也许有人认为这个执行计划没有太大的区别,基本上可以认为等价。但是由于多生成了一个VIEW的步骤,必然会造成性能的下降,更为关键的是:这说明Oracle认为两个SQL语句是不同的,而且处理方式也是不同的。
如果一个简单的VIEW步骤还不能说明什么问题的话,那么看看下面这个在实际运行中碰到的问题:
SQL> SET AUTOT TRACE EXP
SQL> SELECT A.ID,
2 B.NAME_CHN,
3 B.SPEC,
4 A.MANUFACTURE_ID
5 FROM CAT_PRODUCT A,
6 CAT_DRUG B
7 WHERE A.MEDICAL_ID = B.ID
8 AND A.CHECK_FLAG = 1
9 AND NOT EXISTS
10 (
11 SELECT 1
12 FROM PROJECT_SUPPLY_PRODUCT C
13 WHERE C.DATA_PRODUCT = A.ID
14 AND C.ENABLE_FLAG = '1'
15 AND C.PROJECT_ID = 'MRBR00000000000000709824'
16 )
17 ;
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=483 Card=1 Bytes=213)
1 0 NESTED LOOPS (ANTI) (Cost=483 Card=1 Bytes=213)
2 1 NESTED LOOPS (Cost=481 Card=1 Bytes=160)
3 2 VIEW OF 'index$_join$_001' (Cost=480 Card=1 Bytes=77)
4 3 HASH JOIN
5 4 HASH JOIN
6 5 INDEX (FAST FULL SCAN) OF 'PK_CAT_PRODUCT' (UNIQUE) (Cost=33 Card=1 Bytes=77)
7 5 INDEX (FAST FULL SCAN) OF 'TU_CAT_PRODUCT_MED_CHECK' (NON-UNIQUE) (Cost=33 Card=1 Bytes=77)
8 4 INDEX (FAST FULL SCAN) OF 'TU_CAT_PRODUCT_MANUFACT_ID' (NON-UNIQUE) (Cost=33 Card=1 Bytes=77)
9 2 TABLE ACCESS (BY INDEX ROWID) OF 'CAT_DRUG' (Cost=1 Card=1 Bytes=83)
10 9 INDEX (UNIQUE SCAN) OF 'PK_CAT_DRUG' (UNIQUE)
11 1 TABLE ACCESS (BY INDEX ROWID) OF 'PROJECT_SUPPLY_PRODUCT' (Cost=2 Card=1 Bytes=53)
12 11 INDEX (RANGE SCAN) OF 'IDX_PROJECT_SUPPLY_PRODUCT_PJ' (NON-UNIQUE) (Cost=1 Card=1)

SQL> SELECT A.ID,
2 B.NAME_CHN,
3 B.SPEC,
4 A.MANUFACTURE_ID
5 FROM CAT_PRODUCT A,
6 CAT_DRUG B
7 WHERE A.MEDICAL_ID = B.ID
8 AND A.CHECK_FLAG = 1
9 AND NOT EXISTS
10 (
11 SELECT 1
12 FROM PROJECT_SUPPLY_PRODUCT C
13 WHERE 1 = 1
14 AND C.DATA_PRODUCT = A.ID
15 AND C.ENABLE_FLAG = '1'
16 AND C.PROJECT_ID = 'MRBR00000000000000709824'
17 )
18 ;
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=484 Card=1 Bytes=186)
1 0 HASH JOIN (ANTI) (Cost=484 Card=1 Bytes=186)
2 1 NESTED LOOPS (Cost=481 Card=1 Bytes=160)
3 2 VIEW OF 'index$_join$_001' (Cost=480 Card=1 Bytes=77)
4 3 HASH JOIN
5 4 HASH JOIN
6 5 INDEX (FAST FULL SCAN) OF 'PK_CAT_PRODUCT' (UNIQUE) (Cost=33 Card=1 Bytes=77)
7 5 INDEX (FAST FULL SCAN) OF 'TU_CAT_PRODUCT_MED_CHECK' (NON-UNIQUE) (Cost=33 Card=1 Bytes=77)
8 4 INDEX (FAST FULL SCAN) OF 'TU_CAT_PRODUCT_MANUFACT_ID' (NON-UNIQUE) (Cost=33 Card=1 Bytes=77)
9 2 TABLE ACCESS (BY INDEX ROWID) OF 'CAT_DRUG' (Cost=1 Card=1 Bytes=83)
10 9 INDEX (UNIQUE SCAN) OF 'PK_CAT_DRUG' (UNIQUE)
11 1 VIEW OF 'VW_SQ_1' (Cost=2 Card=1 Bytes=26)
12 11 TABLE ACCESS (BY INDEX ROWID) OF 'PROJECT_SUPPLY_PRODUCT' (Cost=2 Card=1 Bytes=53)
13 12 INDEX (RANGE SCAN) OF 'IDX_PROJECT_SUPPLY_PRODUCT_PJ' (NON-UNIQUE) (Cost=1 Card=1)
SQL语句仍然是只相差了NOT EXISTS语句中的一个1 = 1的恒等条件,但是如果不加这个恒等条件,Oracle用的是NESTED LOOP ANTI,而加上了这个恒等条件,则Oracle选择了HASH JOIN ANTI。
这次执行计划的改变足以使SQL的执行时间发生成百上千倍的变化。
一个小小的恒等查询条件居然可以使查询计划发生变化,这是我从来没有想到的。
通过这个问题,我总结了如下三点:
要敢于怀疑任何事情,没有什么是不可能的,一切以实践的结果为准;
不要在SQL上添加一些没有必要的小零碎,一些看似无害的东西在一些情况下可能会引发严重的问题。
建立良好的编码风格,以及严格SQL语句的编写制度的必要性。

 

分享到:
评论

相关推荐

    Sql Server——Sql性能优化

    Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化

    SQL优化 SQL优化软件 SQL优化工具

    1. **查询分析**:这些工具能够分析SQL语句的执行计划,指出可能存在的问题,如不必要的全表扫描、排序操作过多或使用了低效的索引等。 2. **性能监控**:实时监控数据库的性能指标,如CPU使用率、I/O等待时间、...

    《数据挖掘原理与应用——SQL Server 2005 数据库》算法案例

    《数据挖掘原理与应用——SQL Server 2005 数据库》是一本深入探讨数据挖掘技术的书籍,其中包含了丰富的算法实例,旨在帮助读者理解并掌握如何在SQL Server 2005环境下进行数据挖掘实践。数据挖掘是利用统计学、...

    大数据查询与分析技术——SQL on Hadoop.pdf

    大数据查询与分析技术——SQL on Hadoop.pdf 大数据查询与分析技术是当前热门话题之一,特别是在“互联网+”、“云计算”和“大数据”时代中。为了适应SQL专业分析人员的操作习惯和简化大数据分析方法,SQL on ...

    sql 优化基础——程序员必看

    本文将围绕SQL优化基础,包括SQL的书写规则、执行计划的理解、索引的分类与原理以及SQL优化案例进行详细阐述。 首先,SQL的书写规则是优化的基础。规范的SQL语句能避免不必要的计算和扫描,从而提高执行效率。例如...

    MySQL SQL执行计划分析与优化方案.pptx

    通过分析 SQL 执行计划,可以了解 MySQL 是如何执行查询的,并且可以根据执行计划来优化查询性能。下面将对 MySQL SQL 执行计划分析与优化方案进行详细的分析和介绍。 读懂最简单的 SQL 读懂最简单的 SQL 是学习 ...

    打造网站的坚盾——SQL注入防范专题——SQL注入防范之完善网站程序.pdf

    本文档《打造网站的坚盾——SQL注入防范专题——SQL注入防范之完善网站程序》针对如何增强ASP等网站程序抵抗SQL注入攻击的能力提供了专业指导。 首先,文档强调了SQL注入攻击的基本原理,即攻击者在用户可输入的...

    收获不止SQL优化

    第1章 全局在胸——用工具对SQL整体优化 1 1.1 都有哪些性能工具 1 1.1.1 不同调优场景分析 2 1.1.2 不同场景对应工具 2 1.2 整体性能工具的要点 4 1.2.1 五大性能报告的获取 5 1.2.2 五大报告关注的要点 10 ...

    学校教务管理系统VS——SQL

    ADO.NET提供了数据访问组件,如DataSet、DataTable、SqlCommand等,方便开发者执行SQL查询,处理数据流,并将结果展示在用户界面上。 对于初学者来说,这个项目有助于理解面向对象编程的概念,如类、对象、继承和多...

    数据库应用技术——SQL Server 2000简明教程电子教案

    "数据库应用技术——SQL Server 2000简明教程电子教案"将带领学习者深入了解如何使用SQL Server 2000进行数据库管理,从基础概念到高级应用,覆盖了数据库设计、数据操作、安全管理、性能优化等多个方面,是学习和...

    数据库程序设计——SQL Server 2000数据库程序设计【学生用光盘(2)】.part4

    数据库程序设计——SQL Server 2000数据库程序设计【学生用光盘(2)】.part1 ; 数据库程序设计——SQL Server 2000数据库程序设计【学生用光盘(2)】.part2 ; 数据库程序设计——SQL Server 2000数据库程序设计...

    PHP——SQL注入测试靶场

    在这个靶场中,用户可以尝试模拟不同的SQL注入攻击,例如基于错误的注入、联合查询注入、时间基注入等。通过这些实践,可以深入理解SQL语句的构造和执行过程,以及如何通过过滤和转义输入来防止注入攻击。 首先,...

    数据库技术及应用——SQL Server 2005-电子教案

    最后,SQL Server 2005还支持多种高级特性,如全文搜索、XML支持、分区视图和并行查询等,这些都是提高数据处理能力的有力工具。 总的来说,《数据库技术及应用——SQL Server 2005》电子教案将带领学习者全面探索...

    数据库应用技术——SQL Server 2005篇(第2版)

    "数据库应用技术——SQL Server 2005篇(第2版)-源代码.rar" 文件则提供了配套的程序代码示例,让学习者能够亲手实践SQL语句的编写和执行,从而更好地理解和运用所学知识。源代码通常包括各种查询、插入、更新、删除...

    收获,不止SQL优化 PDF 带书签 第三部分

    首先教你SQL整体优化、快速优化实施、如何读懂执行计划、如何左右执行计划这四大必杀招。整这些干嘛呢?答案是,传授一个先整体后局部的宏观解决思路,走进“道”的世界。 接下来带领大家飞翔在“术”的天空。教你...

    数据库应用技术——SQL Server篇》 课件下载

    《数据库应用技术——SQL Server篇》是一门深入探讨SQL Server这一流行关系型数据库管理系统(RDBMS)的课程。SQL Server是微软公司推出的一款强大的数据库解决方案,广泛应用于数据存储、管理和分析。通过本课程,...

    《数据库原理与应用——SQL Server 2000》电子教案

    《数据库原理与应用——SQL Server 2000》是一本深入探讨数据库理论与实践的教材,特别关注了Microsoft SQL Server 2000这一版本。在这个电子教案中,我们将会学习到关于数据库设计、创建、管理和优化的全方位知识。...

    《数据库——sql语法大全》

    学习SQL,读者将能理解如何执行数据库查询,提取所需信息,并学会设计和构建自己的数据库。 接下来,书中详细阐述了以下几个关键概念: 1. **创建新表**:创建表格是数据库管理的基础,表由行和列组成,每一行代表...

    读懂oracle sql执行计划

    Oracle SQL执行计划是指Oracle数据库为SQL语句制定的一系列执行步骤,这些步骤指导数据库如何高效地访问数据和执行SQL语句。执行计划对于Oracle数据库的性能调优至关重要,因为它能够揭示SQL语句的执行细节,帮助...

Global site tag (gtag.js) - Google Analytics