[Java面試十二]資料庫概念相關
[Java面試十二]資料庫概念相關
1. 什麼是儲存過程?它有什麼優點?
答:儲存過程是一組予編譯的SQL語句,它的優點有:
允許模組化程式設計,就是說只需要建立一次過程,以後在程式中就可以呼叫該過程任意次。
允許更快執行,如果某操作需要執行大量SQL語句或重複執行,儲存過程比SQL語句執行的要快。
減少網路流量,例如一個需要數百行的SQL程式碼的操作有一條執行語句完成,不需要在網路中傳送數百行程式碼。
更好的安全機制,對於沒有許可權執行儲存過程的使用者,也可授權他們執行儲存過程。
2. oracle的儲存過程和函式有什麼區別?
Oracle中的函式與儲存過程的區別:
A:函式必須有返回值,而過程沒有.
B:函式可以單獨執行.而過程必須通過execute執行.
C:函式可以嵌入到SQL語句中執行.而過程不行.
其實我們可以將比較複雜的查詢寫成函式.然後到儲存過程中去呼叫這些函式.
Oracle中的函式與儲存過程的特點:
A. 一般來說,儲存過程實現的功能要複雜一點,而函式的實現的功能針對性比較強。
B. 對於儲存過程來說可以返回引數,而函式只能返回值或者表物件。
C.儲存過程一般是作為一個獨立的部分來執行,而函式可以作為查詢語句的一個部分來呼叫,由於函式可以返回一個表物件,因此它可以在查詢語句中位於FROM關鍵字的後面。
3. 什麼是事務?
答:事務是指一個工作單元,它包含了一組資料操作命令,並且所有的命令作為一個整體一起向系統提交或撤消請求操作,即這組命令要麼都執行,要麼都不執行。
原子性
一致性:事務在完成時,必須使所有的資料都保持一致狀態。在相關資料庫中,所有規則都必須應用於事務的修改,以保持所有資料的完整性。事務結束時,所有的內部資料結構(如 B 樹索引或雙向連結串列)都必須是正確的。
隔離性:由併發事務所作的修改必須與任何其它併發事務所作的修改隔離。事務檢視資料時資料所處的狀態,要麼是另一併發事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會檢視中間狀態的資料。這稱為可序列性,因為它能夠重新裝載起始資料,並且重播一系列事務,以使資料結束時的狀態與原始事務執行的狀態相同。
永續性:事務完成之後,它對於系統的影響是永久性的。該修改即使出現系統故障也將一直保持。
4. 什麼是索引?它有什麼優點?
答:索引象書的目錄類似,索引使資料庫程式無需掃描整個表,就可以在其中找到所需要的資料,索引包含了一個表中包含值的列表,其中包含了各個值的行所儲存的位置,索引可以是單個或一組列,索引提供的表中資料的邏輯位置,合理劃分索引能夠大大提高資料庫效能。
5. 什麼是觸發器,它有哪些優點?說說你遇到過的常見應用?
答:觸發器是一種特殊型別的儲存過程,觸發器主要通過事件觸發而被執行的,觸發器的優點:
①.強化約束,觸發器能夠提供比CHECK約束。
②.跟蹤變化,觸發器可以跟蹤資料庫內的操作,從而不允許未經允許許可的更新和變化。
③.聯級運算,比如某個表上的觸發器中包含對另一個表的資料操作,而該操作又導致該表上的觸發器被觸發。
6. 觸發器分為事前觸發和事後觸發的區別。語句級觸發和行級觸發有何區別?
事前觸發器運行於觸發事件發生之前,通常可以獲取事件之前和新的欄位值
事後觸發器運行於觸發事件發生之後。
語句級觸發器可以在語句執行前或後執行,
行級觸發在觸發器所影響的每一行觸發一次
7. 檢視是什麼?遊標是什麼?
答:檢視是一種虛擬表,虛擬表具有和物理表相同的功能,可以對虛擬表進行增該查操作,檢視通常是一個或多個表的行或列的子集,檢視的結果更容易理解(修改檢視對基表不影響),獲取資料更容易(相比多表查詢更方便),限制資料檢索(比如需要隱藏某些行或列),維護更方便。
遊標對查詢出來的結果集作為一個單元來有效的處理,遊標可以定位在結果集的特定行、從結果集的當前位置檢索一行或多行、可以對結果集中當前位置進行修改。
8. 怎麼優化資料庫(在資料百萬條記錄的資料庫中 Oracle)?
使用索引
建立分割槽,分割槽索引
使用儲存過程
9. 如何優化SQL語句
①. 對操作符的優化 儘量不採用不利用索引的操作符
如:in ,not in , is nul, is not null,<>等
②. 對條件欄位的一些優化
採用函式處理的欄位不能利用索引,
進行了顯式或隱式的運算的欄位不能進行索引
條件內包括了多個本表的欄位運算時不能進行索引
③. 在業務密集的SQL當中WHERE後面的條件順序影響
④. 應用ORACLE的HINT(提示)處理
⑤. 查詢表順序的影響
10. 使用索引查詢一定能提高查詢的效能嗎?為什麼?
不能。如果返回的行數目較大,使用全表掃描的效能較好。
11. 操作符優化
①.IN 操作符
用IN寫出來的SQL的優點是比較容易寫及清晰易懂,這比較適合現代軟體開發的風格。但是用IN的SQL效能總是比較低的,從Oracle執行的步驟來分析用IN的SQL與不用IN的SQL有以下區別:
ORACLE試圖將其轉換成多個表的連線,如果轉換不成功則先執行IN裡面的子查詢,再查詢外層的表記錄,如果轉換成功則直接採用多個表的連線方式查詢。由此可見用IN的SQL至少多了一個轉換的過程。一般的SQL都可以轉換成功,但對於含有分組統計等方面的SQL就不能轉換了。
推薦方案:在業務密集的SQL當中儘量不採用IN操作符,用EXISTS 方案代替。
②.NOT IN操作符
此操作是強列不推薦使用的,因為它不能應用表的索引。
推薦方案:用NOT EXISTS 方案代替
③.IS NULL 或IS NOT NULL操作(判斷欄位是否為空)
判斷欄位是否為空一般是不會應用索引的,因為索引是不索引空值的。
推薦方案:用其它相同功能的操作運算代替,如:a is not null 改為 a>0 或a>’’等。不允許欄位為空,而用一個預設值代替空值,如申請中狀態欄位不允許為空,預設為申請。
④.> 及 < 操作符(大於或小於操作符)
大於或小於操作符一般情況下是不用調整的,因為它有索引就會採用索引查詢,但有的情況下可以對它進行優化,如一個表有100萬記錄,一個數值型欄位A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那麼執行A>2與A>=3的效果就有很大的區別了,因為A>2時ORACLE會先找出為2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。
⑤.LIKE操作符
LIKE操作符可以應用萬用字元查詢,裡面的萬用字元組合可能達到幾乎是任意的查詢,但是如果用得不好則會產生效能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。
一個實際例子:用YW_YHJBQK表中營業編號後面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個範圍的查詢,效能肯定大大提高。
⑥.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 [email protected]?
可以改為強制查詢使用索引:?
select id from t with(index(索引名)) where [email protected]
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'--name以abc開頭的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查詢可能不會去利用索引,如一表中有欄位sex,male、female幾乎各一半,那麼即使在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) 一個聯接,該聯接還包括那些和聯接表中記錄不相關的記錄。您可以建立一個外部聯接的三種變形來指定所包括的不匹配行:
左外部聯接、右外部聯接和完全外部聯接。
u 左外部聯接(left outer join) 左邊的表是主表,列所有;右表無取null
u 右外部聯接(right outer join) 右邊的表是主表,列所有;左邊表只列匹配的行,沒有值置null
u 完全外部聯接 列所有,沒有值置null
15. 你熟悉的資料庫有哪些?
l Oracle:甲骨文;
l DB2:IBM;
l SQL Server:微軟;
l Sybase:賽爾斯;
l MySQL:甲骨文;
16. 分別說說DDL、DML、DCL、DQL分別指的是什麼?
l DDL(Data Definition Language):資料定義語言,用來定義資料庫物件:庫、表、列等;
建立資料庫:CREATE DATABASE [IF NOT EXISTS] mydb1;
刪除資料庫:DROP DATABASE [IF EXISTS] mydb1;
修改資料庫編碼:ALTER DATABASE mydb1 CHARACTER SET utf8
l DML(Data Manipulation Language):資料操作語言,用來定義資料庫記錄(資料);
插入資料:INSERT INTO 表名(列名1,列名2, …) VALUES(值1, 值2)
修改資料:UPDATE 表名 SET 列名1=值1, … 列名n=值n [WHERE 條件]
刪除資料:DELETE FROM 表名 [WHERE 條件]
l DCL(Data Control Language):資料控制語言,用來定義訪問許可權和安全級別;
建立使用者:CREATE USER 使用者名稱@地址 IDENTIFIED BY '密碼';
授權使用者:GRANT 許可權1, … , 許可權n ON 資料庫.* TO 使用者名稱
撤銷授權:REVOKE許可權1, … , 許可權n ON 資料庫.* FORM 使用者名稱
檢視許可權:SHOW GRANTS FOR 使用者名稱
刪除使用者:DROP USER 使用者名稱
修改密碼:USE mysql;
UPDATE USER SET PASSWORD=PASSWORD(‘密碼’) WHERE User=’使用者名稱’ and Host=’IP’;
FLUSH PRIVILEGES;
l DQL(Data Query Language):資料查詢語言,用來查詢記錄(資料)。
SELECT selection_list /*要查詢的列名稱*/
FROM table_list /*要查詢的表名稱*/
WHERE condition /*行條件*/
GROUP BY grouping_columns /*對結果分組*/
HAVING condition /*分組後的行條件*/
ORDER BY sorting_columns /*對結果分組*/
LIMIT offset_start, row_count /*結果限定*/
17. 資料庫中,我們對主鍵有哪些要求?
非空、唯一、可引用!
18. 分別說說MySQL和oracle的分頁?
oracle使用rownum加上巢狀子查詢完成分頁功能
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
MySQL使用的是limit函式
SELECT * FROM table LIMIT 5,10; //查詢的是第6條到第15條資料,注意,10位偏移量。