`
sangei
  • 浏览: 336302 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

(转)Oracle sql 优化1

阅读更多

   ORACLE有个高速缓冲的概念,这个高速缓冲呢就是存放执行过的SQL语句,那oracle在执行sql语句的时候要做很多工作,例如解析sql语句,估算索引利用率,绑定变量,读取数据块等等这些操作。假设高速缓冲里已经存储了执行过的sql语句,那就直接匹配执行了,少了步骤,自然就快了,但是经过测试会发现高速缓冲只对简单的表起作用,多表的情况小完全没有效果啊,例如在查询单表的时候那叫一个快,但是假设连接多个表,就龟速了。

    最重要一点,ORACLE的高速缓冲是全字符匹配的,什么意思呢,看下面三个select

 

--No.1
select * from tableA;
--No.2
select * From tableA;
--No.3
select   * from tableA;

这三个语句乍一看是一样的,但是高速缓存是不认的,是全字符匹配的,索引在高速缓存里会存储三条不同的语句,说道这里,又引出一个习惯,就是要保持良好的编程习惯,这个很重要啊。

 ORACLE的多表优化我积累了一些,都是常用的,介绍下

第一点呢是From 子句后面的 表顺序有讲究

   先说为啥,ORACLE在解析sql语句的时候对From子句后面的表名是从右往左解析的,是先扫描最右边的表,然后在扫描左边的表,然后用左边的表匹配数据,匹配成功后就合并。

   所以,在对多表查询中,一定要把小表写在最右边,为什么自己想想就明白了。例如下面的两个语句:

 

--No.1  tableA 100w条记录  tableB 1w条记录 执行速度 十秒级
select count(*) from tableA,tableB;
  
--No.2  执行速度百秒级甚至更高
select count(*) from tableB,tableA;  

这个估计很多人都知道,但是要确认非常有用。

还有一种是三张表的查询,例如

 

select count(1) from tableA a,tableB b ,tableC c where a.id=b.id and a.id=c.id;

上面种 tableA 就称为交叉表,根据oracle对From子句从右向左的扫描方式,应该把交叉表放在最末尾,然后才是最小表,所以上面的应该这样写

--tableA a 交叉表 
--tabelB b 100w
--tableC c 1w
select count(1) from tableB b ,tableC c ,tableA a where a.id=b.id and a.id=c.id;

这种写法对大数据量会非常有用,大家谨记,也是很常用的。

第二点呢是Where子句后面的条件过滤有讲究,ORACLE对where子句后面的条件过滤是自下向上,从右向左扫描的,所以和From子句一样一样的,把过滤条件排个序,按过滤数据的大小,自然就是最少数据的那个条件写在最下面,最右边,依次类推,例如

 

--No.1 不可取 性能低下
select * from tableA a where 
a.id>500
and a.lx = '2b'
and a.id < 'select count(1) from tableA  where id=a.id '

--No.2 性能高
select * from tableA a where 
a.id < 'select count(1) from tableA  where id=a.id '
and a.id>500
and a.lx = '2b'

第三点呢估计搞数据库的都知道啦,就是在select的时候少用*,多敲敲键盘,写上字段名吧,因为ORACLE的查询器会把*转换为表的全部列名,这个会浪费时间的,所以在大表中少用。

第四点呢就是要使用rowid 这个很好啊,可以用来分页,删除查询重复记录,很强大的,给两个例子,rownum是用在分页:

 

下面总结一下几种查找和删除重复记录的方法(以表CZ为例):

CZ的结构如下:

SQL> desc cz

            Name Null? Type

            ----------------------------------------- 

             C1 NUMBER(10)

            C10 NUMBER(5)

            C20 VARCHAR2(3)

删除重复记录的方法原理:

(1).Oracle中,每一条记录都有一个rowidrowid在整个数据库中是唯一的,rowid确定了每条记录是在Oracle中的哪一个数据文件、块、行上。

(2).在重复的记录中,可能所有列的内容都相同,但rowid不会相同,所以只要确定出重复记录中那些具有最大rowid的就可以了,其余全部删除。

重复记录判断的标准是:

C1,C10C20这三列的值都相同才算是重复记录。

经查看表CZ总共有16条记录:

SQL>set pagesize 100

SQL>select * from cz;

    C1 C10 C20

 ---------- ---------- ---

     1 2 dsf

     1 2 dsf

     1 2 dsf

     1 2 dsf

     2 3 che

     1 2 dsf

     1 2 dsf

     1 2 dsf

     1 2 dsf

     2 3 che

     2 3 che

     2 3 che

     2 3 che

     3 4 dff

     3 4 dff

     3 4 dff

     4 5 err

     5 3 dar

     6 1 wee

    7 2 zxc

 20 rows selected.

1.查找重复记录的几种方法:

(1).SQL>select * from cz group by c1,c10,c20 having count(*) >1;

          C1 C10 C20

    ---------- ---------- ---

      1 2 dsf

      2 3 che

      3 4 dff

(2).SQL>select distinct * from cz;

            C1 C10 C20

 ---------- ---------- ---

          1 2 dsf

          2 3 che

          3 4 dff

(3).SQL>select * from cz a where rowid=(select max(rowid) from cz where c1=a.c1 and c10=a.c10 and c20=a.c20);
C1 C10 C20
---------- ---------- ---
1 2 dsf
2 3 che
3 4 dff

2.删除重复记录的几种方法:

(1).适用于有大量重复记录的情况(C1,C10C20列上建有索引的时候,用以下语句效率会很高)

SQL>delete cz where (c1,c10,c20) in (select c1,c10, c20 from cz group by c1,c10,c20 having count(*)>1) and rowid not in (select min(rowid) from cz group by c1,c10,c20 having count(*)>1);
SQL>delete cz where rowid not in (select min(rowid) from cz group by c1,c10,c20);

(2).适用于有少量重复记录的情况(注意,对于有大量重复记录的情况,用以下语句效率会很低)

SQL>delete from cz a where a.rowid!=(select max(rowid) from cz b where a.c1=b.c1 and a.c10=b.c10 and a.c20=b.c20);

SQL>delete from cz a where a.rowid<(select max(rowid)    from cz b where a.c1=b.c1 and a.c10=b.c10 and a.c20=b.c20);
SQL>delete from cz a where rowid <(select max(rowid) from cz where c1=a.c1 and c10=a.c10 and c20=a.c20);

(3).适用于有少量重复记录的情况(临时表法)

SQL>create table test as select distinct * from cz;    (建一个临时表test用来存放重复的记录)
SQL>truncate table cz; (清空cz表的数据,但保留cz表的结构)
SQL>insert into cz select * from test;       (再将临时表test里的内容反插回来)

(4).适用于有大量重复记录的情况(Exception into 子句法)

采用alter table 命令中的 Exception into 子句也可以确定出库表中重复的记录。这种方法稍微麻烦一些,为了使用“excepeion into ”子句,必须首先创建 EXCEPTIONS 表。创建该表的 SQL 脚本文件为 utlexcpt.sql 。对于win2000系统和 UNIX 系统, Oracle 存放该文件的位置稍有不同,在win2000系统下,该脚本文件存放在$ORACLE_HOMEOra90rdbmsadmin 目录下;而对于 UNIX 系统,该脚本文件存放在$ORACLE_HOME/rdbms/admin 目录下

体步骤如下:

SQL>@?/rdbms/admin/utlexcpt.sql

            Table created.

            SQL>desc exceptions

            Name Null? Type

            ----------------------------------------- 

            ROW_ID ROWID

            OWNER VARCHAR2(30)

            TABLE_NAME VARCHAR2(30)

            CONSTRAINT VARCHAR2(30)

            SQL>alter table cz add constraint cz_unique unique(c1,c10,c20) exceptions into exceptions; 

            ERROR at line 1:

           ORA-02299: cannot validate (TEST.CZ_UNIQUE) - duplicate keys found

            SQL>create table dups as select * from cz where rowid in (select row_id from exceptions); 

            Table created.

            SQL>select * from dups; 

            C1 C10 C20

           ---------- ---------- ---

            1 2 dsf

            1 2 dsf

           1 2 dsf

            1 2 dsf

            2 3 che

           1 2 dsf

            1 2 dsf

           1 2 dsf

            1 2 dsf

            2 3 che

            2 3 che

            2 3 che

            2 3 che

            3 4 dff

           3 4 dff

           3 4 dff

            16 rows selected.

            SQL>select row_id from exceptions;

            ROW_ID

           ------------------

           AAAHD/AAIAAAADSAAA

           AAAHD/AAIAAAADSAAB

            AAAHD/AAIAAAADSAAC

            AAAHD/AAIAAAADSAAF

            AAAHD/AAIAAAADSAAH

           AAAHD/AAIAAAADSAAI

            AAAHD/AAIAAAADSAAG

            AAAHD/AAIAAAADSAAD

            AAAHD/AAIAAAADSAAE

            AAAHD/AAIAAAADSAAJ

            AAAHD/AAIAAAADSAAK

            AAAHD/AAIAAAADSAAL

           AAAHD/AAIAAAADSAAM

            AAAHD/AAIAAAADSAAN

            AAAHD/AAIAAAADSAAO

            AAAHD/AAIAAAADSAAP

           16 rows selected.

            SQL>delete from cz where rowid in ( select row_id from exceptions);

            16 rows deleted.

            SQL>insert into cz select distinct * from dups;

           3 rows created.

            SQL>select *from cz;

            C1 C10 C20

            ---------- ---------- ---

1 2 dsf

2 3 che

3 4 dff

4 5 err

5 3 dar

6 1 wee

7 2 zxc

7 rows selected.

从结果里可以看到重复记录已经删除。

Oracle查询删除表中重复记录

最高效删除重复记录的方法,使用为例rowid

DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);

     1、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断
  select * from people where peopleId in (select   peopleId from   people group by   peopleId having count(peopleId) > 1)
  2、删除表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断,只留有 rowid最小的记录
  delete from people where peopleId in (select   peopleId from people group by   peopleId   having count(peopleId) > 1) and rowid not in (select min(rowid) from   people group by peopleId having count(peopleId )>1)
  注:rowidoracle自带不用该.....
  3、查找表中多余的重复记录(多个字段)
  select * from vitae a where (a.peopleId,a.seq) in   (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1)
  4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录
  delete from vitae a where (a.peopleId,a.seq) in   (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1) and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)>1)
  5、查找表中多余的重复记录(多个字段),不包含rowid最小的记录
  select * from vitae a where (a.peopleId,a.seq) in   (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1) and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)>1)
  ()比方说 在A表中存在一个字段“name”,而且不同记录之间的“name”值有可能会相同,现在就是需要查询出在该表中的各记录之间,“name”值存在重复的项;
  Select Name,Count(*) From A Group By Name Having Count(*) > 1
  如果还查性别也相同大则如下:
  Select Name,sex,Count(*) From A Group By Name,sex Having Count(*) > 1

--分页 start=10 limit=10 --end 为 start + limit select * from ( select A.*,Rownum rn from (select * from tableA order by id) A where rownum <= 20 ) b wehre rn> 10 order by id desc /*解释一下, 1.查询要排列的表 A 2.查询A表的Rownum 找出小于end的数据 组成表B 3.查询B表通过rownum找出大于start的数据 完成 简单的说先根据end值过滤数据,然后在根据start过滤数据 so 简单的 */

第五点是存储过程中需要注意的,多用commit了,既可以释放资源,但是要谨慎啊。

第六点是减少对数据库表的查询,这个很重要,能减少就减少,因为在执行语句的时候oracle会做很多初始工作。

第七点不要用in啦,用exists来代替咯,例如:

 

--NO.1  IN的写法  
SELECT * FROM TABLEA A WHERE 
A.ID IN 
( SELECT ID FORM TABLEB B WHERE B.ID>1)

--NO.2 exists 写法
SELECT * FROM TABLEA A WHERE
EXISTS (
SELECT 1 FROM TABLEB B WHERE A.ID=B.ID AND B.ID>1)

相同的还有使用not exists 代替 not in ,方法雷同啊,就不介绍了。

那还有一些简单的方法,例如索引这些就比较简单了,就不介绍了,就写在这里吧。

分享到:
评论

相关推荐

    OracleSQL的优化.pdf

    Oracle SQL 优化 Oracle SQL 优化是数据库性能优化的关键部分。为了提高数据库的性能,我们需要从五个方面进行调整:去掉不必要的大型表的全表扫描、缓存小型表的全表扫描、检验优化索引的使用、检验优化的连接技术...

    ORACLE SQL性能优化系列

    ORACLE SQL性能优化系列 ORACLE SQL性能优化是数据库管理员和开发者非常关心的一个话题。为了提高数据库的性能,ORACLE 提供了多种优化技术。下面我们将详细介绍 ORACLE SQL 性能优化系列中的一些重要知识点。 一...

    oracle SQL优化技巧

    Oracle SQL 优化技巧 Oracle SQL 优化是提高数据库性能的关键技巧之一。以下是 Oracle SQL 优化的 12 个技巧: 1. 选择最有效率的表名顺序 在基于规则的优化器中,Oracle 的解析器按照从右到左的顺序处理 FROM ...

    基于Oracle的SQL优化2

    基于Oracle的SQL优化

    oracle sql优化实战案例

    主要讲述oracle sql 的开发以及优化,对低效率的sql的优化方法和诊断技巧

    ORACLESQL性能优化.pptx

    Oracle SQL 性能优化 Oracle SQL 性能优化是数据库管理中非常重要的一环。通过对 SQL 语句执行的过程、Oracle 优化器、表之间的关联、如何得到 SQL 执行计划、如何分析执行计划等内容的讨论,可以逐步掌握 SQL ...

    基于Oracle的SQL优化1

    基于Oracle的SQL优化

    oracle sql优化

    在Oracle数据库环境中,SQL优化是提升系统性能的关键环节。它涉及到如何有效地检索数据,减少查询时间,减轻数据库服务器的负载,以及改善整体系统的响应速度。本文将深入探讨Oracle SQL优化的相关知识点,帮助你...

    Oracle SQL优化文档

    Oracle SQL优化文档提供了对Oracle数据库进行SQL语句优化的一系列方法和工具,旨在帮助数据库管理员和开发人员提高SQL查询性能和数据库效率。文档内容涵盖了从基本的SQL优化思路到具体的分析工具,详细介绍了如何...

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

    在Oracle环境中,常用的SQL优化工具包括Oracle SQL Developer、Toad for Oracle、SQL Server Management Studio (尽管它是针对SQL Server的)等。这些工具不仅提供了上述功能,还专门针对Oracle数据库的特性进行了...

    oracle sql优化100条

    ### Oracle SQL优化100条概览 在Oracle数据库管理与优化领域,SQL查询的效率直接关系到系统性能和用户体验。以下将详细解读部分Oracle SQL优化原则,涵盖查询执行计划、表扫描方式、SQL语句优化及数据访问顺序等...

    《基于Oracle的SQL优化》PDF版本下载.txt

    根据提供的文件信息,本文将对《基于Oracle的SQL优化》这一主题进行深入解析,包括但不限于SQL优化的重要性、Oracle数据库的特点以及具体的SQL优化方法等。 ### SQL优化的重要性 SQL(Structured Query Language)...

    Oracle 高性能SQL引擎剖析SQL优化与调优机制详解

    深入揭示OracleSQL优化与调优的原理、核心技术与思想方法 盖国强鼎力推荐! Oracle数据库的性能优化直接关系到系统的运行效率,而影响数据库性能的一个重要因素就是SQL性能问题。本书是作者十年磨一剑的成果之一...

    sqlserver自动生成sql语句工具sqlserver转oracle

    1. 数据类型映射:SQL Server和Oracle的数据类型可能存在差异,如SQL Server的`datetime`对应Oracle的`timestamp`,`varchar2`对应`nvarchar2`等,工具会自动进行转换,但也可能需要手动调整。 2. 函数和过程转换:...

    ORACLE SQL优化工具sqlhc

    Oracle SQL优化是数据库管理中的关键任务,用于提升查询性能,减少资源消耗,进而改善整体系统效率。`SQLHC`(SQL Health Check)是Oracle提供的一种实用工具,它可以帮助DBA(数据库管理员)诊断和优化SQL语句。在...

    Oracle SQL 优化与调优技术详解-附录:SQL提示

    在Oracle数据库中,SQL优化是一个至关重要的环节,它能够显著提高数据库查询的效率和性能。本文将详细介绍Oracle SQL中的“提示”(HINT)技术,这是Oracle SQL优化中使用的一项辅助手段,通过为查询提供额外的优化...

    Oracle_SQL优化脚本_完整实用资源

    Oracle SQL优化是数据库管理员和开发人员提升系统性能的关键技能之一。这个"Oracle_SQL优化脚本_完整实用资源"压缩包包含了一系列工具和方法,旨在帮助你优化在Oracle数据库上运行的SQL查询,从而提高数据库的响应...

    落落 Oracle SQL优化与改写培训教程

    大量优化实战方法:将主要SQL优化点一一剖析,分享大量SQL优化的实际工作经验 50余改写调优案例:覆盖大多数DBA日常工作场景,具有相当大的实用价值 技巧+案例:可以作为DBA的参考手册,也可以作为开发人员编写SQL...

    oraclesql优化_Oracle中优化SQL的原则.pdf

    oraclesql优化_Oracle中优化SQL的原则.pdf

Global site tag (gtag.js) - Google Analytics