java程序員一些初中級面試題(數據庫部分)


說出一些數據庫優化方面的經驗?

1.從JDBC編程的角度講,用PreparedStatement一般來說比Statement性能高,因為在使用時,SQL語句被預編譯並存儲在PreparedStatement對象中,然后可以使用PreparedStatement對象多次高效地執行該語句。

2.有外鍵約束會影響插入和刪除性能,如果程序能夠保證數據的完整性,那在設計數據庫時就可以去掉外鍵。(程序控制代替數據庫控制)

3.表中允許適當冗余,比如訂單表中存賬號名,可以方便直接看訂單是哪個賬號創建的,而不用關聯賬號表去查詢賬號名。要分析業務的特點,對數據庫中表做優化,選擇合適的解決方案。也就是說,在有些情況下,設計數據庫可以適當地違反三個范式地設計原則,以獲得更好的程序性能。

4.SQL語句全部使用大寫,特別是列名和表名。Oracle數據庫中的語句執行機制是這樣的:編寫SQL語句->發給Oracle服務端->語法檢查和編譯成為內部指令->緩存和執行指令。在語法檢查和編譯階段,Oracle會自動將SQL語句轉換為大寫。並且根據SQL緩存的特點,不要拼湊條件,而是用占位符參數【?】和PreparedStatement來執行參數化的SQL語句。

5.建立索引改進查詢性能。當經常查詢索引列中的數據時,需要在表上創建索引。索引的缺點是占用磁盤空間,並且降低添加、刪除和更新行的速度。但是在大多數情況下,索引用於數據檢索的速度優勢大大超過它的不足之處。但是,如果應用程序非常頻繁地更新數據,或磁盤空間有限,則可能需要限制索引的數量。

你有優化SQL查詢數據的經驗嗎?如有能說一下你一般用哪些什么方式進行優化?

1.適當建立索引,用索引提高查詢效率、

2.選擇最有效率的表名順序。Oracle的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句寫在最后的表(基礎表,Driving Table)將最先被處理。

3.WHERE子句中的連接順序:Oracle采用自上至下的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前,哪些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。

4.SELECT子句中避免使用通配符【*】,需要什么字段,就寫什么字段的列名。

什么是事務?事務的四個特性是什么?有哪些隔離級別?

事務(Transaction)是數據庫操作的最小工作單元,是作為單個邏輯工作單元執行的一系列操作:這些操作作為一個整體一起向系統提交,要么全都執行,要么全都不執行。事務是一組不可再分的操作集合(工作邏輯單元)。

事務有四個特性,通常稱為ACID特性

1.原子性(Atomicity):事務是一個完整的操作,事務的各步操作是不可分的,要么都執行,要么都不執行。

2.一致性(Consistency):當事務完成時,數據必須處於一致狀態。

3.隔離性(Isolation):對數據進行修改的並發事務是彼此隔離的,這表明事務必須是獨立的,它不應以任何方式依賴於或影響其他事務。

4.持續性(Durability):事務完成后,它對數據庫的修改將被永久保存,事務日志能保持事務的永久性。

隔離級別有四種

1.Read Uncommitted(讀取未提交)

2.Read Committed(讀提交)

3.Repeatable Read(可以重復讀)

4.Serializable(序列化)

數據庫中,數據類型char和varchar2有什么區別?性能方面各有什么優勢?

char表示的是固定長度,所占存儲空間是固定的,定義長度是多少就是多少。數據量較大的時候,以char字段為查詢條件時查詢得快一點。

varchar2表示的是實際長度的數據類型,所占存儲空間為實際大小,前提是不超過定義的長度。如果存儲的字段不是定長的,用varchar2好一點,節省存儲空間。

你怎么知道查詢SQL的性能高還是低?

1.簡單的可以通過查看執行SQL的運行時間。

2.可以通過查看數據庫提供的語句執行計划來分析相應的數據信息,例如查看執行計划中對應的COST(成本耗費)值,反映了運行這段SQL的總體估計成本,通常COST低的執行計划要好一點。

在開發過程中遇到過數據庫鎖嗎?怎樣解鎖? 

如果Oracle中有事務未提交,又打開一個窗口去提交一個新的事務則可能會產生數據庫鎖。

解鎖的兩種方式

1.結束當前的Session(會話,這里值和數據庫的通訊)就會自動解鎖。

例如可以退出當前數據庫連接工具或應用程序。

2.利用DBA權限強行關閉執行Lock操作的Session。

可以通過查詢出SID和SERIAL#(流水號)去殺掉(關閉)會話。

-- 查詢出對應會話操作的SID和SERIAL
SELECT ID, SERIAL#, USERNAME, OSUSER FROM V$SESSION;

-- 根據指定的SID和SERIAL#來殺掉(關閉)對應的會話
ALTER SYSTEM KILL SESSION 'SID, SERIAL'

怎樣處理並發數據?

就數據庫操作來說,是通過加鎖的概念來確保並發數據操作下事務的完整性和數據庫的一致性。

數據庫主要有共享鎖和排他鎖。

排他鎖:當你再修改數據的時候,別人也可以查看,但是他不能修改數據並提交,只能優先你的操作,等到你向數據庫提交了數據之后他才能執行增刪改的操作,這就是排他鎖。

共享鎖:共享鎖就是你和另外一個用戶可以同時共享數據(查看),但是你和他都不能修改。

DELETE FROM TABLE和TRUNCATE TABLE的區別?DROP TABLE呢?

1.TRUNCATE是DDL(數據定義語言),所做的修改是不能回滾的,也就是不可恢復的操作。用了這個命令后就收回了表空間。DELETE是DML(數據操縱語言),執行刪除是會把數據寫入系統回滾段(ROLLBACK SEGEMENT)中以便恢復時使用。

2.兩者都是刪除表中的數據而不會影響到表的結構和定義。

3.使用DROP的話就會刪除表的結構。

UNION和UNION ALL有什么不同?

UNION在進行表連接后會篩選掉重復的記錄,所以在表連接后會對所產生的結果集進行排序運算,刪除重復的記錄再返回排序后的結果。

UNION ALL只是簡單地將兩個結果集合並后就返回,如果兩個結果集中有重復的數據,最后返回的結果集也會包含重復的數據,且不會進行排序。

從效率上來說,UNION ALL要比UNION快很多,如果可以確認合並的兩個結果集中不包含重復數據的話,建議使用UNION ALL。

JDBC訪問數據庫的步驟? 

1.加載JDBC驅動。

2.與數據庫建立連接。

3.發送SQL語句,並得到返回結果。

4.處理返回結果。

5.關閉資源。

大數據量下的分頁解決方法

最好的方法是利用SQL語句進行分頁,這樣每次查詢出的結果集中就只包含某頁的數據內容。在SQL語句無法實現分頁的情況下,可以考慮對大的結果集通過游標定位方式來獲取某頁的數據。

不同的數據庫下的分頁方案各不一樣,下面是主流的三種數據庫的分頁SQL:

SQL Server

String sql = "SELECT TOP " + pageSize + " * FROM STUDENTS WHERE ID NOT IN " + "(SELECT TOP " + pageSize * (pageNumber - 1) + " ID FROM STUDENTS ORDER BY ID)" + " ORDRE BY ID"; 

MySQL

String sql = "SELECT * FROM STUDENTS ORDER BY ID LIMIT " + pageSize * (pageNumber - 1) + "," + pageSize;

Oracle

String sql = "SELECT * FROM " + "(SELECT *, ROWNUM RID FROM (SELECT * FROM STUDENTS ORDER BY POSTIME DESC) WHERE RID <= " + pageSize * pageNumber + ") AS T" + " WHERE T > " + pageSize * (pageNumber - 1);

其實就是和它們SQL語句的不同語法有關。

簡述建立索引的作用和索引的分類?

索引的作用:通過使用索引,大大地提高數據庫的檢索速度,改善數據庫性能。

索引的分類

1.唯一索引:唯一索引不允許兩行具有相同的索引值。

2.主鍵索引:在數據庫關系圖中為表定義一個主鍵自動創建主鍵索引,主鍵索引是唯一索引的特殊類型。

3.聚集索引:在聚集索引中表中各行的事物順序與鍵值的邏輯(索引)順序相同且唯一

4.非聚集索引:非聚集索引建立在索引頁上,在查詢數據時可以總索引中找到記錄存放的位置。

5.復合索引:在創建索引時,並不是只能對其中一列創建索引,與創建主鍵一樣,可以將多個列組合作為索引,這種索引稱為復合索引。

6.全文索引:全文索引是一種特殊類型的、基於標記的功能性索引,由SQL Server中全文引擎服務創建和維護。

什么是存儲過程,有什么優缺點?

存儲過程(Stored Procedure)是一組為了完成特定功能的SQL語句集,是由流程控制和SQL語句書寫的命名語句塊,經編譯和優化后存儲在數據庫服務器中,應用程序使用時只要調用即可,可以通過特定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來調用。 

使用存儲過程有以下的優點

1.具有良好的安全性:可保證數據的安全性和完整性。通過存儲過程可以使沒有權限直接訪問響應數據庫對象的用戶受控制得間接地執行數據庫相關操作,從而保證數據的安全。

2.執行速度快,效率高:在運行存儲過程前,數據庫已對其進行了語法和句法分析,並給出了優化執行方案。這種已經編譯好的過程可極大地改善SQL語句的性能。由於執行SQL語句的大部分工作已經完成,所以存儲過程能以極快的速度執行。

3.減少網絡流量:可以降低網絡的通信量。

4.模塊化程序設計:存儲過程可以封裝業務邏輯,並存入數據服務器中,當業務邏輯發生變化時,無需修改調用存儲過程的應用程序,只需要修改存儲過程即可。

使用存儲過程的缺點是

1.相對而言,調試比較麻煩。

2.移植問題,數據庫端代碼當然是與具體數據庫相關的。

3.代碼可讀性差。

存儲過程與SQL的區別?

存儲過程是一組預編譯的SQL語句,經編譯后存儲在數據庫中,可包含一個或多個SQL語句,能夠完成一定功能的子程序,需要的時候用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。存儲過程可以包含數據操縱語言,邏輯和調用函數等;它又可分為系統存儲過程和用戶自定義的存儲過程。

SQL指的是結構化查詢語言,是一種ANSI的標准計算機語言。

如何創建視圖? 

創建視圖主要是通過以下語句來創建。

CREATE VIEW 視圖名 AS <SELECT 語句>

Oracle數據庫如何提高訪問性能?

避免在索引列上使用IS NULL和IS NOT NULL 操作

避免在索引中使用任何可以為空的列,Oracle蔣無法使用該索引,對於單列索引,如果列包含空值,索引中將不存在此記錄;對於復合索引,如果每個列都為空,索引中同樣不存在此記錄。如果至少有一個列不為空,則記錄存在於索引中。

例如:

如果唯一性索引建立在表的A列和B列上,並且表中存在一條記錄的A,B值為(123, null),Oracle將不接受下一條具有相同A,B值(123, null)的記錄(插入)。然而如果所有的索引列都為空,Oracle將認為整個鍵值為空而不等於空,因此你可以插入1000條具有相同簡直的記錄,當然它們都是空!因為空值不存在與索引列中,所以WHERE子句中對索引列進行空值比較將使Oracle停用該索引。

用UNION替換OR(適用於索引列)

通常情況下,用UNION替換WHERE子句中的OR將會引起較好的效果。對索引列使用OR將造成全表掃描。注意,以上規則只針對多個索引列有效。如果有column沒有被索引,查詢效率可能會因為你沒有選擇OR而降低。

分離表和索引

總是將你的表和索引建立在不同的表空間內(TABLESPACES),絕不要將不屬於Oracle內部系統的對象存放到System表空間里。同時,確保數據表空間和索引表空間置於不同的硬盤上(通過指定表空間的方式可以實現這個要求)。

共享SQL語句

為了不重復解析相同的SQL語句,在第一次解析之后,Oracle將SQL語句存放在內存中。這塊處於系統全局區域SGA(System Global Area)的共享池(Shared Buffer Pool)中的內存可以被所有的數據庫用戶共享。因此,當你執行一個SQL語句(有時被稱為一個游標)時,如果它之前和之前的執行過的語句完全相同,Oracle就能很快獲得已經被解析的語句以及最好的執行路徑。Oracle的這個功能大大提高了SQL的執行性能,並節省了內存的使用。

當你向Oracle提交一個SQL語句,Oracle會首先在這塊內存中查找相同的語句。

這里需要說明的是,Oracle對兩者采取的是一種嚴格匹配,要達到共享,SQL語句必須完全相同(包括空格,換行等)。

WHERE子句中的連接順序

Oracle采用自上而下的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前,那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。

SELECT子句中避免使用通配符【*】 

當你想在SELECT子句中列出所有的COLUMN時,使用動態列引用【*】是一個方便的方法,不幸的是,這是一個非常低效的方法。實際上,Oracle在解析的過程中,會將【*】依次轉換成所有的列名,這個工作是通過查詢數據字典完成的,這意味着將耗費更多的時間。

使用DECODE函數來減少處理時間 

使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表。

SELECT 
  COUNT(*),
  SUM(SAL)
FROM EMP
WEHRE DEPT_NO
= '0020' AND ENANME LIKE 'SMITH%'; SELECT
  COUNT(*),
  SUM(SAL)

FROM EMP
WEHRE DEPT_NO
= '0030' AND ENAME LIKE 'SMITH%'

你可以使用DECODE函數高效地得到相同結果。

SELECT
    COUNT(DECODE(DEPT_NO, '0020', 'X', NULL)) D0020_COUNT,
    COUNT(DECODE(DEPT_NO, '0030', 'X', NULL)) D0030_COUNT,
    SUM(DECODE(DEPT_NO, '0020', SAL, NULL)) D0020_SAL,
    SUM(DECODE(DEPT_NO, '0030', SAL, NULL)) D0030_DAL

FROM EMP

WHERE E_NAME LIKE 'SMITH%'

類似的,DECODE函數也可以運用於GROUP BY和ORDER BY子句中。

用TRUNCATE替代DELETE

當刪除表中的記錄時,在通常情況下,回滾段(ROLLBACK SEGMENTS)用來存放可以被恢復的信息。如果你沒有COMMIT事務,ORACLE會將數據恢復到刪除之前的狀態(准確地說是恢復到執行刪除命令之前的狀況)。而當運用TRUNCATE時,回滾段不再存放任何可以被恢復的信息。當命令運行后,數據不能被恢復。因此很少的資源被調用,執行時間也會很短。

不過要注意的是,TRUNCATE只在刪除全表適用,TRUNCATE是DDL,而不是DML。

盡量多使用COMMIT 

只要有可能,在程序中盡量多使用COMMIT,這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少。

COMMIT所釋放的資源:

1.回滾段上用於恢復數據的信息。

2.被程序語句獲得的鎖。

3.REDO LOG BUFFER中的空間。

4.Oracle為管理上述3種資源的內部花費。

在使用COMMIT時必須要注意到事務的完整性,現實中效率和事務完整性往往是不可兼得。

用WHERE子句替代HAVING子句

避免使用HAVING子句,因為HAVING子句只會在檢索出所有的記錄之后才對結果集進行過濾。這個處理需要排序,總計等操作,如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷。

用EXISTS替代IN

在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接,在這種情況下,使用EXISTS(或NOT EXISTS)通常將提高查詢的效率。

用NOT EXISTS替代NOT IN

在子查詢中,NOT IN 子句將執行一個內部的排序和合並。無論在哪種情況下,NOT IN都是最低效的(因為它對子查詢中的表執行了一個全表遍歷)。為了避免使用NOT IN,我么可以把它改寫成外連接(Outer Joins)或NOT EXISTS(最高效)。

聚合函數有哪些?

AVG()返回某列的平均值。

COUNT()返回某列的行數。

MAX()返回某列的最大值。

MIN()返回某列的最小值。

SUM()返回某列之和。

悲觀鎖和樂觀鎖的區別?

悲觀鎖(Pessimistic Lock):顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫里面就用到了很多這種鎖機制,比如行鎖,表鎖,讀鎖,寫鎖等,都是在做操作之前先上鎖。

樂觀鎖(Optimistic Lock):顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖。但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似於WRITE_CONDITION機制的其實都是提供的樂觀鎖。

兩種鎖各有優缺點,不可認為一種好於另一種。像樂觀鎖適用於寫比較少的情況下,即沖突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。

但是如果經常產生沖突,上層應用會不斷地進行retry,這樣反而降低了性能,所以這種情況下用悲觀鎖就比較合適。

 

"讓我來成為你一天的開始與結束。"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM