1.join原理:

  select t1.UserName,t2.Title,t3.Content

    from user t1,user_message t2,message_content t3

    where t1.pkid=10001

    and t1.pkid=t2.userId

   and  t2.pkid=te.messageId;

 MySQL中,只有一种JOIN算法,Nested Loop Join .用第一个表的结果集 作为循环基础数据,作为 过滤条件到下一个表中查询,最后合并结果,再将前两个表中数据作为循环基础条件,到第三个表中查询数据。

  优化:尽量减少循环次数。有效的方法:使结果集尽可能小,永远用小结果集驱动大结果集。

          优先优化内层循环。

         保证Join语句中被驱动表的Join条件字段被索引且内存充足。

  Oracle中有三种:

  Nested Loop join:

  Outer table中第一行与inner table中的相应记录join,类似一个嵌套的循环。

  Sort merge join:

  将两个表排序,然后再进行join.

  Hash join:

 将两个表中较小的一个在内存中构建一个Hash表(对Join Key),扫描另一个表,同样对Join Key 进行Hash后 探测是否可以join,找出与之匹配的行。

 一张小表被hash在内存中,因数据量小,大多数数据已驻入内存,剩下少量在临时表空间。

每读取一条大表记录,和小表内存中数据比较,符合就输出,如果与小表临时空间数据符合,则不直接输出,而也是被存储临时表空间中。读取完毕,再将临时表空间的输出。

并行环境下:每读取一条大表记录,和内存中小表数据比较,符合先做join,而不直接输出。

       直到大表读取完,如果内存够,join好的数据保存在内存中,否则,就在临时表空间。

 适用范围:

  Nested loop join:outer table记录集较少,inner table(被驱动)索引选择性较好。

 Sorted merge join:数据没有索引但已排序。效率最差。

 Hash join:两个表数据量差别很大。效率最高,因为只要对两张表扫描一次,消耗CPU

2.索引:

    相当于图书的目录。

   加速表与表的链接,加快数据的检索速度。

  唯一性索引,保证每一行数据的唯一性。

 三种:唯一索引,主键索引,聚集索引

唯一索引:不允许其中任两行索引值相同。 ( 行)

    如在emplyee表中职员的姓上创建唯一索引。

主键索引:一列或列组合,其值唯一标识表中的每一行。该列称主键。

     是唯一索引的特定类型。

SQL Server中提供聚集索引,非聚集索引。

聚集索引:键值中的逻辑顺序决定表中相应行的物理顺序。电话簿

注意事项:使用的列越少越好。包含大量非重复值的列

          使between,>,>=等运算符返回一个范围值的查询

        被连续访问的列,返回大型结果集的查询

       经常被使用联接或group by子句查询的列。

      不适合频繁更改的列,宽键。

非聚集索引: 数据存储在一个地方,索引存储在另一个地方

     索引带有指针指向存储位置。

如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。  

  列: 出货单 ,日期date 建立一个聚集索引 year

      为2013年的范围, year=2013,  2014年范围 year=2014,

     

3.SQL优化:

  1.  is null 与is not null

   不能用null作索引。

  2.联接列

   有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。

 下面是一个采用联接查询的SQL语句,

    select * from employss where first_name||''||last_name ='Beill Cliton';

    上面这条语句完全可以查询出是否有Bill Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。

  当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。

    where first_name ='Beill' and last_name ='Cliton';

  3.带通配符(%)的like语句

   select * from employee where last_name like '%cliton%';

 由于通配符在搜寻词首出现,所以Oracle不使用last_name的索引。然而当通配符出现在其他位置时,优化器就能利用索引。

  select * from emplyee where last_name like 'c%';

4.Order by语句

 order by语句决定Oracle如何将返回的查询结果排序。对要排序的列无限制,也可将函数加入列中。

 任何在Order by语句中的非索引项或有计算表达式都将降低查询速度。

 解决办法 :重写order by以使用索引,也可以为所作用的列建立另外一个索引,绝对避免在Order by子句中使用表达式。

5.NOT

 where status <>'INVALID';

可以改为不使用NOT

 select * from employee where salary<3000 or salary>3000;

第二种方案更快,因为查询允许Oracle对salary列使用索引,而第一种查询不能使用索引。

 

1.选择最有效率的表名顺序,Oracle从右到左的顺序处理FROM子句中的表名,最后 一个表(基础表),必须选择记录条数最少的表。

 如果有3个以上的表连接查询,就将交叉表作为基础表,交叉表指被其他表所引用的表。

2.where子句中的连接顺序

  Oracle采用自下而上的顺序解析where 子句,表之间的连接必须写在其他where 条件之前

可以过滤掉最大数量记录的条件必须写在where子句末尾。

3.where中避免使用 *

Oracle解析时会将*依次转换为所有列表。耗费时间。

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

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

 该函数可以避免重复扫描相同记录或重复连接相同的表。

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

7 删除重复记录

 delete from emp e where e.rowid>(

   select MIN(x.rowid) from emp x

 where x.emp_no=emp_no);

8删除表记录时用truncate代替delete

9用where子句代替Having子句

having 只会在检索出所有记录后才对结果集进行过滤,此处理需要排序,总计。

 on where having三个都可以加条件的子句中,on 最先执行,where次之,

having最后。因为on是先把不符合条件的记录过滤后才进行统计,减少中间运算要处理的数据 。

where过滤过数后才进行sum,在两个表联接时才用on的。

10 使用表的另外,用exists 替代 in,用not exists 替代 not in

11 用索引提供效率

 12.用exists替换distinct

当提交一个 包含 一对多表信息(如部门表和雇员表)查询时。因为RDMS核心模块将在子查询条件一旦满足后,立刻返回结果。

低效

 select distinct dep_no,dep_name from dep d, emp e

where d.dep_no=e.dep_no;

高效

select dep_no,dep_name from dep d where exists

(select 'X' form emp e where e.dep_no=d.dep_no);

13,语句大写。避免在索引上使用计算。

低效:select .. from dept where sal*12>25000;

高效:select .. from dept where sal>25000/12;

14.用>=替代>.

高效: 
SELECT * FROM  EMP  WHERE  DEPTNO >=4 
低效: 
SELECT * FROM EMP WHERE DEPTNO >3

两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.

(24 用UNION替换OR (适用于索引列) 
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引. 
高效: 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 
UNION 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE REGION = “MELBOURNE”

低效: 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”

(29) 用WHERE替代ORDER BY 
ORDER BY 子句只在两种严格的条件下使用索引. 
ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. 
ORDER BY中所有的列必须定义为非空. 
WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.

SELECT DEPT_CODE FROM  DEPT  ORDER BY  DEPT_TYPE 
高效: (使用索引) 
SELECT DEPT_CODE  FROM  DEPT  WHERE  DEPT_TYPE > 0

1)、select,update,delete 语句中的子查询应当有规律地查找少于20%的表行.如果一个语句查找的行数超过总行数的20%,它将不能通过使用索引获得性能上的提高.

  2). IN和EXISTS

  有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种格式的子查询。

  第一种格式是使用IN操作符:

... where column in(select * from ... where ...);

第二种格式是使用EXIST操作符:

... where exists (select 'X' from ...where ...);

posted on 2014-10-23 15:51  Dreaming-Dan  阅读(166)  评论(0编辑  收藏  举报