当前位置:文档之家› SQL语句优化大全

SQL语句优化大全

SQL语句优化大全
SQL语句优化大全

SQL语句培训

文章来源于https://www.doczj.com/doc/ef12789227.html,/ 交流论坛 https://www.doczj.com/doc/ef12789227.html,/

赞助商 https://www.doczj.com/doc/ef12789227.html,/

1.选用适合的ORACLE优化器

ORACLE的优化器共有3种:

a. RULE (基于规则)

b. COST (基于成本)

c. CHOOSE

(选择性)

设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如

RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在

SQL句级或是会话(session)级对其进行覆盖.

为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性.

如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关. 如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器.

2.访问Table的方式

ORACLE 采用两种访问表中记录的方式:

a. 全表扫描

全表扫描就是顺序地访问表中每条记录.

ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描.

b.通过ROWID访问表

你可以采用基于ROWID的访问方式情况,提高访问表的效率, , ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系. 通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高.

3.共享SQL语句

为了不重复解析相同的SQL语句,在第一次解析之后, ORACLE 将SQL语句存放在内存中.这块位于系统全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享. 因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它

和之前的执行过的语句完全相同, ORACLE就能很快获得已经被解析的语句以及最好的

执行路径. ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用.

可惜的是ORACLE只对简单的表提供高速缓冲(cache buffering) ,这个功能并不适用于多表连接查询.

数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性

也就越大了.

当你向ORACLE 提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.

这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须

完全相同(包括空格,换行等).

共享的语句必须满足三个条件:

A. 字符级的比较:

当前被执行的语句和共享池中的语句必须完全相同.

例如:

SELECT * FROM EMP;

和下列每一个都不同

SELECT * from EMP;

Select * From Emp;

SELECT * FROM EMP;

B. 两个语句所指的对象必须完全相同(模式相同)

例如:

用户对象名如何访问

Jack sal_limit private synonym

Work_city public synonym

Plant_detail public synonym

Jill sal_limit private synonym

Work_city public synonym

Plant_detail table owner

考虑一下下列SQL语句能否在这两个用户之间共享.

Jack用户执行

select * from sal_limit

Jill用户执行

select * from sal_limit

C.两个SQL语句中必须使用相同的名字的绑定变量(bind variables)

例如:第一组的两个SQL语句是相同的(可以共享),而第二组中的两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值) a.

select pin , name from people where pin = :blk1.pin;

select pin , name from people where pin = :blk1.pin;

b.

select pin , name from people where pin

= :blk1.ot_ind;

select pin , name from people where pin

= :blk1.ov_ind;

4.选择最有效率的表名顺序(只在基于规则的优化器中有效)

ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.

例如: 表 TAB1 16,384 条记录

表 TAB2 1 条记录

选择TAB2作为基础表 (最好的方法)

select count(*) from tab1,tab2 执行时间0.96秒

选择TAB2作为基础表 (不佳的方法)

select count(*) from tab2,tab1 执行时间26.09秒

如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.

例如: EMP表描述了LOCATION表和CATEGORY表的交集.

SELECT *

FROM LOCATION L ,

CATEGORY C,

EMP E

WHERE E.EMP_NO BETWEEN 1000 AND 2000

AND E.CAT_NO = C.CAT_NO

AND E.LOCN = L.LOCN

将比下列SQL更有效率

SELECT *

FROM EMP E ,

LOCATION L ,

CATEGORY C

WHERE E.CAT_NO = C.CAT_NO

AND E.LOCN = L.LOCN

AND E.EMP_NO BETWEEN 1000 AND 2000

5.WHERE子句中的连接顺序.

ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

例如:

(低效,执行时间156.3秒)

SELECT …

FROM EMP E

WHERE SAL > 50000

AND JOB = …MANAGER?

AND 25 < (SELECT COUNT(*) FROM EMP

WHERE MGR=E.EMPNO);

(高效,执行时间10.6秒)

SELECT …

FROM EMP E

WHERE 25 < (SELECT COUNT(*) FROM EMP

WHERE MGR=E.EMPNO)

AND SAL > 50000

AND JOB = …MANAGER?;

6.SELECT子句中避免使用… * …

当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL 列引用…*? 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将?*? 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.

7.减少访问数据库的次数

当执行每条SQL语句时, ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的工作量.

例如,

以下有三种方法可以检索出雇员号等于0342或0291的

职员.

方法1 (最低效)

SELECT EMP_NAME , SALARY , GRADE

FROM EMP

WHERE EMP_NO = 342;

SELECT EMP_NAME , SALARY , GRADE

FROM EMP

WHERE EMP_NO = 291;

方法2 (次低效)

DECLARE

CURSOR C1 (E_NO NUMBER) IS

SELECT EMP_NAME,SALARY,GRADE

FROM EMP

WHERE EMP_NO = E_NO;

BEGIN

OPEN C1(342);

FETCH C1 INTO …,..,.. ;

OPEN C1(291);

FETCH C1 INTO …,..,.. ;

CLOSE C1;

END;

方法3 (高效)

SELECT A.EMP_NAME , A.SALARY , A.GRADE,

B.EMP_NAME , B.SALARY , B.GRADE

FROM EMP A,EMP B

WHERE A.EMP_NO = 342

AND B.EMP_NO = 291;

注意:

如果有一个表不是返回1条记录而是多条记录的话,会产生卡笛尔乘积.

8.使用DECODE函数来减少处理时间

使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.

例如:

SELECT COUNT(*),SUM(SAL)

FROM EMP

WHERE DEPT_NO = 0020

AND ENAME LIKE?SMITH%?;

SELECT COUNT(*),SUM(SAL)

FROM EMP

WHERE DEPT_NO = 0030

AND ENAME LIKE?SMITH%?;

你可以用DECODE函数高效地得到相同结果

SELECT COUNT(DECODE(DEPT_NO,0020,?X?,NULL))

D0020_COUNT,

COUNT(DECODE(DEPT_NO,0030,?X?,NULL))

D0030_COUNT,

SUM(DECODE(DEPT_NO,0020,SAL,NULL))

D0020_SAL,

SUM(DECODE(DEPT_NO,0030,SAL,NULL))

D0030_SAL

FROM EMP WHERE ENAME LIKE …SMITH%?;

类似的,DECODE函数也可以运用于GROUP BY 和ORDER BY子句中.

9.整合简单,无关联的数据库访问

如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)

例如:

SELECT NAME

FROM EMP

WHERE EMP_NO = 1234;

SELECT NAME

FROM DPT

WHERE DPT_NO = 10 ;

SELECT NAME

FROM CAT

WHERE CAT_TYPE = …RD?;

上面的3个查询可以被合并成一个:

SELECT https://www.doczj.com/doc/ef12789227.html, , https://www.doczj.com/doc/ef12789227.html, , https://www.doczj.com/doc/ef12789227.html,

FROM CAT C , DPT D , EMP E,DUAL X

WHERE NVL(…X?,X.DUMMY) = NVL(…X?,E.ROWID(+))

AND NVL(…X?,X.DUMMY) = NVL(…X?,D.ROWID(+))

AND NVL(…X?,X.DUMMY) = NVL(…X?,C.ROWID(+))

AND E.EMP_NO(+) = 1234

AND D.DEPT_NO(+) = 10

AND C.CAT_TYPE(+) = …RD?;

10.删除重复记录

最高效的删除重复记录方法 ( 因为使用了ROWID)

DELETE FROM EMP E

WHERE E.ROWID > (SELECT MIN(X.ROWID)

FROM EMP X

WHERE X.EMP_NO = E.EMP_NO);

11.用TRUNCATE替代DELETE

当删除表中的记录时,在通常情况下, 回滚段(rollback

segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)

而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短.

12.尽量多使用COMMIT

只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:

COMMIT所释放的资源:

a. 回滚段上用于恢复数据的信息.

b. 被程序语句获得的锁

c. redo log buffer 中的空间

d. ORACLE为管理上述3种资源中的内部花费

说明: 在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼

13.用Where子句替换HAVING子句

避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.

例如:

低效:

SELECT REGION,AVG(LOG_SIZE)

FROM LOCATION

GROUP BY REGION

HAV ING REGION REGION != …SYDNEY?

AND REGION != …PERTH?

高效

SELECT REGION,AVG(LOG_SIZE)

FROM LOCATION

WHERE REGION REGION != …SYDNEY?

AND REGION != …PERTH?

GROUP BY REGION

HAVING 中的条件一般用于对一些集合函数的比较,如

COUNT() 等等. 除此而外,一般的条件应该写在WHERE子句中14.减少对表的查询

在含有子查询的SQL语句中,要特别注意减少对表的查询.

例如:

低效

SELECT TAB_NAME

FROM TABLES

WHERE TAB_NAME = ( SELECT TAB_NAME

FROM TAB_COLUMNS

WHERE VERSION = 604)

AND DB_VER= ( SELECT DB_VER

FROM TAB_COLUMNS

WHERE VERSION = 604)高效

SELECT TAB_NAME

FROM TABLES

WHERE (TAB_NAME,DB_VER)

= ( SELECT TAB_NAME,DB_VER)

FROM TAB_COLUMNS

WHERE VERSION = 604)

Update 多个Column 例子:

低效:

UPDATE EMP

SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES),

SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES)

WHERE EMP_DEPT = 0020;

高效:

UPDATE EMP

SET (EMP_CAT, SAL_RANGE)

= (SELECT MAX(CATEGORY) , MAX(SAL_RANGE)

FROM EMP_CATEGORIES)

WHERE EMP_DEPT = 0020;

15.通过内部函数提高SQL效率.

SELECT

H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC,COUNT(*)

FROM HISTORY_TYPE T,EMP E,EMP_HISTORY H

WHERE H.EMPNO = E.EMPNO

AND H.HIST_TYPE = T.HIST_TYPE

GROUP BY

H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC;

通过调用下面的函数可以提高效率.

FUNCTION LOOKUP_HIST_TYPE(TYP IN NUMBER) RETURN VARCHAR2

AS

TDESC VARCHAR2(30);

CURSOR C1 IS

SELECT TYPE_DESC

FROM HISTORY_TYPE

WHERE HIST_TYPE = TYP;

BEGIN

OPEN C1;

FETCH C1 INTO TDESC;

CLOSE C1;

RETURN (NVL(TDESC,???));

END;

FUNCTION LOOKUP_EMP(EMP IN NUMBER) RETURN VARCHAR2

AS

ENAME VARCHAR2(30);

CURSOR C1 IS

SELECT ENAME

FROM EMP

WHERE EMPNO=EMP;

BEGIN

OPEN C1;

FETCH C1 INTO ENAME;

CLOSE C1;

RETURN (NVL(ENAME,???));

END;

SELECT H.EMPNO,LOOKUP_EMP(H.EMPNO),

H.HIST_TYPE,LOOKUP_HIST_TYPE(H.HIST_TYPE),COUNT (*)

FROM EMP_HISTORY H

GROUP BY H.EMPNO , H.HIST_TYPE;

16.使用表的别名(Alias)

当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.

17.用EXISTS替代IN

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率.

低效:

SELECT *

FROM EMP (基础表)

WHERE EMPNO > 0

AND DEPTNO IN (SELECT DEPTNO

FROM DEPT

WHERE LOC = …MELB?)

高效:

SELECT *

FROM EMP (基础表)

WHERE EMPNO > 0

AND EXISTS (SELECT …X?

FROM DEPT

WHERE DEPT.DEPTNO = EMP.DEPTNO

AND LOC = …MELB?)

绑定

18.用NOT EXISTS替代NOT IN

在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.

例如:

SELECT …

FROM EMP

WHERE DEPT_NO NOT IN (SELECT DEPT_NO

FROM DEPT

WHERE DEPT_CAT=…A?);

为了提高效率.改写为:

(方法一: 高效)

SELECT ….

FROM EMP A,DEPT B

WHERE A.DEPT_NO = B.DEPT(+)

AND B.DEPT_NO IS NULL

AND B.DEPT_CAT(+) = …A?

(方法二: 最高效)

SELECT ….

FROM EMP E

WHERE NOT EXISTS (SELEC T …X?

FROM DEPT D

WHERE D.DEPT_NO = E.DEPT_NO

AND DEPT_CAT = …A?);

19.用表连接替换EXISTS

通常来说 , 采用表连接的方式比EXISTS更有效率 SELECT ENAME

FROM EMP E

WHERE EXISTS (SELECT …X?

FROM DEPT

WHERE DEPT_NO = E.DEPT_NO

AND DEPT_CAT = …A?);

(更高效)

SELECT ENAME

FROM DEPT D,EMP E

WHERE E.DEPT_NO = D.DEPT_NO

AND DEPT_CAT = …A? ;

在RBO的情况下,前者的执行路径包括FILTER,后者使用NESTED LOOP

20.用EXISTS替换DISTINCT

当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换

例如:

SELECT DISTINCT DEPT_NO,DEPT_NAME

FROM DEPT D,EMP E

WHERE D.DEPT_NO = E.DEPT_NO

高效:

SELECT DEPT_NO,DEPT_NAME

FROM DEPT D

WHERE EXISTS ( SELECT …X?

FROM EMP E

WHERE E.DEPT_NO = D.DEPT_NO);

EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.

21.识别?低效执行?的SQL语句

22.使用TKPROF工具来状态查询SQL性能

23.用EXPLAIN PLAN 分析SQL语句

24.用索引提高效率

25.索引的操作

ORACLE对索引有两种访问模式.

索引唯一扫描 ( INDEX UNIQUE SCAN)

大多数情况下, 优化器通过WHERE子句访问INDEX.

表LODGING有两个索引 : 建立在LODGING列上的唯一性索引LODGING_PK和建立在MANAGER列上的非唯一性索引

LODGING$MANAGER.

SELECT *

FROM LODGING

WHERE LODGING = …ROSE HILL?;

在内部 , 上述SQL将被分成两步执行, 首先 , LODGING_PK 索引将通过索引唯一扫描的方式被访问 , 获得相对应的ROWID, 通过ROWID访问表的方式执行下一步检索.

如果被检索返回的列包括在INDEX列中,ORACLE将不执行第二步的处理(通过ROWID访问表). 因为检索数据保存在索引中, 单单访问索引就可以完全满足查询结果.

下面SQL只需要INDEX UNIQUE SCAN 操作.

SELECT LODGING

FROM LODGING

WHERE LODGING = …ROSE HILL?;

索引范围查询(INDEX RANGE SCAN)

适用于两种情况:

在程序开发中怎样写SQL语句可以提高数据库的性能

1、首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个10万条记录的表中查1条记录,那查询优化器会选 择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用“全表扫描”方式。 可见,执行计划并不是固定的,它是“个性化的”。产生一个正确 的“执行计划”有两点很重要: (1) SQL语句是否清晰地告诉查询优化器它想干什么? (2) 查询优化器得到的数据库统计信息是否是最新的、正确的? 2、统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。 select * from dual Select * From dual 其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行! 3、不要把SQL语句写得太复杂 我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。 一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。 另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,

sql语句(mysql优化)绝对经典

sql语句(mysql优化)绝对经典 误区1:count(1)和count(primary_key) 优于count(*) 很多人为了统计记录条数,就使用count(1) 和count(primary_key) 而不是count(*) ,他们认为这样性能更好,其实这是一个误区。对于有些场景,这样做可能性能会更差,应为数据库对count(*) 计数操作做了一些特别的优化。 误区2:count(column) 和count(*) 是一样的 这个误区甚至在很多的资深工程师或者是DBA 中都普遍存在,很多人都会认为这是理所当然的。实际上,count(column) 和count(*) 是一个完全不一样的操作,所代表的意义也完全不一样。count(column) 是表示结果集中有多少个column字段不为空的记录,count(*) 是表示整个结果集有多少条记录 误区3:select a,b from … 比select a,b,c from …可以让数据库访问更少的数据量 这个误区主要存在于大量的开发人员中,主要原因是对数据库的存储原理不是太了解。实际上,大多数关系型数据库都是按照行(row)的方式存储,而数据存取操作都是以一个固定大小的IO单元(被称作block 或者page)为单位,一般为4KB,8KB… 大多数时候,每个IO单元中存储了多行,每行都是存储了该行的所有字段(lob等特殊类型字段除外)。 所以,我们是取一个字段还是多个字段,实际上数据库在表中需要访问的数据量其实是一样的。当然,也有例外情况,那就是我们的这个查询在索引中就可以完成,也就是说当只取a,b两个字段的时候,不需要回表,而c这个字段不在使用的索引中,需要回表取得其数据。在这样的情况下,二者的IO量会有较大差异。(覆盖索引) 误区4:order by 一定需要排序操作 我们知道索引数据实际上是有序的,如果我们的需要的数据和某个索引的顺序一致,而且我们的查询又通过这个索引来执行,那么数据库一般会省略排序操作,而直接将数据返回,因为数据库知道数据已经满足我们的排序需求了。实际上,利用索引来优化有排序需求的SQL,是一个非常重要的优化手段。延伸阅读:MySQL ORDER BY 的实现分析,MySQL 中GROUP BY 基本实现原理以及MySQL DISTINCT 的基本实现原理。(order by null)

如何优化sql语句

如何优化sql语句.txt心态决定状态,心胸决定格局,眼界决定境界。当你的眼泪忍不住要流出来的时候,睁大眼睛,千万别眨眼,你会看到世界由清晰到模糊的全过程。2010-01-18 honglove (高级程序员) 1、查询时不返回不需要的行、列 业务代码要根据实际情况尽量减少对表的访问行数,最小化结果集,在查询时,不要过多地使用通配符如:select * from table1语句,要用到几列就选择几列,如:select col1,col2 from table1;在可能的情况下尽量限制结果集行数如:select top 100 col1,col2,col3 from talbe2,因为某些情况下用户是不需要那么多的数据的。 2、合理使用EXISTS, NOT EXISTS字句 如下所示: SELECT SUM(T1.C1) FROM T1 WHERE ((SELECT COUNT(*) FROM T2 WHERE T2.C2=T1.C2)>0) SELECT SUM(T1.C1) FROM T1 WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2) 两种产生相同的结果,但是后者的效率显然要高过于前者。银行后者不会产生大量锁定的表扫描或是索引扫描。 经常需要些一个T_SQLL语句比较一个父结果集和子结果集,从而找到是否存在在父结果集中有而在子结果集中乜嘢的记录,如: SELECT _a.hdr_key FROM hdr_tb1 a -----------tb1 a 表示tb1用别名a代替 WHERE NOT EXISTS (SELECT * FROM dt1_tb1 b WHERE a.hdr_key = b.hdr_key) SELECT _a.hdr_key FROM hdr_tb1 a -----------tb1 a 表示tb1用别名a代替 LEFT JION dt1_tb1 b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL SELECT hdr_key FROM hdr_tb1

2020年(Oracle管理)如何优化SQL语句以提高Oracle执行效率

(Oracle管理)如何优化SQL语句以提高Oracle执 行效率

(1)选择最有效率的表名顺序(只在基于规则的优化器中有效): Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表drivingtable)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询,那就需要选择交叉表(intersectiontable)作为基础表,交叉表是指那个被其他表所引用的表。 (2)WHERE子句中的连接顺序: Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。(3)SELECT子句中避免使用‘*’: Oracle在解析的过程中,会将‘*’依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。 (4)减少访问数据库的次数: Oracle在内部执行了许多工作:解析SQL语句,估算索引的利用率,绑定变量,读数据块等。(5)在SQL*Plus,SQL*Forms和Pro*C中重新设置ARRAYSIZE参数,可以增加每次数据库访问的检索数据量,建议值为200。 (6)使用DECODE函数来减少处理时间: 使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。 (7)整合简单,无关联的数据库访问: 如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)。 (8)删除重复记录: 最高效的删除重复记录方法(因为使用了ROWID)例子:DELETEFROMEMPEWHEREE.ROWID>(SELECTMIN(X.ROWID)

基础:如何编写优化的sql语句

一.SQL的优化器执行分析 在ORACLE RDBMS SERVER软件的内部,对于SQL语句的执行有一个优化器(OPTIMIZER)对SQL语句的执行进行优化。在我们使用后面介绍的工具对SQL的执行路径进行查看的时候,系统显示出来的是由优化器给出的执行路径的解释方案,如果对优化器的解释方案不了解的话,就无法针对出现的问题进行SQL语句的调整。现把ORACLE8提供的优化器的执行解释方案公布如下。 这部分内容的详细解释可以参照oracle的文档。这里给出的是快速参考。实际上,这些操作的含义往往名字上就可以表现出来,不用查手册。 1.如何看SQL解释方案 Execution Plan ---------------------------------------------------------- 1SELECT STATEMENT Optimizer=CHOOSE (Cost=94 Card=1) 2SORT (AGGREGATE) 3COUNT (STOPKEY) 4INDEX (FULL SCAN) OF 'PK_TBI_TM' (UNIQUE) (Cost=94 Car d=27164) (图1) 图1为ORACLE对语句“select count(*) from tbi_tm where rownum<10”给出的一个执行的解释方案,那我们该如何看这个方案呢?我们在看这个执行方案的时候要遵循一个原则“由里到外,由高到低”,同时“由里到外”不能违反“由高到低”的原则。因此上述的语句的执行步骤顺序为:4、3、2;假设存在一个步骤5的话,而且它的层次同3一致,那么,上述语句的执行步骤顺序就会改为:4、3、5、2。在图1中还给出了执行了何种操作(例如:INDEX(FULL SCAN),COUNT (STOPKEY)等,具体的说明在下面进行解释),同时在最后还给出了执

SQL Server优化之SQL语句优化

一切都是为了性能,一切都是为了业务 (2) 二、执行顺序 (3) 三、只返回需要的数据 (4) 四、尽量少做重复的工作 (5) 五、注意临时表和表变量的用 (6) 六、子查询的用法 (7) 七:尽量使用索引 (10) 八:多表连接的连接条件对索引的选择有着重要的意义,所以我们在写连接条件条件的时候需要特别注意。 (15)

一切都是为了性能,一切都是为了业务 一、查询的逻辑执行顺序 (1) FROM left_table (3) join_type JOIN right_table (2) ON join_condition (4) WHERE where_condition (5) GROUP BY group_by_list (6) WITH {cube | rollup} (7) HAVING having_condition (8) SELECT (9) DISTINCT (11) top_specification select_list (9) ORDER BY order_by_list 标准的SQL 的解析顺序为: (1) FROM 子句组装来自不同数据源的数据 (2) WHERE 子句基于指定的条件对记录进行筛选 (3) GROUP BY 子句将数据划分为多个分组 (4) 使用聚合函数进行计算 (5) 使用HAVING子句筛选分组

(6) 计算所有的表达式 (7) 使用ORDER BY对结果集进行排序 二、执行顺序 1. FROM:对FROM子句中前两个表执行笛卡尔积生成虚拟表vt1 2. ON: 对vt1表应用ON筛选器只有满足join_condition 为真的行才被插入vt2 3. OUTER(join):如果指定了OUTER JOIN保留表(preserved table)中未找到的行将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束。 4. WHERE:对vt3应用WHERE 筛选器只有使where_condition 为true的行才被插入vt4 5. GROUP BY:按GROUP BY子句中的列列表对vt4中的行分组生成vt5 6. CUBE|ROLLUP:把超组(supergroups)插入vt6,生成vt6 7. HAVING:对vt6应用HAVING筛选器只有使having_condition 为true的组才插入vt7 8. SELECT:处理select列表产生vt8 9. DISTINCT:将重复的行从vt8中去除产生vt9 10. ORDER BY:将vt9的行按order by子句中的列列表排序生成一个游标vc10

优化 SQL SELECT 语句性能的 6 个简单技巧

SELECT语句的性能调优有时是一个非常耗时的任务,在我看来它遵循帕累托原则。20%的努力很可能会给你带来80%的性能提升,而为了获得另外20%的性能提升你可能需要花费80%的时间。除非你在金星工作,那里的每一天都等于地球上的243天,否则交付期限很有可能使你没有足够的时间来调优SQL查询。 根据我多年编写和运行SQL语句的经验,我开始开发一个检查列表,当我试图提高查询性能时供我参考。在进行查询计划和阅读我使用的数据库文档之前,我会参考其中的内容,数据库文档有时会很复杂。我的检查列表绝对说不上全面或科学,它更像是一个保守计算,但我可以说,遵循这些简单的步骤大部分时间我确实能得到性能提升。检查列表如下。 检查索引 在SQL语句的WHERE和JOIN部分中用到的所有字段上,都应该加上索引。进行这个3分钟SQL性能测试。不管你的成绩如何,一定要阅读那些带有信息的结果。 限制工作数据集的大小 检查那些SELECT语句中用到的表,看看你是否可以应用WHERE子句进行过滤。一个典型的例子是,当表中只有几千行记录时,一个查询能够很好地执行。但随着应用程序的成长,查询慢了下来。解决方案或许非常简单,限制查询来查看当前月的数据即可。 当你的查询语句带有子查询时,注意在子查询的内部语句上使用过滤,而不是在外部语句上。 只选择你需要的字段 额外的字段通常会增加返回数据的纹理,从而导致更多的数据被返回到SQL客户端。另外: •使用带有报告和分析功能的应用程序时,有时报告性能低是因为报告工具必须对收到的、带有详细形式的数据做聚合操作。 •偶尔查询也可能运行地足够快,但你的问题可能是一个网络相关的问题,因为大量的详细数据通过网络发送到报告服务器。 •当使用一个面向列的DBMS时,只有你选择的列会从磁盘读取。在你的查询中包含的列越少,IO开销就越小。 移除不必要的表 移除不必要的表的原因,和移除查询语句中不需要的字段的原因一致。 编写SQL语句是一个过程,通常需要大量编写和测试SQL语句的迭代过程。在开发过程中,你可能将表添加到查询中,而这对于SQL代码返回的数据可能不会有任何影响。一旦SQL运行正确,我发现许多人不会回顾他们的脚本,不会删除那些对最终的返回数据没有任何影响和作用的表。通过移除与那些不必要表的JOINS操作,你减少了大量数据库必须执行的流程。有时,就像移除列一样,你会发现你减少的数据又通过数据库返回来了。 移除外部连接查询 这说起来容易做起来难,它取决于改变表的内容有多大的影响。一个解决办法是通过在两个表的行中放置占位符来删除OUTER JOINS操作。假设你有以下的表,它们通过定义OUTER JOINS来确保返回所有的数据: customer_idcustomer_name 1John Doe 2Mary Jane 3Peter Pan 4Joe Soap

SQL语句编写与优化规范

SQL语句编写与优化规范 1用SELECT查询用具体字段代替“*”,且尽可能只查询需要的字段。 SELECT * FROM DEMO_TABLE; SELECT FIELD1,FILED2 FROM DEMO_TABLE; 2多表查询时,使用表的别名,就可以减少解析的时间并减少那些由列名歧义引起的语法错误 SELECT FIELD1,FILED2 FROMDEMO_TABLE1,DEMO_TABLE2 WHERE T1_ID=T2_ID; SELECT t1.T1_ID=t2.T2_ID; 3用EXISTS替代IN,用NOT EXISTS替代NOT IN SELECT * FROM EMP ( FROM DEPT WHERE LOC = 'MELB'); SELECT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 'MELB') 4WHERE条件连接顺序,把表关系写在最前 例如Oracle采用自下而上的顺序解析WHERE子句,表之间的条件连接必须写在其他条件之前,把可以过滤掉大量数据的条件写在WHERE子句的最后,按照过滤记录数量的多少 SELECT * FROM A a, B b WHERE a.num>3000 and b.state=2 AND a.ID=b.ID; SELECT * FROM A a, B b WHERE a.ID=b.ID and b.state=2and a.num>3000 5删除全表时,用TRUNCATE替代DELETE 当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.

基于索引的SQL语句优化

基于索引的SQL语句优化 一、尽量避免非操作符的使用 通常情况下,为了对指定列建立特定的条件,需要在WHERE子句中使用诸如NOT、!=、<>、!<、!>等操作符,在索引列上使用这些非操作符,DBMS是不使用索引的,可以将查询语句转换为可以使用索引的查询。例: SELECT * FROM ORDERS WHERE ORDERDATE<>1997-l2 转化为:SELECT * FROM ORDERS WHERE ORDERDATE l998-l-l 这样DBMS就能利用索引字段ORDERDATE,大大提高查询效率。 二、避免困难的正规表达式 MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。 例如:SELECT * FROM STUDENT WHERE STUDENT_NUM LIKE “98_ _” 即使在STUDENT_NUM字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT * FROM STUDENT WHERE STUDENT_NUM >”98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。如果一定要使用通配符也要避免通配符在搜索字段的首部出现,这种情况下DBMS的优化器不会使用索引[6]。 三、避免在索引列上使用NULL关键字 避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引。即使索引有多列,只要这些列中有一列含有NULL,该列就会从索引中排除,也就是说如果某列存在空值,即使对该列建索引也不会提高性能[7]。 任何在WHERE子句中使用IS NULL或IS NOT NULL的语句,优化器是不允许使用索引的。 四、避免对查询的列使用数学运算 如果在查询列使用数学运算,则DBMS优化器先要处理数学运算也会影响查询效能。例如: (1)SELECT * FROM ORDERDETAILS WHERE QUANTITY*2<50 (2)SELECT * FROM ORDERDETAILS WHERE QUANTITY<25 虽然这两条查询的结果完全相同,但某些情况下第二个语句的执行效率远高于第一个,因此在查询前应将数学运算转化。

SQL语句大批量多表查询优化解决方案

SQL语句大批量多表查询优化方案 我写这个没什么目的,只是分享一下给大家。 此为自己项目当中所碰见的。 当时也很纠结。但是优化过后。经过测试二亿条数据多表查询,在一分钟以内出来,虽然不是很快。但也尽量了。 首先,数据库表中索引如何创建我想大家都知道。 这是百度当中找到的解释已经很详细了。 聚集索引: 聚集索引基于聚集索引键按顺序排序和存储表或视图中的数据行。聚集索引按 B 树索引结构实现,B 树索引结构支持基于聚集索引键值对行进行快速检索。 非聚集索引: 既可以使用聚集索引来为表或视图定义非聚集索引,也可以根据堆来定义非聚集索引。非聚集索引中的每个索引行都包含非聚集键值和行定位符。此定位符指向聚集索引或堆中包含该键值的数据行。索引中的行按索引键值的顺序存储,但是不保证数据行按任何特定顺序存储,除非对表创建聚集索引。 唯一索引: 唯一索引确保索引键不包含重复的值,因此,表或视图中的每一行在某种程度上是唯一的。 聚集索引和非聚集索引都可以是唯一索引。 包含性列索引: 一种非聚集索引,它扩展后不仅包含键列,还包含非键列。 索引视图: 视图的索引将具体化(执行)视图,并将结果集永久存储在唯一的聚集索引中,而且其存储方法与带聚集索引的表的存储方法相同。创建聚集索引后,可以为视图添加非聚集索引。 全文索引: 一种特殊类型的基于标记的功能性索引,由 Microsoft SQL Server 全文引擎(MSFTESQL) 服务创建和维护。用于帮助在字符串数据中搜索复杂的词。 至于语法之类的就不讲解,大家百度一下就有很多。综合在表当中建立索引是靠

大家自己,如何安排才会觉得合理。在此不做建议。 第一部开始。 创建临时虚拟表。也就是用其实就是把一大堆重复用到的SQL语句放在with as 里面,取一个别名,后面的查询就可以用它 这样对于大批量的SQL语句起到一个优化的作用,而且清楚明了 具体实例 WITH BASE AS ( SELECT * FROM MDM_DISTRIBUTOR ) SELECT * FROM BASE 这只是举例一下,在实际情况中,其实就是把一大堆重复用到的SQL语句放在with as 里面,取一个别名,后面的查询就可以用它这样对于大批量的SQL语句起到一个优化的作用,而且清楚明了 为什么要用WITH ,用with好处就是把把复杂的SQL语句全部都放到这里。把他当作一张表,进行查询。 第二部,创建临时表 语法 --创建临时表 SELECT * INTO #TEMP_REPORT_TABLE FROM BASE --删除临时表,最好判断一下是否为空,在进行删除 IF object_id('tempdb..#TEMP_REPORT_TABLE') IS NOT NULL BEGIN DROP TABLE #TEMP_REPORT_TABLE END 最终优化的就是

sql语句优化工具LECCO SQL Expert

sql语句优化工具LECCO SQL Expert 2007-12-17 14:16 软件讲明: 所谓SQL,确实是指Structured Query Language(结构化查询语言),它是目前使用最广泛的数据库语言,用来和数据库打交道,从数据库中得到用户需要的数据。然而要想熟练使用SQL语句,也不是一件简单的事,有些语句使用起来也比较苦恼。如果我们对SQL语句进行优化,那么用户使用起来就会方便许多。 简单来讲,SQL语句的优化确实是将性能低下的SQL 语句转换成达到同样目的的性能优异的SQL语句。人工智能自动SQL优化确实是使用人工智能技术,自动对SQL语句进行重写,找到性能最好的等效SQL语句。 人工智能自动SQL 优化随着人工智能技术的进展和在数据库优化领域应用的深入,在20世纪90年代末终于显现了突破性的进展——人工智能自动SQL优化。目前在商用数据库领域LECCO TechnologyLi mited(灵高公司)拥有该技术并提供使用该技术的自动优化产品——LECCO SQL Expert,其支持Oracle、Sybase、MS SQLServer和IBMDB2数据库平台。该产品针对数据库应用的开发和爱护时期提供了几个专门的模块:S QL语法优化器、PL/SQL集成化开发调试环境(IDE)、扫描器、数据库监视器等。图1 人工智能自动SQL优化示意图其核心模块之一“SQL语法优化器”的工作原理大致如下 一条源SQL语句输入→“人工智能反馈式搜索引擎”对输入的S QL语句结合检测到的数据库结构和索引进行重写,产生N条等效的SQL 语句输出→产生的N条等效SQL语句再送入“人工智能反馈式搜索引擎”进行重写,直至无法产生新的输出或搜索限额满→对输出的SQL语句进行过滤,选出具有不同执行打算的SQL语句(即不同的执行效率)→对得到的S QL语句进行批量测试,找出性能最好的SQL语句。图2 优化前的SQL语句自动优化实例假设我们从源代码中抽取出这条SQL语句

Sql优化or语句

如何优化带or条件的sql ----------本文章转自网络,互相学习,互相帮助 以下为转帖内容: ======================================================================================== ======== 今天在论坛上看到了一个帖子,问题如下: select * from cc where ((a1 ='ffff' and z1='mmmm') or (b1='sss' and z2='nnnn')) and c1 ='ggggg' 其中表有30万行数据,返回的数据10行左右,怎样创建index访问最快。 按照别人的说法测试了一下,步骤如下: create table CC ( A1 VARCHAR2(5), Z1 VARCHAR2(5), B1 VARCHAR2(5), Z2 VARCHAR2(5), C1 VARCHAR2(5) ) insert into cc values('dffd','dfsd','fdf','fdsfs','sfds');--重复插入2097152条,对查询时间可能有影响 SQL> select count(*) from cc; COUNT(*) ---------- 2097160 SQL> set timing on SQL> edit 已写入file afiedt.buf 1 select * from cc 2 where ((a1='ffff'and z1='mmmm') or (b1='sss' and z2='nnnn')) 3* and c1='ggggg'--无索引情况下or查询 SQL> / A1 Z1 B1 Z2 C1 ----- ----- ----- ----- ----- ffff mmmmm sss nnnn ggggg ffff mmmmm sss nnnn ggggg ffff mmmmm sss nnnn ggggg ffff mmmmm sss nnnn ggggg ffff mmmmm sss nnnn ggggg ffff mmmmm sss nnnn ggggg

如何优化sql语句

1.首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用“全表扫描”方式。 可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要: 1)SQL语句是否清晰地告诉查询优化器它想干什么? 2)查询优化器得到的数据库统计信息是否是最新的、正确的? 2.统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。 select * from dual select * From dual 其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行! 3.不要把SQL语句写得太复杂 我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。 一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。 另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。 4.使用“临时表”暂存中间结果 简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。

SQL语句优化方法

1. 选择最有效率的表名顺序, FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.汗颜!!以前以为dimensional table,都是多条记录呢,怪不得以前写的查询速度这么慢。 2. Where子句中的连接顺序.: 数据库采用自下而上的顺序解析Where子句,根据这个原理,表之间的连接必须写在其他Where条件之前, 那些可以过滤掉最大数量记录的条件必须写在Where子句的末尾.HAVING 最后。这个貌似一直这么写的,不过那是在SQLSERVER里面的,前面都是用的JOIN 3. 整合简单,无关联的数据库访问: 如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系),这个我没有体会,貌似都是按照业务逻辑把它们分成了一小块一小块的呢 4. 尽量缩小子查询的结果。 5. 用EXISTS替代IN、用NOT EXISTS替代NOT IN。貌似我做项目的时候只在少数基于条件的表连接才会用EXISTS,基本不用IN 和NOT IN。 6. 避免在索引列上使用计算. Where子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描. 7,用>=替代> 这个我也不是特别明白,>是IS NOT? 8,用UNION替换OR (适用于索引列) 通常情况下, 用UNION替换Where子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引.这个在项目中我是有遇到过的,我写了个临时表的函数,其他的SQL需要和临时表连接起来,因为业务逻辑比较复杂,连接的时候速度很慢,后来把OR都改成了UNION ALL 9,避免在索引列上使用IS NULL和IS NOT NULL 10,避免改变索引列的类型 11. 需要当心的Where子句: 某些Select 语句中的Where子句不使用索引. 这里有一些例子. 在下面的例子里, (1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) ‘||'是字符连接函数. 就象其他函数那样, 停用了索引. (3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描.

索引SQL语句优化★★★

标题 : 基于索引的SQL语句优化之降龙十八掌 第一掌避免对列的操作 3 第二掌避免不必要的类型转换 4 第三掌增加查询的范围限制 4 第四掌尽量去掉"IN"、"OR" 4 第五掌尽量去掉 "<>" 5 第六掌去掉Where子句中的IS NULL和IS NOT NULL 5 第七掌索引提高数据分布不均匀时查询效率 5 第八掌利用HINT强制指定索引 6 第九掌屏蔽无用索引 6 第十掌分解复杂查询,用常量代替变量 7 第十一掌 like子句尽量前端匹配 7 第十二掌用Case语句合并多重扫描 7 第十三掌使用nls_date_format 8 第十四掌使用基于函数的索引 8 第十五掌基于函数的索引要求等式匹配 9 第十六掌使用分区索引 9 第十七掌使用位图索引 9 第十八掌决定使用全表扫描还是使用索引 9 1 前言 客服业务受到SQL语句的影响非常大,在规模比较大的局点,往往因为一个小的SQL语句不够优化,导致数据库性能急剧下降,小型机idle所剩无几,应用服务器断连、超时,严重影响业务的正常运行。因此,称低效的SQL语句为客服业务的‘恶龙’并不过分。数据库的优化方法有很多种,在应用层来说,主要是基于索引的优化。本次秘笈根据实际的工作经验,在研发原来已有的方法的基础上,进行了一些扩充,总结了基于索引的SQL语句优化的降龙十八掌,希望有一天你能用其中一掌来驯服客服业务中横行的‘恶龙’。 2 总纲 l 建立必要的索引 这次传授的降龙十八掌,总纲只有一句话:建立必要的索引,这就是后面降龙十八掌的内功基础。这一点看似容易实际却很难。难就难在如何判断哪些索引是必要的,哪些又是不必要的。判断的最终标准是看这些索引是否对我们的数据库性能有所帮助。具体到方法上,就必须熟悉数据库应用程序中的所有SQL语句,从中统计出常用的可能对性能有影响的部分SQL,分析、归纳出作为Where条件子句的字段及其组合方式;在这一基础上可以初步判断出哪些表的哪些字段应该建立索引。其次,必须熟悉应用程序。必须了解哪些表是数据操作频繁的表;哪些表经常与其他表进行连接;哪些表中的数据量可能很大;对于数据量大的表,其中各个字段的数据分布情况如何;等等。对于满足以上条件的这些表,必须重点关注,因为在这些表上的索引,将对SQL语句的性能产生举足轻重的影响。不过下面还是总结了一下降龙十八掌内功的入门基础,建立索引常用的规则如下: 1、表的主键、外键必须有索引; 2、数据量超过300的表应该有索引; 3、经常与其他表进行连接的表,在连接字段上应该建立索引;

高性能SQL优化总结

SQL 高性能查询优化语句,一些经验总结 1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null; 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num = 0; 2.应尽量避免在 where 子句中使用!=或$amp; 3.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20; 可以这样查询: select id from t where num=10 union all select id from t where num=20; 4.in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据。如: select id from t where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3; 5.尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。 见如下例子: SELECT * FROM T1 WHERE NAME LIKE ‘%L%’; SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’; SELECT * FROM T1 WHERE NAME LIKE ‘L%’; --第三个查询能够使用索引来加快操作 即使NAME字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。而第三个查询能够使用索引来加快操作。 6.必要时强制查询优化器使用某个索引,如在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描: select id from t where num=@num; 可以改为强制查询使用索引:

数据库性能优化之SQL语句优化

数据库性能优化之SQL语句优化一、问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。 在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引,这有助于写出高性能的SQL语句。 二、SQL语句编写注意问题 下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低。

1. 操作符优化 (a) IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别: ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。 推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。 (b) NOT IN操作符 此操作是强列不推荐使用的,因为它不能应用表的索引。 推荐方案:用NOT EXISTS 方案代替 (c) IS NULL 或IS NOT NULL操作(判断字段是否为空) 判断字段是否为空一般是不会应用索引的,因为索引是不索引空值的。不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是

sql语句优化原则

SQL语句优化原则 数据库性能是整个应用程序性能的重要部分。数据库优化涉及的内容非常广泛,各类数据库都提供众多的性能指标和大量的优化工具。 下面我们简单介绍一下优化的基本概念。 一个运行良好的数据库至少应具有以下特点: 合理的物理结构及硬件能力 合理的物理结构指数据库文件及整个网络的物理分布。硬件能力指是否有足够的硬件资源来完成应用程序功能。合理的物理结构至少带来两个方面的好处: 1、适量的数据冗余,提高数据安全性。 2、平衡磁盘IO,增强数据读写能力。 而足够的硬件能力的作用自然不言而喻。一旦建立好数据库系统并开始运行,数据库的物理结构就不能改变。 合理的系统参数 对应数据库来说,随着数据量的变化,数据库性能也一直处在变化之中,因此数据库建立之初设定的系统参数会变的越来越不合适,有时甚至阻碍了数据库的正常运行,导致性能瓶颈。因此观察性能变化,随时调整系统参数,使数据库一直处于一个良好的运行状态,就成为管理员最重要的日常工作之一。对系统参数的合理调整,常常能将数据库从崩溃的边缘挽救回来。oracle、sqlserver这样的高品质数据库都为系统参数提供了灵活多变的调整方式。一般来说,只要数

据库结构设计不存在重大缺陷,通过后期的调整,都可以使数据库运行在一个良好的状态下。 性能优良的sql语句 sql语句是在程序开发阶段就已经决定了的,由低效率的sql语句给数据库性能带来的问题,往往在数据库开始运行一段时间后才凸现出来(随着数据量的不断增加),但发现后就变的难以改变,成为不可突破的性能瓶颈。因此,作为一名合格的开发人员,应该建立基本的优化概念和良好的编程习惯,从整体上提高应用程序的质量。 同时,提高sql语句的执行效率,是提高整个数据库性能的最立竿见影且价格低廉的方法之一。因为几乎所有的数据库都会不可避免的运行一些效率低下的sql语句。对数据库性能的调整,往往都是从sql语句调优开始的。 下面我们简单介绍数据库是怎么执行sql语句的。 sql语句是唯一从应用程序发送到数据库实例的命令。数据库实例所做的全部工作就是接受、解释和执行sql语句。 在绝大多数情况下,我们并不需要关心sql语句是怎么执行的,这是因为在当前流行的数据库软件中都无一例外的采用了高性能的优化器,而这些优化器在绝大多数的情况下都能将用户某些不合理的sql语句结构转换成更合理的形式,从而有效提高sql的执行效率。 优化器的优化原理有两种:

SQL语句优化建议

SQL语句优化建议(09-12) 第一条 //* ExecutionPlan1.sqlplan 中缺少索引的详细信息 查询处理器估计采用以下索引可以将查询开销减少99.9151%。 */ /* USE [gh60] GO CREATE NONCLUSTERED INDEX [] ON [dbo].[workflow_fileinbox] ([from_id],[isspecial],[issent]) INCLUDE ([id],[flow_id],[user_id],[file_id],[step_id],[branch_id],[isattention],[hurrytimes],[wishdate],[days] ,[startdate],[checkindate],[sentdate],[leaveword],[token]) GO */ 第二条 //* ExecutionPlan1.sqlplan 中缺少索引的详细信息 查询处理器估计采用以下索引可以将查询开销减少50.609%。 */ /* USE [gh60] GO CREATE NONCLUSTERED INDEX [] ON [dbo].[workflow_fileattach] ([file_id]) INCLUDE ([id],[user_id],[outuser_id],[title],[topic_id],[type],[ver],[lastver],[createdate],[startdate],[enddate ],[checkout],[serverfile],[filename],[fileext],[filesize],[descn]) GO */ 第三条 //* ExecutionPlan1.sqlplan 中缺少索引的详细信息 查询处理器估计采用以下索引可以将查询开销减少93.8037%。 */ /* USE [gh60]

相关主题
文本预览
相关文档 最新文档