love wife love life —Roger的Oracle/MySQL數據恢復博客

Phone:18180207355 提供專業Oracle/MySQL數據恢復、性能優化、遷移升級、緊急救援等服務

Insert into is very slowly,why ?

本站文章除注明轉載外,均為本站原創: 轉載自love wife love life —Roger的Oracle/MySQL數據恢復博客

本文鏈接地址: Insert into is very slowly,why ?

上周運營商客戶的計費庫反應其入庫程序很慢,應用方通過監控程序發現主要慢在對于幾個表的insert操作上。按照我們的通常理解,insert應該是極快的,為什么會很慢呢?而且反應之前挺好的。這有點讓我百思不得其解。通過檢查event也并沒有發現什么奇怪的地方,于是我通過10046 跟蹤了應用的入庫程序,如下應用方反應比較慢的表的insert操作,確實非常慢,如下所示:

我們可以發現,insert了4579條數據,一共花了27.41秒;其中有24.02秒是處于等待的狀態。而且等待事件為順序讀.

很明顯這通常是索引的讀取操作,實際上檢查10046 trace 裸文件,發現等待的對象確實是該表上的2個index。
同時我們從上面10046 trace可以看出,該SQL執行之所以很慢,主要是因為存在了大量的物理讀,其中4579條數據的insert,
物理讀為4534;這說明什么問題呢? 這說明,每插入一條數據大概產生一個物理讀,而且都是index block的讀取。
很明顯,通過將該index cache到keep 池可以解決該問題。 實際上也確實如此,通過cache后,應用反饋程序快了很多。
那么對該問題,這里其實有幾個疑問,為什么這里的SQL insert時物理讀如此之高? oracle的keep pool對于緩存對象
的清理機制是如何的?

下面我們通過一個簡單的實驗來進行說明。

首先我們創建2個測試表,并創建好相應的index,如下所示:

從前面的信息我們可以看出,object_name上的index其實聚簇因子比較高,說明其數據分布比較離散。
接著我們現在將index都cache 到keep 池中,如下:

這里需要注意的是,僅僅執行alter 命令是不夠的,我們還需要手工將index block讀取到keep池中,如下:

我們可以大致看出,db keep pool 也是存在LRU的,而且對于block的清除機制是先進先出原則。那么為什么前面的問題中,insert會突然變慢呢?

下面我們來進行3次insert 測試。

#### one

#### two

#### three

從測試來看,隨著表的數據越來越大,insert的效率會越來越低,也其實主要在于index的問題。
我們可以發現,3次測試過程中,物理讀越來越大,而且db file sequential read的等待時間分別從0.5秒,增加到0.56秒,最后增加到1.07秒。?為什么會出現這樣的情況呢?
隨著表數據的日益增加,導致表上的index也不斷增大,同時index的離散度比較高,這樣就導致每次insert時,oracle在進行index block讀取時,可能在buffer cache中都無法命中相應的block;這樣就會導致每次讀取需要的index block時,可能都要進行物理讀,這勢必會導致性能問題的出現。
同時默認的default buffer cache pool雖然也可以緩存index 塊,但是也要同時緩存其他的數據塊,這樣很容易導致
相關的index block被從buffer cache pool中移走。所以這也是前面為什么需要將index cache到keep 池的原因。

One Response to “Insert into is very slowly,why ?”

  1. sqlora Says:

    除了keep cache沒有別的辦法嗎?

Leave a Reply

You must be logged in to post a comment.

百度彩票APP