Oracle优化01-引起数据库性能问题的因素
思維導圖
概述
一個數據庫是否存在性能問題,基本上在系統設計的時候就決定了,這個系統設計包括軟件的設計、數據庫的設計和硬件的設計.其中更細節的分類參考目錄。
在一個系統的設計階段,其中任何一個環節存在設計不當之處,都可能導致系統的性能下降,而系統的性能在多數情況下又反映為數據庫的性能問題。
軟件設計對數據庫的影響
軟件架構設計對數據庫性能的影響
軟件系統的架構對數據庫的影響是非常直接的。 比如一套并發量非常大的系統,一般都會采用一套軟件來搭建一個中間層,用來構建緩沖池,在數據庫之前多大量的并發進行處理,以便于每次只有少數的用戶連接到數據庫中,其他的用戶在緩沖池的隊列中等待,同時,很多這種中間件軟件還提供了負載均衡的功能。
Oracle自身也提供了一種MTS技術,很少用,大部分都是采用中間件服務。
軟件代碼的編寫對數據庫性能的影響
軟件代碼對數據庫的影響,通常指的是應用程序中對數據庫操作的代碼部分對數據庫產生的影響。
具體來講就是SQL或者PL/SQL包。
SQL語句
SQL造成的影響
- 一種是 SQL語句本身在邏輯上就效率低下
- 另外一種SQL語句沒有綁定變量。
性能底下的SQL語句,比如使用不合適的Hint,不合適的外關聯,謂詞的隱含轉換,優化器的選擇等等,特別是多表關聯的情況下,影響更是顯著。 它主要體現為SQL語句的執行收到了人為的約束,比如數據的訪問方式(索引還是全表掃描),以及表關聯方式的選擇上.
人為的在SQL中加入Hint來約束SQL的執行計劃
對于高版本的數據庫(10g以上),CBO(基于成本的優化器)技術已經比較成熟,我們還是應該讓數據庫自己根據表、索引的統計分析信息來決定SQL的執行計劃,因為表中的數據是變化的,人為強制的干預,必然會在某個時候出現問題。
不必要的外連接操作
外連接是一個代價非常昂貴的執行過程,如果業務需要,這種操作是必須的,但是有時候會出現人為的在SQL中使用不必要的外連接的情形,因為有的開發者擔心遺漏一些數據而刻意使用它,讓SQL執行計劃變的非常耗時。
栗子
--創建t create table t as select rownum a , rownum+100 b from dba_users u where rownum <10 ;--批量向t表中寫入10萬數據,每5000次提交一次 beginfor i in 10 .. 100000 loopinsert into t (a, b) values (i, i);if mod(i, 5000) = 0 thencommit;end if;end loop; end;--創建t2 create table t2 as select decode(mod(rownum ,2),0,rownum) c ,rownum+1000 d from dba_users u where rownum<10;查詢
--左連接方式 select a, b, c, dfrom t, t2where t.a = t2.c(+)and t2.d > 1000;這個sql的含義是:得到t表上的所有行,然后用a和t2的c列關聯,同時t2的d>1000--內連接 select a, b, c, dfrom t, t2where t.a = t2.cand t2.d > 1000;從結果集上看,這兩條SQL是等價的,在這情況下,外連接其實是沒有用的,是人為的在SQL里設定的限制。
不難發現t2.d>1000已經明確的指出,在結果集中,t2表的任何一行,c列都應該有值,也就是在這種情況下,根本不需要使用外連接,業務邏輯上講,外連接在這里是多余的。 對數據庫來講,有時候在執行時可能會引起極大的性能差別。
CBO下優化器模式的選擇
通常對已一種功能單一的數據庫來講,在實例設置一個優化器模式即可,比如OLAP系統,絕大多數的時候運行的是報表作業,執行的基本上是聚合類的SQL操作,比如group by ,這個時候把優化器模式設置為all_rows是恰當的。
而對于一些分頁操作比較多的網站類數據庫,設置成 first_rows會更好一些。
但是有些情況比較復雜,比如數據庫上運行的基本是一個OLAP系統,所以優化器模式設置為ALL_ROWS,這樣利于報表的快速完成。
同時,數據庫上還有一些查詢業務,查詢的方式可以說是分頁的,針對這種情況,在開發階段就要考慮到這種情況,在SQL里通過Hint的方式將優化模式轉換成FIRST_ROWS,這樣既可以大大的提高數據的處理速度。
比如一次提取10條記錄的分頁查詢:
select * from (select /*+first_rows(10)*/x.*, rownum rnumfrom (select /* +first_rows(10)*/a, bfrom torder by a) xwhere rownum <= 10)where rnum >= 1;盡管在SQL中認為的加入hint操作不是一個好主意,但是有的時候如果需要兼顧用戶的其他操作,可以考慮這樣的設定。 但前期要做一些測試工作,確保這樣的優化能夠帶來性能上的提高,同時不會對數據庫造成其他方面的影響。 這是系統設計階段應該仔細考慮的一個問題。
沒有綁定變量的SQL
對于這個話題,很多人存在一個誤區,認為不使用綁定變量系統就要出問題一樣,有時候綁定變量對性能的影響被夸大化了。
其實我們應該分析我們當前的系統的實際情況:比如數據庫的用戶連接用戶很少,每個用戶每天觸發的查詢操作也很少,同時我們的數據庫主機8G內存,16個cpu, 硬解析對數據庫的性能影響的微乎其微,完全可以忽略掉,因為我們的系統是一個OLAP系統。
實際上,至少對于OLAP系統(在線分析系統,通常是指這樣的系統,數據庫中存放著海量的數據,連接的用戶很少,SQL基本上是用戶生成報表的大查詢)來說,即使沒有綁定變量對數據庫的影響也是有限的,甚至是完全沒有必要的,因為只有少量的用戶和少量的sql操作,數據庫不需要花多少資源在SQL分析上面。
綁定變量的真正的用途是在OLTP系統,OLTP系統通常有這樣的特點:
- 用戶并發數很大,
- 用戶的請求十分密集,
- 并且這些sql大多數是可以重復使用的。
試想一下,這些成千上萬的SQL一遍又一遍的被數據庫進行語法分析,予以分析,生成執行計劃,數據庫的壓力該有多大?
如果一條SQL執行一遍之后就被緩存到數據庫的內存(實際上是共享池里),后續所有的用戶請求的同樣的SQL,都是用共享池中的數據,biubiubiu~~~效率是不是提高很多?
所以,當你考察綁定變量對你的數據庫的影響有多大時,先確定你的系統是OLAP還是OLTP系統。 當然現在很多數據庫同事承擔著這兩種劫色,那么就需要分析數據庫的性能情況了,比如做一個Statspack Report幫助你確定變量是否綁定,以及是否已對系統的性能構成了嚴重的影響。
PL/SQL包
如果你的程序里有PL/SQL包,請考慮使用存過來代替它 。
存過是經過成功編譯后存放在數據庫中的代碼,執行起來的效率比程序代碼中的PL/SQL包的效率高很多,因為它不需要做語法和語義的分析。
語法分析:數據庫對sql進行檢查,是否存在語法錯誤
語義分析:查看語句執行的對象是否存在,是否有操作權限等。
數據庫的設計
除了一些必要的對象創建之外,還應該更多的考慮一些前瞻性的設計,以滿足系統生命周期里的各方面的需求,不至于發生大的修改或者升級。
基本上看來,前期數據庫的設計一個根基就是要弄清楚數據庫的類型。
OLTP(在線事物處理系統) 數據庫
OLTP更加強調數據庫的內存效率,強調各種指標的命中率,強調綁定變量,強調并發。
OLTP用戶并發數很多,數據庫側重對用戶操作的快速響應,這是對數據庫最重要的性能要求。
對于一個OLTP系統而言,數據庫內存設計顯得非常重要,如果數據都可以在內存中處理,無疑性能會提高很多, 有些對數據處理速度很高的系統,比如計費系統,已經差用了一些內存數據庫,比如ORACLE的Times Ten.
內存設計通常是通過調整Oracle和內存相關的初始化參數實現的。
SGA的大小(Data Buffer ,Shared Pool),PGA的大小(排序區,Hash區等)
這些參數在OLTP的系統中顯得至關重要。
OLTP數據塊的變化非常頻繁,SQL語句提交非常頻發,
- 對于數據塊來說,應該盡可能的讓數據塊保存在內存當中
- 對于SQL來說,盡可能的使用綁定變量來達到SQL的重用,減少物理IO和重復的SQL解析
關于初始化參數的設置,沒有一個絕對的標準,先給出一個經驗值 ,需要根據業務不斷的測試和調整,已達到最佳的性能。
除了內存、沒有綁定變量的SQL, 熱塊同樣也會導致數據庫性能的下降。
當一個塊被多個用戶同時讀取的時候,oracle為了維護數據的一致性,需要使用latch來串行化用戶的操作,當一個用戶獲取到了這個latch之后,其他的用戶就需要被迫等待。 獲取這個數據塊的用戶越多,等待就越明顯,就造成了熱塊問題。
這種熱塊可能是數據塊,也可能是回滾段。
對于數據塊來講,通常是數據塊上的數據分部不均勻導致,如果是索引的數據塊,可以考慮創建反向索引來達到重新分布數據的目的。
對于回滾段數據塊,可以適當的增加幾個回滾段來避免爭用。
OLAP(在線分析系統)/DSS(決策支持系統) 數據庫
OLAP著強調數據分析,強調SQL的執行時長,強調磁盤IO,強調分區等等
內存的優化對于OLAP的影響很小,因為海量的數據全部在內存中操作是很困難的,同時也是完全沒必要的,因為這些數據塊很少重用,緩存起來意義不大,倒是物理IO相當大,這種系統的瓶頸往往在磁盤IO上。
SQL優化
對于OLAP,SQL優化顯得非常重要,打個比方,一個表只有幾千條數據,無論是全表掃描還是使用索引,對我們來講差異其實很小。
但是當數據量達到幾億或者幾十億甚至更多的時候,全表掃索引可能導致極大的性能差異。因此SQL優化非常重要。
分區
同樣的,分區技術在OLAP系統中也很重要。 這種重要性主要體現在數據的管理上。
至于分區在性能上的影響,不能一概而論,認為分區的性能始終好于非分區,這個結論也是不成立的。
當查詢范圍正好落在某個分區時候
這個時候,分區的效率自然是高于沒有分區的,因為SQL咋有分區的表上只掃一個分區的數據,而對于沒有分區的數據,需要掃描整個表。
當查詢范圍跨越幾個分區時
這個時候分區可能并不絕對是最優的,分區索引并不一定比全局索引在任何時候都快,有時候反而會更慢
數據庫的硬件設計
數據庫的硬件設計在性能上主要體現在:
- CPU
- I/O
- 負載情況
存儲容量
占用空間的對象可以在DBA_SEGMENTS視圖中查找到,數據庫的空間分配是以段的形式分配的,凡是段對象都要占用空間,包括表 視圖 索引 物化視圖 其他一些大對象等。
存儲的物理設計
現在越來越多的數據庫選擇 SAN結構,這是一個擴展性非常好的存儲設計。
維護人員不僅要懂得磁盤陣列的技術,同時還要掌握SAN交換機的相關技術。
數據的安全
Data Guard 結構
https://docs.oracle.com/cd/B19306_01/server.102/b14239/toc.htm
如果用戶對數據的安全性要求性非常高,并且對系統宕機的時間要求很高,可以考慮使用Data Guard設計結構。
當主數據庫出現故障時,維護人員可以最短時間啟用備用數據庫,確保業務的正常進行。
RAC結構
RAC結構和Data Guard結構分屬于不同級別的安全設計,
Data Guard 能夠保證數據不丟失或者盡可能少丟失,Data Guard 的數據庫級別是一個冗余結構。
而RAC則是實例級的一個冗余結構,它能夠保證數據庫在一個實例出現故障后,用戶可以無縫地由另外一個實例接管。
現在很多業務連續性很高的系統都采用RAC+Data Guard的 數據庫結構設計。
Rman+歸檔方式
Rman+歸檔的備份方式,相對于RAC+Data Guard來看,
優勢是成本低廉,并且能夠保證數據的完整,當數據庫損壞時,可以恢復到備份的時間點。
缺點是 需要較長的宕機時間。
exp/imp , expd/impdp
這兩種方式更像是數據傳遞或者數據保存,它不能保證數據的安全。
總結
首先弄清楚系統是OLAP還是OLTP
系統并發量,OLTP作為一個重要的因素
高并發可能導致
- 系統資源嚴重被使用,系統過負荷運行
- 嚴重的等待事件,比如熱塊和鎖定
SQL代碼的編寫,SQL優化的技巧
數據庫的設計
存儲的設計
總結
以上是生活随笔為你收集整理的Oracle优化01-引起数据库性能问题的因素的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Shell脚本攻略02-玩转变量与环境变
- 下一篇: Shell脚本攻略03-使用shell进