程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> Oracle一條SQL語句時快時慢

Oracle一條SQL語句時快時慢

編輯:Oracle教程

Oracle一條SQL語句時快時慢


今天碰到一個非常奇怪的問題問題,一條SQL語句在PL/SQL developer中很慢,需要9s,問題SQL:

SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001'; 表GG_function_location有5千萬的數據,parent_id上是有索引的。

診斷第一步:就在PL/SQL developer中按F5,看到的執行計劃是走索引的,應該不會慢啊。

第二步:在sqlplus中用autotrace看,非常快,0.06s。

第三部:我想要重現這種慢,於是在PL/SQL developer中開一個窗口,天啊!單獨執行SQL非常慢,但使用下面的語句就非常快,真是太神奇了。

alter session set tracefile_identifier = 'gg_test';
alter session set events '10046 trace name context forever ,level 12' ;
SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001' ;
alter session set events '10046 trace name context off' ;

第四部:我想到v$sql中找到這條SQL的執行計劃,終於有了發現。

SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE 12.1.0.1.0 Production
TNS for Linux: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production

SQL> select s.SQL_TEXT,s.SQL_ID

from v$sql s
where s.SQL_TEXT like
'SELECT * FROM GG_function_location f WHERE f.parent_id =%'
and s.SQL_TEXT not like '%AND%';
SQL_TEXT SQL_ID
------------------------------------------------------------------------- ------------
SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001' dk02nb8mkchna
SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001' 2zav8x5kwxb32
SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001' bc0k800k6u0x3

先找到SQL_ID,再找到對應的執行計劃

select hash_value, child_number, sql_text from v$sql s
where s.SQL_ID = 'bc0k800k6u0x3';
select * from table(dbms_xplan.display_cursor(611124131, 0, 'advanced'));

執行計劃一:
HASH_VALUE 656818826, child number 0
-------------------------------------
SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001'
Plan hash value: 1550360901
-----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 7 (100)| | | |
| 1 | TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| GG_FUNCTION_LOCATION | 3 | 999 | 7 (0)| 00:00:01 | ROWID | ROWID |
|* 2 | INDEX RANGE SCAN | IDX_GG_FL_PARENT_ID | 3 | | 4 (0)| 00:00:01 | | |
-----------------------------------------------------------------------------------------------------------------------------------

執行計劃二:
HASH_VALUE 611124131, child number 0
-------------------------------------
SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001'
Plan hash value: 3374024865
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 68 (100)| | | |
| 1 | PARTITION LIST ALL | | 1 | 247 | 68 (0)| 00:00:01 | 1 | 2 |
| 2 | PARTITION LIST ALL| | 1 | 247 | 68 (0)| 00:00:01 | 1 | 20 |
|* 3 | TABLE ACCESS FULL| GG_FUNCTION_LOCATION | 1 | 247 | 68 (0)| 00:00:01 | 1 | 40 |
------------------------------------------------------------------------------------------------------------

分析:我判斷是解析這條SQL語句走錯了執行計劃,SELECT * FROM GG_function_location f WHERE f.parent_id ='03000000000001',於是我把改為

SELECT /*+gg*/* FROM GG_function_location f WHERE f.parent_id ='03000000000001',非常快。接近就簡單了,把索引刪除後,重建,會讓此SQL重新解析。

解決方案:
drop index IDX_GG_FL_PARENT_ID;
create index IDX_GG_FL_PARENT_ID on GG_FUNCTION_LOCATION (PARENT_ID) nologging;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved