SQL进阶学习笔记

Posted on 2007-09-08 13:20 久城 阅读(3294) 评论(1)  编辑  收藏 所属分类: 数据库学习

听了一堂SQL课,受益良多,做下笔记。

SQL语句的执行计划

惭愧啊,这个名词我今天还是第一次接触,这大概已经是常识了吧呵呵。

没有太深的研究,暂时想是这样的,每一种数据库服务器在执行一条SQL语句的时候,首先都要解析这条SQL语句,每种数据库服务器的解析方式是不一样的,这样,制定出来的执行计划也就是不一样的。服务器通常都会在执行前通过某种算法(优化器)计算出很多种执行计划,然后选择其中它认为是最优的一种进行执行。

学会查看SQL语句的执行计划,有助于清晰的理解SQL语句的执行过程,特别是对SQL语句进行优化的时候,会有很大的帮助。

外连接

SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column(+= table2.column

如上所示,即左外连接,表示左边的内容有可能不全。当不全的时候,结果用空来代替。

理解外连接:相当于两个循环嵌套。
for table2.column
    
// 遍历table2中的每一列
    
// 把内容全的放在最外层循环
    for table1.column
    
// 数据库的具体执行内容

全外连接,相当于左外连接和右外连接的并集。

子查询

不相关子查询:子查询中,不涉及外层表中的数据。如:
SELECT list
FROM table a
WHERE a.f1 = ( SELECT b.f2
               
FROM table b
               
WHERE b.f3 = 'hello')

不相关子查询理解:先执行子查询,再执行外层查询。

相关子查询:子查询中,涉及到外层表中的数据。如:
SELECT list
FROM table a
WHERE a.f1 = ( SELECT b.f2
               
FROM table b
               
WHERE b.f3 = a.f4)

相关子查询理解:同样是两个循环的嵌套,如下:
for a
    
// 遍历表a中的每一行
    for b
    
// 遍历表b中的每一行
     
// 执行b.f3 = a.f4的查询,返回查询结果b.f2
    
// 这里查询结果如果为多条,oracle中会报错
    end for;
    
// 执行a.f1 = b.f2的查询
end for;

PS: a.f1 = (select语句),这个属于SQL3中的表表达式,select中可以返回多条记录,Oracle中不支持这种写法,所以当select语句返回多条记录的时候,会报错。但是DB2支持。

多行子查询:子查询返回多行记录,一般和IN, ANY, ALL, EXISTS配合使用。如:
SELECT list
FROM table a
WHERE a.f1 IN ( SELECT b.f2
                
FROM table b
                
WHERE b.f3 = a.f4 )


理解多行子查询:a.f1会和子查询结果中的每一个数据进行一次匹配循环,所以,这里值得注意的是:
1. IN和EXISTS的执行计划正好相反。用IN时,子查询为内层循环,用EXISTS时,子查询为外层循环。
2. 用IN时,子查询的返回条数不要太多,一般几十个已经够多了,如果过百的话.....呵呵.....

Top-N查询

SELECT [column_list] ROWNUM
FROM ( SELECT [column_list]
       
FROM table
       
ORDER BY Top-N_column )
WHERE ROWNUM <= N;


这里有个值得注意的地方就是,一定要先排序,再取Top-N。两个不要写在一起。

PS: SQL服务器从来都不保证解析出来的数据是有次序的,虽然我们不写ORDER BY查询时,每次查询结果的次序几乎都是一样的,但是,不能被表象所迷惑,这是不稳定的次序。

游标

以前理解游标只是一种变量类型,如果把它看成是一种语句执行方式的话,那么任何的SQL语句都是用游标的形式执行的。

游标变量
1. Strong 类型,即强类型。也许是我接触的比较少,还没发现有什么用,该类型游标变量必须指定游标的类型,对游标的使用进行了限制。
2. Weak类型,即弱类型。经常用,使用起来比较灵活,可以存储任意的返回类型。既然灵活,我想,也许会多少占用一些内存吧,还没深入研究。

异常

预先知道的一些异常,最好不要写在最后的异常捕获里。

比如,SELECT a INTO b FROM c. 如果a为null的话,会报no data found异常。象这样的,我们往往接受为null的情况,不想用异常来捕获,可以用两种方法来处理:
1. 使用游标
FETCH ... INTO...的时候,即使为空,也不会出异常,会继续执行下面的语句。
2. 使用PL/SQL块
BEGIN
  ...
  EXCEPTION
  // 进行局部异常处理
END;


关于优化

这个地方听的我就很迷糊了,很多概念都很模糊,先记录下。

任何一个SQL语句传到数据库的服务端都会被解析成一个执行树,每个节点是一个函数。

对表的处理只有两种处理方式,全表扫描和使用索引。

当返回值达到N时,使用全表扫描,也就是把数据全读到内存中一一进行处理。这里N的值,很多因素影响,一直都有变化,曾经是20%,可做参考。

当返回值小于N时,使用索引进行扫描。

索引就是一个B+树,和表密切相关。在执行delete操作的时候,索引并不被删除,而是用某个标识标识无效,所以,当对某个有索引的表的insert,delete操作比较频繁的时候,索引很有可能变得很庞大,这个时候就要考虑到对索引的维护。
这里索引的用法我还有很多地方迷惑,保留做以后研究。

欢迎来访!^.^!
本BLOG仅用于个人学习交流!
目的在于记录个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!

Feedback

# re: SQL进阶学习笔记  回复  更多评论   

2007-09-09 13:39 by 忘了哭
技术就是技术,日语是没有办法的工具,如果不是必要,请不要放在一起!
学习的笔记的整理能力值得学习,可以用日语结束,减,减,减- - :)

本评论仅用于个人沟通交流!
目的在于督触个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!

只有注册用户登录后才能发表评论。


网站导航:
 

Copyright © 久城