长沙做网站公司解密如何编写高效率的SQL语句

如何书写高效的SQL语句
 长沙做网站公司在应用开发中,书写SQL语句是最基本的工作,但我们往往在这方面侧重的是功能的实现,很容易把效率问题给忽略了,在随着系统数据的不断增加,可能有些低效的SQL语句会让客户感觉系统反映缓慢,甚至还有可能会因长时间执行不出结果而报超时或其它系统错误,所以我们要养成一个良好的编码习惯,不仅要实现其功能,而且要尽可能的提高效率。
 下面内容是在网络上收集的一些比较典型实用的优化点,以及在工作中用到的典型样例,供大家参考学习。

1、注意UNion和UNion all 的区别。
   它们两都可以把相同结果集并在一起,但UNION all的效率稍好一些,在就是如果A并上B有重复记录,union all可以把重复数据distict掉

2、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的 

3、查询时不要返回不需要的行、列 ,即最好不要用select * from tablename,这样会把所有的字段都解析出来.

4、如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引:
   SELECT   *   FROM   PersonMember   (INDEX   =   IX_Title)   WHERE   processid   IN   (‘男’,‘女’) 

5、在SQL2000以前,一般不要用如下的字句:   "IS   NULL",   " <> ",   "!=",   "!> ",   "! <",   "NOT",   "NOT   EXISTS",   "NOT   IN",   "NOT   LIKE",   and   "LIKE’%500’",因为他们不走索引全是表扫描。也不要在WHere字句中的列名加函数,如Convert,substring等,如果必须用函数的时候,创建计算列再创建索引来替代.还可以变通写法:WHERE   SUBSTRING(firstname,1,1)   =   ’m’改为WHERE   firstname   like  ’m%’(索引扫描),一定要将函数和列名分开。并且索引不能建得太多和太大。NOT   IN会多次扫描表,使用EXISTS、NOT   EXISTS   ,IN   ,   LEFT   OUTER   JOIN   来替代,特别是左连接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同的是IS   NULL,“NOT",   "NOT   EXISTS",   "NOT   IN"能优化她,而” <> ”等还是不能优化,用不到索引。 对于like的高效使用方法 本站有详细的讲解。

6、将需要查询的结果预先计算好放在表中,查询的时候再SELECT。这在SQL7.0以前是最重要的手段。例如医院的住院费计算。 

7、MIN() 和 MAX()能使用到合适的索引 

8、数据库有一个原则是代码离数据越近越好,所以优先选择Default,依次为Rules,Triggers,   Constraint(约束如外健主健CheckUNIQUE……,数据类型的最大长度等等都是约束),Procedure.这样不仅维护工作小,编写程

序质量高,并且执行的速度快。 

 9、如果要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌INsert来插入(不知JAVA是否)。因为这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值.存储

过程就没有这些动作:   方法:Create   procedure   p_insert   as   insert   into   table(Fimage)   values   (@image),   在前台调用这个存储过程传入二进制参数,这样处理速度明显改善。 

10、Between在某些时候比IN速度更快,Between能够更快地根据索引找到范围。用查询优化器可见到差别。   select   *   from   chineseresume   where   title   in   (’男’,’女’)   Select   *   from  

chineseresume   where   between   ’男’   and   ’女’   是一样的。由于in会在比较多次,所以有时会慢些。 

11、在必要是对全局或者局部临时表创建索引,有时能够提高速度,但不是一定会这样,因为索引也耗费大量的资源。他的创建同是实际表一样。 

12、不要建没有作用的事物例如产生报表时,浪费资源。只有在必要使用事物时使用它。  

13、用OR的字句可以分解成多个查询,并且通过UNION   连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNION   all执行的效率更高.多个OR的字句没有用到索引,改写成UNION的形式再试图与索引匹配。一个关键的问题是否用到索引。 

14、对于长沙网站建设开发的来说我们尽量少用视图,因为它的效率低。对视图操作比直接对表操作慢,可以用stored   procedure来代替她。特别的是不要用视图嵌套,嵌套视图增加了寻找原始资料的难度。我们看视图的本质:它是存放在服务器上的被优化好了

的已经产生了查询规划的SQL。对单个表检索数据时,不要使用指向多个表的视图,直接从表检索或者仅仅包含这个表的视图上读,否则增加了不必要的开销,查询受到干扰.为了加快视图的查询,MsSQL增加了视图索引的功能。 

15、没有必要时不要用DISTINCT和ORDER   BY,这些动作可以改在客户端执行。它们增加了额外的开销。这同UNION   和UNION   ALL一样的道理。 

16、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数 

17、当用SELECT   INTO时,它会锁住系统表(sysobjects,sysindexes等等),阻塞其他的连接的存取。创建临时表时用显示申明语句,而不是 select   INTO.   drop   table   t_lxh   begin   tran   select   *  

into   t_lxh   from   chineseresume   where   name   =   ’XYZ’   --commit   在另一个连接中SELECT   *   from   sysobjects可以看到   SELECT   INTO   会锁住系统表,Create   table   也会锁系统表(不管是临时表还是系统表)。所以千万不要在事物内使用它!!!这样的话如果是经常要用的临时表请使用实表,或者临时表变量。
18、一次更新多条记录比分多次更新每次一条快,就是说批处理好 

19、SELECT   COUNT(*)的效率教低,尽量变通他的写法,而EXISTS快.同时请注意区别:   select   count(Field   of   null)   from   Table   和   select   count(Field   of   NOT   null)   from   Table   的返回值是不同的。 

20、当服务器的内存够多时,配制线程数量   =   最大连接数+5,这样能发挥最大的效率;否则使用   配制线程数量 <最大连接数启用SQL   SERVER的线程池来解决,如果还是数量   =   最大连接数+5,严重的损害服务器的性能。 

我觉得主要应该从5个方面进行调整:
1.去掉不必要的大型表的全表扫描
2.缓存小型表的全表扫描
3.检验优化索引的使用
4.检验优化的连接技术
5.尽可能减少执行计划的Cost

现在简单的举几个例子

Where子句中有“!=”将不使用索引
select account_name from test where amount != 0  (不使用)
select account_name from test where amount > 0  (使用)

Where条件中对字段增加处理函数将不使用该列的索引
select * from emp where to_char(hire_date,’yyyymmdd’)=’20080411’ (不使用)
select * from emp where hire_date = to_char(’20080411’,’yyyymmdd’) (使用)

避免在索引列上使用IS NULL和 IS NOT NULL
select * from emp where dept_code is not null  (不使用)
select * from emp where dept_code > 0  (使用)

通配符% 的使用
select * from emp where name like ’%A’  (不使用索引)
select * from emp where name like ’A%’  (使用索引)

最高效的删除重复记录方法 ( 因为使用了ROWID)例子:
DELETE  FROM  EMP E  WHERE  E.ROWID > (SELECT MIN(X.ROWID)
FROM  EMP X  WHERE  X.EMP_NO = E.EMP_NO);

sql语句用大写的;因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行

在java代码中用到preparedStatement的時候尽量少用连接符“+”连接字符串!

1. SELECT子句中避免使用 ‘*’
    当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询

数据字典完成的, 这意味着将耗费更多的时间.

2.选择最有效率的表名顺序(只在基于规则的优化器中有效)
     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

3. 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’;

4. 减少访问数据库的次数
   当执行每条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;
注意:
在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200.

5.使用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子句中.

6 使用表的别名(Alias)
   当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
(译者注: Column歧义指的是由于SQL中不同的表具有相同的Column名,当SQL语句中出现这个Column时,SQL解析器无法判断这个Column的归属)

7. 用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’)
(译者按: 相对来说,用NOT EXISTS替换NOT IN 将更显著地提高效率,下一节中将指出)

8. 用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 (SELECT ‘X’
                    FROM DEPT D
                    WHERE D.DEPT_NO = E.DEPT_NO
                    AND DEPT_CAT = ‘A’);

9. 用表连接替换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’ ;

10.   用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核心模块将在子查询的条件一旦满足后,立刻返回结果.

11. 用外连接代替NOT EXISTS
低效写法:
select count(t.fid)
from tableA t
where not exists
(select t1.fid
          from tableB t1
         where t.fid = t1.fid)
   and t.fdatastatus = ’unrelease’
   and t.fdevicetypeid in
       (select t2.fid from tableC t2 where t2.fcategory = ’保护’);

高效写法:
select count(t.fid)
from tableA t, tableB t1
where t.fid = t1.fid(+)
and t.fdatastatus = ’unrelease’
and t.fdevicetypeid in
     (select t2.fid from tableC t2 where t2.fcategory = ’保护’)
and t1.fid is null;

条件1:tableA表中有181901 ,tableB表中有195条数据;查出满足条件的数据4798
   低效写法用时:2.2874秒
   高效写法用时:0.8814秒

条件2:tableA表中有298870 ,tableB表中有89338条数据;查出满足条件的数据30909
   低效写法用时:半小时执行不出结果(直接费了)
   高效写法用时:6.2964秒

注:通过上面两条SQL语句分析,除法(不包含)用not exists的执行效率在数据量大的情况下也是很低的,我们可以通过左右链接的方法同样能满足这样的需求,且效率上有惊人的变化。转载请注明www.sendawangluo.com
时间: 2024-10-25 16:57:12

长沙做网站公司解密如何编写高效率的SQL语句的相关文章

高效率Oracle SQL语句

最近在JavaEye上发现好多同志对sql的优化好像是知道的很少,最近总结了几条仅供参考,不过除少数可能要依情况而定,大多数还是相当有效的. [注:以下说的(低效)与(高效)都是相当来说的.] 1.Where子句中的连接顺序: ORACLE采用自下而上的顺序解析WHERE子句. 根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. 举例: (低效) select ... from table1 t1 where t1.sal

vb.net如何编写高效率的SQLHelper——(二)代码实战

上一篇博客:<vb.net如何编写高效率的SqlHelper--(一)基础篇> 咱们谈到了很多关系ADO.net的基础知识,那些是看懂本篇文章的前提.所以童鞋们有必要好好看看哦. 本篇选取了最常用的几个方法,而且尽可能的简单化,灵活化(用到了函数重载和读取配置文件) 好了,废话不多说,直接上代码. '************************************************* '作者:刘文彬 '小组: '说明:利用函数重载,配置文件读取使得程序更加灵活 '创建日期:201

MySql如何编写高效的SQL

最近应团队要求,研究整理了下,mysql相关的优化,有些是根据实际java项目中碰到的情况经验之谈.欢迎讨论~ SQL 语言是一种强大而且灵活的语言,在使用 SQL 语言来执行某个关系查询的时候,用户可以写出很多不同的 SQL 语句来获取相同的结果.也就是说,语法不同的SQL语句,有可能在语义上是完全相同的.但是尽管这些 SQL 语句最后都能返回同样的查询结果,它们执行所需要的时间却有可能差别很大. 一.优化目标 减少 IO 次数 IO永远是数据库最容易产生瓶颈的地方,这是由数据库的职责所决定的

如何编写高效的SQL查询语句

概述 如何编写性能比较高的SQL查询语句呢?两个方法:创建合理的索引:书写高效的SQL语句 索引的基本原理 索引分为聚集索引和非聚集索引.一个表只能创建一个聚集索引和N个非聚集索引,这句话的由来主要是由于索引的原理决定的. 数据库中的一张表不论你创建不创建索引,或者,不论你创建那种类型的索引,其在硬盘上的存储是一样的,那么,创建索引和不创建索引,或者,创建聚集索引和非聚集索引的区别在什么地方呢? 其区别是表内数据在内存的存在形式.对于没有创建索引的表,其加载到内存里时,就只有数据块:对于有聚集索

详解Java的MyBatis框架中SQL语句映射部分的编写

这篇文章主要介绍了Java的MyBatis框架中SQL语句映射部分的编写,文中分为resultMap和增删查改实现两个部分来讲解,需要的朋友可以参考下 1.resultMap SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: ? 1 2 3 4 5 6 <mappers>   <mapper resource="com/limi

sql语句代编写、sql 游标 、事务代写

sql语句代编写.sql 游标 .事务代写1. AimsThis project aims to give you practice in? reading and understanding a moderately large relational schema (MyMyUNSW)? implementing SQL queries and views to satisfy requests for information? implementing SQL functions to ai

公司有一台很重要SQL数据库,如何实现数据库实时同步?

一.客户需求 客户现在有一个需求,公司有一台很重要SQL数据库,怕有一天服务器或者系统崩溃,导致所有SQL数据库数据丢失,客户想把数据库数据,通过某种方式将数库进行实时同步到另外一台服务器上,这样可以做个backup. 那客户这个需求如何实现呢? 二.解决方案: 通过分析与研究,使用的是SQL自带的发布与订阅功能,旧的SQL Server版本是2008,新安装一个SQL Server 2014版本,通过旧SQL Serer发布,再通过SQL Server2014订阅,来同步数据库数据. 三.实现

SQL语句编写注意事项

1.SQL编写注意事项 1.1 null 列 null 列使用索引是无意义的,任何包含null 值的列都不会包含在索引中.因此where 语句中的is null 或者 is not null 的语句,导致索引失效. 1.2 concat 或 || concate 或 || 是mysql 和 oracle 的字符串连接操作,如果对列进行函数操作,就会忽略索引的使用,比如下面的查询语句: -- 忽律索引 select ... from .. where first_name || '' || las

snake4444勒索病毒成功处理教程方法工具达康解密金蝶/用友数据库sql后缀snake4444

*snake4444勒索病毒成功处理教程方法 案例:笔者负责一个政务系统的第三方公司的运维,上班后发现服务器的所有文件都打不开了,而且每个文件后面都有一个snake4444的后缀,通过网络我了解到这是一种勒索病毒.因为各个文件不能正常打开,因此整个系统近乎瘫痪,幸运的是我通过朋友介绍找到了达康解密,经过客服耐心的接待让我知道了很多应对方法.在他们了解情况后2小时他们的工程师就赶到了现场,跟我们签了合同后,开始了解密工作,时间不长4小时左右就全部解密完成.所以感谢达康解密,成功替我保住了工作.他们