SQL進階學習筆記

          Posted on 2007-09-08 13:20 久城 閱讀(3315) 評論(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 © 久城

          主站蜘蛛池模板: 旺苍县| 西安市| 孟村| 克东县| 富阳市| 财经| 博兴县| 梅河口市| 兖州市| 新竹市| 富蕴县| 江源县| 扎兰屯市| 株洲市| 宁南县| 益阳市| 邵阳市| 无棣县| 大洼县| 佛教| 鄢陵县| 兴安盟| 隆子县| 南昌市| 兰州市| 金乡县| 汉中市| 广昌县| 阿鲁科尔沁旗| 化德县| 丰城市| 黄石市| 加查县| 海兴县| 丰县| 利川市| 罗平县| 浪卡子县| 怀远县| 武城县| 赣州市|