數據庫

數據庫

1. 什麼存儲過程?它有什麼優點?

答:存儲過程是一組予編譯的SQL語句,

它的優點有:

允許模塊化程序設計,就是說只需要創建一次過程,以後在程序中就可以調用該過程任意次。

允許更快執行,如果某操作需要執行大量SQL語句或重複執行,存儲過程比SQL語句執行的要快。

減少網絡流量,例如一個需要數百行的SQL代碼的操作有一條執行語句完成,不需要在網絡中發送數百行代碼。

更好的安全機制,對於沒有權限執行存儲過程的用戶,也可授權他們執行存儲過程。

2. 存儲過程和函數有什麼區別?

Oracle中的函數與存儲過程的區別

A:函數必須有返回值,而過程沒有

B:函數可以單獨執行.而過程必須通過execute執行

C:函數可以嵌入到SQL語句中執行.而過程不行

其實我們可以將比較複雜的查詢寫成函數.然後到存儲過程中去調用這些函數

Oracle中的函數與存儲過程的特點

A. 一般來說,存儲過程實現的功能要複雜一點,而函數的實現的功能針對性比較強。 

B. 對於存儲過程來說可以返回參數,而函數只能返回值或者表對象。 

C.存儲過程一般是作爲一個獨立的部分來執行,而函數可以作爲查詢語句的一個部分來調用,由於函數可以返回一個表對象,因此它可以在查詢語句中位於FROM關鍵字的後面。

3. 什麼是事務?

答:事務是指一個工作單元,它包含了一組數據操作命令,並且所有的命令作爲一個整體一起向系統提交或撤消請求操作,即這組命令要麼都執行,要麼都不執行。

原子性:事務必須是原子工作單元;對於其數據修改,要麼全都執行,要麼全都不執行。

一致性:事務在完成時,必須使所有的數據都保持一致狀態。在相關數據庫中,所有規則都必須應用於事務的修改,以保持所有數據的完整性。事務結束時,所有的內部數據結構(如 樹索引或雙向鏈表)都必須是正確的。

隔離性:由 併發事務所作的修改必須與任何其它併發事務所作的修改隔離。事務查看數據時數據所處的狀態,要麼是另一併發事務修改它之前的狀態,要麼是另一事務修改它之 後的狀態,事務不會查看中間狀態的數據。這稱爲可串行性,因爲它能夠重新裝載起始數據,並且重播一系列事務,以使數據結束時的狀態與原始事務執行的狀態相 同。

持久性:事務完成之後,它對於系統的影響是永久性的。該修改即使出現系統故障也將一直保持。

4. 什麼是索引?它有什麼優點?

答:索引象書的目錄類似,索引使數據庫程序無需掃描整個表,就可以在其中找到所需要的數據,索引包含了一個表中包含值的列表,其中包含了各個值的行所存儲的位置,索引可以是單個或一組列,索引提供的表中數據的邏輯位置,合理劃分索引能夠大大提高數據庫性能。

5. 什麼是觸發器,它有哪些優點

答:觸發器是一種特殊類型的存儲過程,觸發器主要通過事件觸發而被執行的,

觸發器的優點:

1.強化約束,觸發器能夠提供比CHECK約束。

2.跟蹤變化,觸發器可以跟蹤數據庫內的操作,從而不允許未經允許許可的更新和變化。

3.聯級運算,比如某個表上的觸發器中包含對另一個表的數據操作,而該操作又導致該表上的觸發器被觸發。

6. 觸發器分爲事前觸發和事後觸發的區別。語句級觸發和行級觸發有何區別?

事前觸發器運行於觸發事件發生之前,通常可以獲取事件之前和新的字段值

事後觸發器運行於觸發事件發生之後。

語句級觸發器可以在語句執行前或後執行,

行級觸發在觸發器所影響的每一行觸發一次

7. 視圖是什麼?遊標是什麼?

答:視圖是一種虛擬表,虛擬表具有和物理表相同的功能,可以對虛擬表進行增該查操作,視圖通常是一個或多個表的行或列的子集,視圖的結果更容易理解(修改視圖對基表不影響),獲取數據更容易(相比多表查詢更方便),限制數據檢索(比如需要隱藏某些行或列),維護更方便。

遊標對查詢出來的結果集作爲一個單元來有效的處理,遊標可以定位在結果集的特定行、從結果集的當前位置檢索一行或多行、可以對結果集中當前位置進行修改。

8. 怎麼優化數據庫(在數據百萬條記錄的數據庫中 Oracle)?

使用索引

建立分區,分區索引

使用存儲過程

9. 如何優化SQL語句

1. 對操作符的優化 儘量不採用不利用索引的操作符

如:in not in , is nul, is not null<>

2. 對條件字段的一些優化

     採用函數處理的字段不能利用索引,

 進行了顯式或隱式的運算的字段不能進行索引

 條件內包括了多個本表的字段運算時不能進行索引

3. 在業務密集的SQL當中WHERE後面的條件順序影響

4. 應用ORACLEHINT(提示)處理

5. 查詢表順序的影響 

10. 使用索引查詢一定能提高查詢的性能嗎?爲什麼?

不能。如果返回的行數目較大,使用全表掃描的性能較好。

11. 操作符優化

1.IN 操作符

IN寫出來的SQL的優點是比較容易寫及清晰易懂,這比較適合現代軟件開發的風格。但是用INSQL性能總是比較低的,從Oracle執行的步驟來分析用INSQL與不用INSQL有以下區別:

ORACLE試圖將其轉換成多個表的連接,如果轉換不成功則先執行IN裏面的子查詢,再查詢外層的表記錄,如果轉換成功則直接採用多個表的連接方式查詢。由此可見用INSQL至少多了一個轉換的過程。一般的SQL都可以轉換成功,但對於含有分組統計等方面的SQL就不能轉換了。

推薦方案:在業務密集的SQL當中儘量不採用IN操作符,用EXISTS 方案代替。

2.NOT IN操作符

此操作是強列不推薦使用的,因爲它不能應用表的索引。

推薦方案:NOT EXISTS 方案代替

3.IS NULL IS NOT NULL操作(判斷字段是否爲空)

判斷字段是否爲空一般是不會應用索引的,因爲索引是不索引空值的。

推薦方案用其它相同功能的操作運算代替,如:a is not null 改爲 a>0 a>’’等。不允許字段爲空,而用一個缺省值代替空值,如申請中狀態字段不允許爲空,缺省爲申請。

4.及 操作符(大於或小於操作符)

大於或小於操作符一般情況下是不用調整的,因爲它有索引就會採用索引查找,但有的情況下可以對它進行優化,如一個表有100萬記錄,一個數值型字段A30萬記錄的A=030萬記錄的A=139萬記錄的A=21萬記錄的A=3。那麼執行A>2A>=3的效果就有很大的區別了,因爲A>2ORACLE會先找出爲2的記錄索引再進行比較,而A>=3ORACLE則直接找到=3的記錄索引。

5.LIKE操作符

LIKE操作符可以應用通配符查詢,裏面的通配符組合可能達到幾乎是任意的查詢,但是如果用得不好則會產生性能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。

一個實際例子:用YW_YHJBQK表中營業編號後面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個範圍的查詢,性能肯定大大提高。

6.UNION操作符

UNION在進行錶鏈接後會篩選掉重複的記錄,所以在錶鏈接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。實際大部分應用中是不會產生重複的記錄,最常見的是過程表與歷史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,如果表數據量大的話可能會導致用磁盤進行排序。

推薦方案:採用UNION ALL操作符替代UNION,因爲UNION ALL操作只是簡單的將兩個結果合併後就返回。

select * from gc_dfys
union all
select * from ls_jg_dfys

12. 說說你知道的一些關於查詢優化的方案?

1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

2.應儘量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:?

     select id from t where num is null?

     可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:?

     select id from t where num=0

3.應儘量避免在 where 子句中使用!=<>操作符,否則將引擎放棄使用索引而進行全表掃描。

4.應儘量避免在 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

5.in 和 not in 也要慎用,否則會導致全表掃描,如:?

     select id from t where num in(1,2,3)?

     對於連續的數值,能用 between 就不要用 in 了:?

     select id from t where num between 1 and 3

6.下面的查詢也將導致全表掃描:?

     select id from t where name like '%abc%'?

     若要提高效率,可以考慮全文檢索。

7.如果在 where 子句中使用參數,也會導致全表掃描。因爲SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作爲索引選擇的輸入項。如下面語句將進行全表掃描:?

     select id from t where num=@num?

     可以改爲強制查詢使用索引:?

     select id from t with(index(索引名)) where num=@num

8.應儘量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:?

     select id from t where num/2=100?

     應改爲:?

     select id from t where num=100*2

9.應儘量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:?

     select id from t where substring(name,1,3)='abc'--nameabc開頭的id?

     select id from t where datediff(day,createdate,'2005-11-30')=0--2005-11-30’生成的id?

     應改爲:?

     select id from t where name like 'abc%'?

     select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

10.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

11.在使用索引字段作爲條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個字段作爲條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓字段順序與索引順序相一致。

12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:?

     select col1,col2 into #t from t where 1=0?

     這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:?

     create table #t(...)

13.很多時候用 exists 代替 in 是一個好的選擇:?

     select num from a where num in(select num from b)?

     用下面的語句替換:?

     select num from a where exists(select 1 from b where num=a.num)

14.並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段sexmalefemale幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。

15.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因爲 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

16.應儘可能的避免更新 clustered 索引數據列,因爲 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那麼需要考慮是否應將該索引建爲 clustered 索引。

17.儘量使用數字型字段,若只含數值信息的字段儘量不要設計爲字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因爲引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。

18.儘可能的使用 varchar/nvarchar 代替 char/nchar ,因爲首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

19.任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

20.儘量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。

21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

22.臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。

23.在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,爲了緩和系統表的資源,應先create table,然後insert

24.如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。

25.儘量避免使用遊標,因爲遊標的效率較差,如果遊標操作的數據超過1萬行,那麼就應該考慮改寫。

26.使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。

27.與臨時表一樣,遊標並不是不可使用。對小型數據集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。

28.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句後向客戶端發送 DONE_IN_PROC 消息。

29.儘量避免大事務操作,提高系統併發能力。

30.儘量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

13. 談談你對SQL海量數據查詢優化性能的一些看法?

數據庫系統是管理信息系統的核心,基於數據庫的聯機事務處理(OLTP)以及聯機分析處理(OLAP)是銀行、企業、政府等部門最爲重要的計算機應用之一。從大多數系統的應用實例來看,查詢操作在各種數據庫操作中所佔據的比重最大,而查詢操作所基於的SELECT語句在SQL語句中又是代價最大的語句。舉例來說,如果數據的量積累到一定的程度,比如一個銀行的賬戶數據庫表信息積累到上百萬甚至上千萬條記錄,全表掃描一次往往需要數十分鐘,甚至數小時。如果採用比全表掃描更好的查詢策略,往往可以使查詢時間降爲幾分鐘,由此可見查詢優化技術的重要性。

百萬數據查詢優化技巧三十則(見問題12)

14. 數據庫內聯與外聯的區別?

內部聯接(inner join)一個聯接,返回兩表的公共列都匹配的行

外部聯接(outer join) 一個聯接,該聯接還包括那些和聯接表中記錄不相關的記錄。您可以創建一個外部聯接的三種變形來指定所包括的不匹配行:

左外部聯接、右外部聯接和完全外部聯接

左外部聯接(left outer join)   左邊的表是主表,列所有;右表無取null

右外部聯接(right outer join)  右邊的表是主表,列所有;左邊表只列匹配的行,沒有值置null

完全外部聯接 列所有,沒有值置null

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章