知识大全 适时增加Distinct提高查询效率

Posted 操作

篇首语:知识是有学问的人的第二个太阳。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 适时增加Distinct提高查询效率相关的知识,希望对你有一定的参考价值。

适时增加Distinct提高查询效率  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

只有增加DISTINCT关键字 Oracle必然需要对后面的所有字段进行排序 以前也经常发现由于开发人员对SQL不是很理解 在SELECT列表的 多个字段前面添加了DISTINCT 造成查询基本上不可能执行完成 甚至产生ORA 错误 所以一直向开发人员强调DISTINCT给性能带来的影响

  没想到开发人员在测试一条大的SQL的时候 告诉我如果加上了DISTINCT 则查询大概需要 分钟左右可以执行完 如果不加DISTINCT 则查询执行了 多分钟 仍然得不到结果

  首先想到的是可能DISTINCT是在子查询中 由于加上了DISTINCT 将第一步结果集缩小了 导致查询性能提高 结果一看SQL 发现DISTINCT居然是在查询的最外层

  由于原始SQL太长 而且牵扯的表太多 很难说清楚 这里模拟了一个例子 这个例子由于数据量和SQL的复杂程度限制 无法看出二者执行时间上的明显差别 这里从两种情况的逻辑读对比来说明问题

  首先建立模拟环境  

SQL> CREATE TABLE T AS SELECT * FROM DBA_OBJECTS   WHERE OWNER = SYS    AND OBJECT_TYPE NOT LIKE %BODY    AND OBJECT_TYPE NOT LIKE JAVA% ;  Table created   SQL> CREATE TABLE T AS SELECT * FROM DBA_SEGMENTS WHERE OWNER = SYS ;  Table created   SQL> CREATE TABLE T AS SELECT * FROM DBA_INDEXES WHERE OWNER = SYS ;  Table created   SQL> ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (OBJECT_NAME);  Table altered   SQL> CREATE INDEX IND_T _SEGNAME ON T (SEGMENT_NAME);  Index created   SQL> CREATE INDEX IND_T _TABNAME ON T (TABLE_NAME);  Index created   SQL> EXEC DBMS_STATS GATHER_TABLE_STATS(USER T METHOD_OPT => FOR ALL INDEXED COLUMNS SIZE CASCADE => TRUE)  PL/SQL procedure successfully pleted   SQL> EXEC DBMS_STATS GATHER_TABLE_STATS(USER T METHOD_OPT => FOR ALL INDEXED COLUMNS SIZE CASCADE => TRUE)  PL/SQL procedure successfully pleted   SQL> EXEC DBMS_STATS GATHER_TABLE_STATS(USER T METHOD_OPT => FOR ALL INDEXED COLUMNS SIZE CASCADE => TRUE)  PL/SQL procedure successfully pleted

  仍然沿用上面例子中的结构 看看原始SQL和增加DISTINCT后的差别

SQL> SET AUTOT TRACE  SQL> SELECT T OBJECT_NAME T OBJECT_TYPE T TABLESPACE_NAME   FROM T T    WHERE T OBJECT_NAME = T SEGMENT_NAME   AND T OBJECT_NAME IN   (   SELECT INDEX_NAME FROM T    WHERE T TABLESPACE_NAME = T TABLESPACE_NAME   );   rows selected   Execution Plan      SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes= )   HASH JOIN (SEMI) (Cost= Card= Bytes= )   HASH JOIN (Cost= Card= Bytes= )   TABLE ACCESS (FULL) OF T (Cost= Card= Bytes= )   TABLE ACCESS (FULL) OF T (Cost= Card= Bytes= )   TABLE ACCESS (FULL) OF T (Cost= Card= Bytes= )  Statistics      recursive calls   db block gets   consistent gets   physical reads   redo size   bytes sent via SQL*Net to client   bytes received via SQL*Net from client   SQL*Net roundtrips to/from client   sorts (memory)   sorts (disk)   rows processed  SQL> SELECT DISTINCT T OBJECT_NAME T OBJECT_TYPE T TABLESPACE_NAME   FROM T T    WHERE T OBJECT_NAME = T SEGMENT_NAME   AND T OBJECT_NAME IN   (   SELECT INDEX_NAME FROM T    WHERE T TABLESPACE_NAME = T TABLESPACE_NAME   );   rows selected   Execution Plan      SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes= )   SORT (UNIQUE) (Cost= Card= Bytes= )   HASH JOIN (Cost= Card= Bytes= )   HASH JOIN (Cost= Card= Bytes= )   TABLE ACCESS (FULL) OF T (Cost= Card= Bytes= )   TABLE ACCESS (FULL) OF T (Cost= Card= Bytes= )   TABLE ACCESS (FULL) OF T (Cost= Card= Bytes= )  Statistics      recursive calls   db block gets   consistent gets   physical reads   redo size   bytes sent via SQL*Net to client   bytes received via SQL*Net from client   SQL*Net roundtrips to/from client   sorts (memory)   sorts (disk)   rows processed

  从统计信息可以看出 添加了DISTINCT后 语句的逻辑读反而比不加DISTINCT要高 为什么会产生这种情况 还要从执行计划说起

  不加DISTINCT的情况 由于使用IN子查询的查询 Oracle对第二个连接采用了HASH JOIN SEMI 这种HASH JOIN SEMI相对于普通的HASH JOIN 代价要大一些

  而添加了DISTINCT之后 Oracle知道最终肯定要进行排序去重的操作 因此在连接的时候就选择了HASH JOIN作为了连接方式 这就是为什么加上了DISTINCT之后 逻辑读反而减少了 但是同时 加上了DISTINCT之后 语句增加了一个排序操作 而在不加DISTINCT的时候 是没有这个操作的

  当连接的表数据量很大 但是SELECT的最终结果不是很多 且SELECT列的个数不是很多的时候 加上DISTINCT之后 这个排序的代价要小于SEMI JOIN连接的代价 这就是增加一个DISTINCT操作查询效率反而提高 这个似乎不可能发生的情况的真正原因

cha138/Article/program/Oracle/201311/18286

相关参考

知识大全 用Distinct在MySQL中查询多条不重复记录值[1]

用Distinct在MySQL中查询多条不重复记录值[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 用Distinct在MySQL中查询多条不重复记录值[2]

用Distinct在MySQL中查询多条不重复记录值[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 oracle提高查询效率

  ()选择最有效率的表名顺序(只在基于规则的优化器中有效) ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名FROM子句中写在最后的表(基础表drivingtable)将被最先处理在F

知识大全 Oracle高级查询实例,提升效率

Oracle高级查询实例,提升效率  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  使用Oracl

平衡施肥提高玉米种植效率

科学的施肥方法是提高玉米产量的重要手段,随着玉米产量的不断提高,化肥投入的不断增加,盲目施肥现象也随之更加严重。如氮肥投入过多,钾肥、微肥用量不足,造成土壤养分不平衡,肥料利用率下降,玉米产量降低玉米

平衡施肥提高玉米种植效率

科学的施肥方法是提高玉米产量的重要手段,随着玉米产量的不断提高,化肥投入的不断增加,盲目施肥现象也随之更加严重。如氮肥投入过多,钾肥、微肥用量不足,造成土壤养分不平衡,肥料利用率下降,玉米产量降低玉米

有效保温防冻 提高农机使用效率

冬季由于天气严寒,给农业机械的使用和维护工作带来诸多不便。发动机不仅难以启动,而且耗油量也会增加,极易产生冰冻,所以有效保温防冻成为严寒季节提高农机使用效率的关键。一、防止冻裂机件1.一天作业结束后,

有效保温防冻 提高农机使用效率

冬季由于天气严寒,给农业机械的使用和维护工作带来诸多不便。发动机不仅难以启动,而且耗油量也会增加,极易产生冰冻,所以有效保温防冻成为严寒季节提高农机使用效率的关键。一、防止冻裂机件1.一天作业结束后,

知识大全 MySQL使用rand随机查询记录效率测试

MySQL使用rand随机查询记录效率测试  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  以下的

知识大全 Oracle分页查询中排序与效率问题

Oracle分页查询中排序与效率问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  原始未分页查