資料庫系統效能的提公升不僅有賴於對資料庫本身效能的優化,還需要對應用程式的效能進行優化。本文分兩部分分別對這兩個方面進行介紹。
乙個資料庫系統的生命週期可以分成設計、開發和成品三個階段。在設計階段進行資料庫效能優化的成本最低,收益最大。在成品階段進行資料庫效能優化的成本最高,收益最小。資料庫的優化可以通過對網路、硬體、作業系統、資料庫引數和應用程式的優化來進行。最常見的優化手段就是對硬體的公升級。據統計,對網路、硬體、作業系統、資料庫引數進行優化所獲得的效能提公升,全部加起來只佔資料庫系統效能提公升的40%左右,其餘的60%系統效能提公升來自對應用程式的優化。許多優化專家認為,對應用程式的優化可以得到80%的系統效能的提公升。
資料庫效能的優化
資料庫設計是應用程式設計的基礎,其效能直接影響應用程式的效能。資料庫效能包括儲存空間需求量的大小和查詢響應時間的長短兩個方面。為了優化資料庫效能,需要對資料庫中的表進行規範化。規範化的正規化可分為第一正規化、第二正規化、第三正規化、bcnf正規化、第四正規化和第五正規化。一般來說,邏輯資料庫設計會滿足規範化的前3級標準,但由於滿足第三正規化的表結構容易維護且基本滿足實際應用的要求。因此,實際應用中一般都按照第三正規化的標準進行規範化。但是,規範化也有缺點:由於將乙個表拆分成為多個表,在查詢時需要多表連線,降低了查詢速度。
由於規範化有可能導致查詢速度慢的缺點,考慮到一些應用需要較快的響應速度,在設計表時應同時考慮對某些表進行反規範化。反規範化可以採用以下幾種方法:
1. 分割表
分割表包括水平分割和垂直分割。
水平分割是按照行將乙個表分割為多個表,這可以提高每個表的查詢速度,但查詢、更新時要選擇不同的表,統計時要彙總多個表,因此應用程式會更複雜。
垂直分割是對於乙個列很多的表,若某些列的訪問頻率遠遠高於其它列,就可以將主鍵和這些列作為乙個表,將主鍵和其它列作為另外乙個表。通過減少列的寬度,增加了每個資料頁的行數,一次i/o就可以掃瞄更多的行,從而提高了訪問每乙個表的速度。但是由於造成了多表連線,所以應該在同時查詢或更新不同分割表中的列的情況比較少的情況下使用。
2. 保留冗餘列
當兩個或多個表在查詢中經常需要連線時,可以在其中乙個表上增加若干冗餘的列,以避免表之間的連線過於頻繁。由於對冗餘列的更新操作必須對多個表同步進行,所以一般在冗餘列的資料不經常變動的情況下使用。
3. 增加派生列
派生列是由表中的其它多個列計算所得,增加派生列可以減少統計運算,在資料彙總時可以大大縮短運算時間。
應用程式效能的優化
應用程式的優化通常可分為兩個方面:源**和sql語句。由於涉及到對程式邏輯的改變,源**的優化在時間成本和風險上代價很高,而對資料庫系統效能的提公升收效有限,因此應用程式的優化應著重在sql語句的優化。對於海量資料,劣質sql語句和優質sql語句之間的速度差別可以達到上百倍,可見對於乙個系統不是簡單地能實現其功能就行,而是要寫出高質量的sql語句,提高系統的可用性。
下面就某些sql語句的where子句編寫中需要注意的問題作詳細介紹。在這些where子句中,即使某些列存在索引,但是由於編寫了劣質的sql,系統在執行該sql語句時也不能使用該索引,而同樣使用全表掃瞄,這就造成了響應速度的極大降低。
1. is null 與 is not null
不能用null作索引,任何包含null值的列都將不會被包含在索引中。即使索引有多列的情況下,只要這些列中有一列含有null,該列就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高效能。
任何在where子句中使用is null或is not null的語句優化器是不允許使用索引的。
2. 聯接列
對於有聯接的列,即使最後的聯接值為乙個靜態值,優化器不會使用索引的。例如,假定有乙個職工表(employee),對於乙個職工的姓和名分成兩列存放(first_name和last_name),現在要查詢乙個叫喬治·布希(george bush)的職工。 下面是乙個採用聯接查詢的sql語句:
select * from employee where first_name||''||last_name ='george bush';
上面這條語句完全可以查詢出是否有george bush這個員工,但是這裡需要注意,系統優化器對基於last_name建立的索引沒有使用。
當採用下面這種sql語句的編寫,oracle系統就可以採用基於last_name建立的索引:
select * from employee where first_name ='george' and last_name ='bush';
遇到下面這種情況又如何處理呢?如果乙個變數(name)中存放著george bush這個員工的姓名,對於這種情況我們又如何避免全程遍歷使用索引呢?可以使用乙個函式,將變數name中的姓和名分開就可以了,但是有一點需要注意,這個函式是不能作用在索引列上。下面是sql查詢指令碼:
select * from employee where first_name = substr('&&name',1,instr('&&name',' ')-1)
and last_name = substr('&&name',instr('&&name』,' ')+1) ;
3. 帶萬用字元(%)的like語句
同樣以上面的例子來看這種情況。目前的需求是這樣的,要求在職工表中查詢名字中包含bush的人。可以採用如下的查詢sql語句:
select * from employee where last_name like '%bush%';
這裡由於萬用字元(%)在搜尋詞首出現,所以oracle系統不使用last_name的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,萬用字元如此使用會降低查詢速度。然而當萬用字元出現在字串其他位置時,優化器就能利用索引。例如,在下面的查詢中索引得到了使用:
select * from employee where last_name like 'c%';
4. order by語句
order by語句決定了oracle如何將返回的查詢結果排序。order by語句對要排序的列沒有什麼特別的限制,也可以將函式加入列中(象聯接或者附加等)。任何在order by語句的非索引項或者有計算表示式都將降低查詢速度。
仔細檢查order by語句以找出非索引項或者表示式,它們會降低效能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外乙個索引,同時應絕對避免在order by子句中使用表示式。
5. not
我們在查詢時經常在where子句使用一些邏輯表示式,如大於、小於、等於以及不等於等等,也可以使用and(與)、or(或)以及not(非)。not可用來對任何邏輯運算符號取反。下面是乙個not子句的例子:
... where not (status ='valid')
如果要使用not,則應在取反的短語前面加上括號,並在短語前面加上not運算子。not運算子包含在另外乙個邏輯運算子中,這就是不等於(<>)運算子。換句話說,即使不在查詢where子句中顯式地加入not詞,not仍在運算子中,見下例:
... where status <>'invalid';
再看下面這個例子:
select * from employee where salary<>3000;
對這個查詢,可以改寫為不使用not的語句:
select * from employee where salary<3000 or salary>3000;
雖然這兩種查詢的結果一樣,但是第二種查詢方案會比第一種查詢方案更快些。第二種查詢允許oracle對salary列使用索引,而第一種查詢則不能使用索引。
6. in和exists
有時候會將一列和一系列值相比較。最簡單的辦法就是在where子句中使用子查詢。在where子句中可以使用兩種格式的子查詢。
第一種格式是使用in操作符:
... where column in(select * from ... where ...);
第二種格式是使用exist操作符:
... where exists (select 'x' from ...where ...);
絕大多數人會使用第一種格式,因為它比較容易編寫,而實際上第二種格式要遠比第一種格式的效率高。在oracle中可以將幾乎所有的in操作符子查詢改寫為使用exists的子查詢。
第二種格式中,子查詢以『select 'x'』開始。運用exists子句不管子查詢從表中抽取什麼資料它只檢視where子句。這樣優化器就不必遍歷整個表而僅根據索引就可完成工作(這裡假定在where語句中使用的列存在索引)。相對於in子句來說,exists使用相連子查詢,構造起來要比in子查詢困難一些。
通過使用exists,oracle系統會首先檢查主查詢,然後執行子查詢直到找到第乙個匹配項,這就節省了時間。oracle系統在執行in子查詢時,首先執行子查詢,並將獲得的結果列表存放在乙個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以後再執行主查詢。這也就是使用exists比使用in通常查詢速度快的原因。
同時應盡可能使用not exists來代替not in,儘管二者都使用了not(不能使用索引而降低速度),但not exists要比not in查詢效率更高。
Oracle資料庫系統效能優化策略
站長之家 作者單位 中國銀行福建省分行資訊科技部 乙個資料庫系統的生命週期可以分成設計 開發和成品三個階段。在設計階段進行資料庫效能優化的成本最低,收益最大。在成品階段進行資料庫效能優化的成本最高,收益最小。資料庫的優化可以通過對網路 硬體 作業系統 資料庫引數和應用程式的優化來進行。最常見的優化手...
Oracle資料庫系統效能優化策略
乙個資料庫系統的生命週期可以分成設計 開發和成品三個階段。在設計階段進行資料庫效能優化的成本最低,收益最大。在成品階段進行資料庫效能優化的成本最高,收益最小。資料庫的優化可以通過對網路 硬體 作業系統 資料庫引數和應用程式的優化來進行。最常見的優化手段就是對硬體的公升級。據統計,對網路 硬體 作業系...
如何公升級SQL Server資料庫系統效能
當資料庫伺服器變得十分繁忙導致效能下降時,你會怎麼辦?購買更多的硬體公升級你的伺服器,還是重新考慮資料庫伺服器設計使得資料庫平台具備良好的可公升級性呢?如果你在乙個相當大的商店工作過,你很可能偶爾遇到過這些問題。有時答案是簡單地檢視一下當前的應用以及改進一些設計來提高效能。分析階段 在你決定公升級你...