由于NLS參數設置不當導致的性能問題案例

這篇論壇文章(賽迪網技術社區)針對一個由于NLS參數設置不當導致的性能問題案例進行了深入的講解,更多內容請參考下文:

錯誤現象:

服務器CPU增加、響應慢。

問題原因:

取回statspack報告一看,問題很快找到了,有一條語句的physical reads非常高,初步判斷這條語句沒中索引,是全表掃描。但奇怪的是,這條語句結構很簡單,對一個表的查詢,帶一個查詢條件。類似如下:

select a, b from ttt where b like 'aaa%'

ttt表是個大表,這樣簡單而且會導致全表掃描的語句沒道理能輕易跑到生成庫上去的啊。

查了一下,果然字段b上面也是有索引的,而且b的cardinality值很高,以上語句幾乎肯定命中索引,在開發庫上看了它的查詢計劃,確實沒錯,命中了索引,效率也很高,幾乎沒有物理讀:

Execution Plan

----------------------------------------------------------

Plan hash value: 240739660

-------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 2 | 60 | 2 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TTT | 2 | 60 | 2 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | TTT_IDX | 2 | | 1 (0)| 00:00:01 |

-------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("B" LIKE 'aaa%')

filter("B" LIKE 'aaa%')

Statistics

----------------------------------------------------------

246 recursive calls

0 db block gets

57 consistent gets

4 physical reads

0 redo size

464 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

5 sorts (memory)

0 sorts (disk)

1 rows processed

嗯,難道是生産庫上的分析數據不正確(采用的是CBO),于是讓現場獲取語句的查詢計劃,竟然和開發庫結果是一樣的!這就奇怪了,statspack報告上顯示這條語句每次都幾百萬的物理讀啊,對比一下剛剛從生産庫拿到的報告,還是和前面一樣。難道有什麽東西改變了語句的查詢計劃?爲了證實這個想法,決定用更高級別的statspack來獲取該語句運行時的查詢計劃(具體方法可以參加另一篇文章《利用statspack來獲取生成環境中top SQL及其執行計劃》)。

先讓現場産生2個級別爲6的快照,從這兩個快照生成的報告中找到了語句的hash值,然後生成語句的報告,果然和我們得到的查詢計劃不同,是全表掃描!

SQL Text

~~~~~~~~

select a, b from ttt where b like 'aaa%'

Plans in shared pool between Begin and End Snap Ids

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Shows the Execution Plans found in the shared pool between the begin and end

snapshots specified. The values for Rows, Bytes and Cost shown below are those

which existed at the time the first-ever snapshot captured this plan - these

values often change over time, and so may not be indicative of current values

-> Rows indicates Cardinality, PHV is Plan Hash Value

-> ordered by Plan Hash Value

--------------------------------------------------------------------------------

| Operation | PHV/Object Name | Rows | Bytes| Cost |

--------------------------------------------------------------------------------

|SELECT STATEMENT | 2 | 60 | | 56 |

| TABLE ACCESS FULL | | 2 | 60 | 56 |

--------------------------------------------------------------------------------

爲什麽會這樣呢?

檢查程序代碼,結果在調用這條語句所在函數之前的語句中,我們發現了以下語句:

Execute Immediate ' alter session set nls_comp=LINGUISTIC'

Execute Immediate ' alter session set nls_sort=BINARY_CI'

嗯,這下我基本明白了。看到這兩個會話參數的設置我知道程序員是想對查詢條件不區分大小寫。這是10gR2的新特性,我也曾經在我的blog上介紹過,但是,我也提到過,這會導致查詢無法正確命中索引,這一點卻被該程序員忽略了。可以看以下結果:

SQL> alter session set nls_sort='BINARY_CI';

Session altered.

SQL> alter session set nls_comp='LINGUISTIC';

Session altered.

SQL> set autot trace

SQL> select a, b from ttt where b like 'aaa%';

Execution Plan

----------------------------------------------------------

Plan hash value: 774701505

-------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 2 | 60 | 56 (2)| 00:00:01|

|* 1 | TABLE ACCESS FULL| TTT | 2 | 60 | 56 (2)| 00:00:01|

-------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("B" LIKE 'aaa%')

Statistics

----------------------------------------------------------

364 recursive calls

0 db block gets

321 consistent gets

73 physical reads

0 redo size

560 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

8 sorts (memory)

0 sorts (disk)

5 rows processed

SQL> alter session set nls_sort='BINARY';

Session altered.

SQL> alter session set nls_comp='BINARY';

Session altered.

SQL> select a, b from ttt where b like 'aaa%';

Execution Plan

----------------------------------------------------------

Plan hash value: 240739660

-------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 2 | 60 | 2 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TTT | 2 | 60 | 2 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | TTT_IDX | 2 | | 1 (0)| 00:00:01 |

------------------------------------------------------------------------------

---------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("B" LIKE 'aaa%')

filter("B" LIKE 'aaa%')

Statistics

----------------------------------------------------------

8 recursive calls

0 db block gets

6 consistent gets

3 physical reads

0 redo size

464 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

這裏關于這個問題再說多兩句,當時我的文章中認爲通過nls設置不區分大小寫的實質是oracle內部加了upper函數,這個結論應該是錯的。實質上,此時在做精確匹配時應該是做了NLSSORT函數轉換:

SQL> alter session set nls_sort='BINARY_CI';

Session altered.

SQL> alter session set nls_comp='LINGUISTIC';

Session altered.

SQL> select a, b from ttt where b = 'aaa';

Execution Plan

----------------------------------------------------------

Plan hash value: 774701505

-------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 2 | 60 | 57 (4)| 00:00:01|

|* 1 | TABLE ACCESS FULL| TTT | 2 | 60 | 57 (4)| 00:00:01|

-------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter(NLSSORT("B",'nls_sort=''BINARY_CI''')=HEXTORAW('61616100')

)

Statistics

----------------------------------------------------------

217 recursive calls

0 db block gets

293 consistent gets

68 physical reads

0 redo size

461 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

5 sorts (memory)

0 sorts (disk)

1 rows processed

最終,對于這個問題的解決,還是通過傳統的加upper函數來解決。

結論:

1、 不要輕易修改會話屬性,對于一個具有獨立屬性的會話,將很難定位其中的問題;

2、 新特性固然有好處,但在使用之前,一定要先了解它的負面影響。

注意,本文目的是描述問題及其解決過程,所用數據都是在試驗庫上模擬出來的。

由于回滾段參數設置存在問題導致數據庫無法啓動
由于回滾段參數設置存在問題導致數據庫無法啓動 由于回滾段參數設置存在問題導致數據庫無法啓動 操作系統:Sun Solaris 8 雙機軟件: Sun Cluster 3.0數據庫:Oracle 8.1.7.3故障現象:1.Oracle無法啓動。2.雙...查看完整版>>由于回滾段參數設置存在問題導致數據庫無法啓動
 
由于回滾段參數設置存在問題導致數據庫無法啓動
操作系統:Sun Solaris 8 雙機軟件: Sun Cluster 3.0數據庫:Oracle 8.1.7.3故障現象:1.Oracle無法啓動。2.雙機的環境一個節點或者所有點上的oracle資源組無法啓動,顯示爲offline。3.手工啓動oracle時報告"ORA-010...查看完整版>>由于回滾段參數設置存在問題導致數據庫無法啓動
 
系統參數設置不當導致訪問速度慢-網絡故障
症狀 某著名系統集成商專門負責政府網建設的項目經理羅先生今天十萬火急地到網絡醫院電話急診,請求緊急支援。 羅先生反映的網絡故障表現很簡單:基本上所有的網絡成員訪問網絡資源的速度都非常緩慢,Ping測...查看完整版>>系統參數設置不當導致訪問速度慢-網絡故障
 
由于控制文件計劃不當而導致數據庫停止
由于控制文件所在磁盤空間滿了,歸檔的時候無法再往控制文件中添加歸檔信息,導致數據庫crash。 這是由于當初對文件磁盤分配沒有充分考慮而導致的。 ...查看完整版>>由于控制文件計劃不當而導致數據庫停止
 
由于控制文件計劃不當而導致數據庫停止
  由于控制文件所在磁盤空間滿了,歸檔的時候無法再往控制文件中添加歸檔信息,導致數據庫crash。  這是由于當初對文件磁盤分配沒有充分考慮而導致的。  系統檢查到數據庫無法登陸,不過internal可以登陸察看日...查看完整版>>由于控制文件計劃不當而導致數據庫停止
 
由于缺少分區導致Linux系統無法引導問題
問題出現的原因是系統增加一塊硬盤用來拷貝一些數據,然後將這塊硬盤拿走,系統就不能正常啓動了。提示信息是:請手動啓動系統。說實話,這句夠唬人的,LINUX 系統啓動時做了大量的工作,我們怎麽可能輕易搞定呢? 但...查看完整版>>由于缺少分區導致Linux系統無法引導問題
 
Linux下由于軟件問題導致死機的情況列舉
主要是列舉軟件上(或正常硬件)的死機原因,故此由硬件故障産生的死機問題不作任何列舉。格式:軟件1 + 軟件2 + 硬件3 + ...死機條件,死機症狀最佳解決辦法firefox + flash-plugin9打開firefox浏覽,畫面定格把flash...查看完整版>>Linux下由于軟件問題導致死機的情況列舉
 
給控制台使用正確的NLS_LANG設置
  大多數使用Windows命令提示符來運行SQL*Plus命令的用戶通常使用一個字符集,而這種字符集對于超過ASCII 的7位字符範圍之外的值就不正確了。一旦你嘗試從其他歐洲語言進入有特定音符的字符,擴展字符就會被翻譯錯...查看完整版>>給控制台使用正確的NLS_LANG設置
 
高級複制中mlog$表的HWM過高導致性能問題
這篇論壇文章(賽迪網技術社區)針對高級複制中由于mlog$表的HWM過高導致的性能問題進行了詳細的講解,更多內容請參考下文: 某系統升級後,報告事務端的數據庫反應非常慢,用戶大量投訴。 現場檢查系統後,發現CPU占...查看完整版>>高級複制中mlog$表的HWM過高導致性能問題
 
 
回到王朝網路移動版首頁