[英]How to check whether index is being used or not in Oracle
SELECT *
FROM (SELECT TEMP.*,
ROWNUM RNUM
FROM (SELECT entry_guid
FROM alertdevtest.ENTRY
WHERE Upper(alert_name) = 'alertname'
AND user_guid = 'AlertProductClientTest'
AND product_code = '-101'
AND status_code != 13) TEMP
WHERE ROWNUM <= 2500)
WHERE rnum >= 0;
SELECT *
FROM (SELECT TEMP.*,
ROWNUM RNUM
FROM (SELECT entry_guid
FROM alertdevtest.ENTRY
WHERE Upper(alert_name) = 'alertname'
AND user_guid = 'AlertProductClientTest'
AND product_code = '-101'
AND status_code != 13
AND product_view IN ( 'PView' )) TEMP
WHERE ROWNUM <= 2500)
WHERE rnum >= 0;
我正在運行上述查詢,發現第二個查詢與第一個查詢相比性能下降。 唯一的區別是第二個查詢中的附加過濾器和 PRODUCT_VIEW IN ('PView')。 但它在該列上有索引。 請讓我知道性能下降的原因是什么以及如何檢查索引是否被使用? 我正在使用 Oracle SQL 開發人員並嘗試檢查解釋計划但無法獲得更多詳細信息。
在Oracle SQL Developer中,當工作表中包含SQL時,會有一個“說明計划”按鈕,您也可以按F10鍵。 執行Explain計划后,它將顯示在SQL Developer的底部視圖中。 有一列“ OBJECT_NAME”,它將告訴您正在使用什么索引。 例如,在我剛運行的查詢中,左列(OPERATION)首先顯示“ SELECT STATEMENT”,然后顯示SORT(AGGREGATE),然后顯示INDEX(RANGE SCAN),然后在OBJECT_NAME列中顯示TICKER_IDX1,即我表上索引的名稱。
因此,您可以通過OBJECT_NAME列查看正在使用的索引。
Oracle基於成本的優化器可能會選擇次優的執行計划。 許多次更新統計信息將解決此問題。 其他選擇是添加其他索引,換句話說就是多列索引。 您可以提示一條SQL語句,但這很少需要。 另外,可以重寫查詢。
EXPLAIN PLAN
語句是檢查執行計划的最佳方法。 圖形執行計划被認為是有害的。
EXPLAIN PLAN
對於執行計划的常見圖形表示, EXPLAIN PLAN
具有許多優點:
DBMS_XPLAN.DISPLAY
可在任何環境中工作,並產生Oracle專業人員所熟悉的輸出。 有權使用Oracle的任何人都可以重現該問題,並且每個人都可以使用相同的標准名稱討論該問題。 SQL Developer可能是免費的,但大多數開發人員和DBA都不使用它。 Note
部分。 該部分通常包含重要信息。 在您的示例中,DBA可能為其中一個查詢而不是其他查詢固定了SQL Plan Baseline。 如果沒有“ Notes
部分,我們只需要猜測是否發生了奇怪的事情。 alter session enable parallel dml;
,計划可能會大不相同alter session enable parallel dml;
。 對於SQL Developer來說這似乎不是問題,但是我在其他程序中已經看到了。 DBMS_XPLAN
腳本,並具有許多強大的功能,例如format => '+outline'
, dbms_xplan.display_awr
等。 以下是EXPLAIN PLAN
的簡單示例。 這個計划很好,但是它確實有一個巨大的危險信號,大多數圖形執行計划都不會顯示。 最后一行,使用的dynamic statistics used: dynamic sampling (level=2)
表示其中一個表缺少優化器統計信息。
drop table test1;
create table test1(a number);
explain plan for insert into test1 select * from test1;
select * from table(dbms_xplan.display);
Plan hash value: 4122059633
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
| 1 | LOAD TABLE CONVENTIONAL | TEST1 | | | | |
| 2 | TABLE ACCESS FULL | TEST1 | 1 | 13 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
快速檢查可以輕松按F10,F5,Ctrl + E或您特定IDE中的任何快捷鍵。 但是對於要與他人共享的嚴肅分析,請始終使用EXPLAIN PLAN
。
了解性能低下的原因的最好的辦法是獲取SQL * Trace。 有多種啟用跟蹤的方法http://docs.oracle.com/cd/B19306_01/server.102/b14211/sqltrace.htm#g33356例如
EXECUTE DBMS_SESSION.SESSION_TRACE_ENABLE(waits => TRUE, binds => TRUE);
您需要啟用跟蹤,運行這些查詢,最后獲取數據(因為通常Oracle在獲取期間執行大部分工作),關閉會話(需要關閉游標以使帶有時間統計信息的執行計划出現在跟蹤文件中)。
然后,您應該轉到數據庫服務器上的轉儲文件夾,獲取跟蹤文件,使用tkprof實用程序將其轉換為更具可讀性的方式,在其中找到這些查詢,然后享受:)。
SQL Trace的好處在於,它提供了在SQL執行過程中使用的真實計划,並且為計划的每個步驟提供了非常精確的時間,讀取,獲取,一致讀取,cpu統計信息(不幸的是,我不知道任何其他工具可以可以做到)。
缺點是您需要特權才能開始跟蹤,並且需要訪問轉儲文件夾(或者您需要讓DBA使用跟蹤來執行查詢,並且需要服務器管理員來獲取文件)。
更粗糙的選擇是啟用對此SQL的監視(例如,通過/ * + monitor * /提示)並使用DBMS_SQLTUNE.REPORT_SQL_MONITOR
http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_sqltun.htm #CHDBHIBG-可能會為執行計划的每個步驟生成帶有統計信息的漂亮HTML(例如在SQL Trace中)
優點是易於使用(您無需訪問服務器文件夾即可使用此功能)。
缺點是這種情況下的統計數據通常為1秒,因此僅對長時間運行的查詢(10秒或更長時間)有用。
如果僅需要檢查在SQL執行期間是否使用了索引,則可以查詢v $ sql_plan視圖和v $ sql,v $ sql_monitor視圖以找到適當的計划。
您可以運行此查詢來檢查索引的使用情況。
select ius.* ,
(select sum(trunc(bytes / 1024 / 1024/ 1024 ,2))
from dba_segments sgm
where sgm.owner = ius.OWNER
and sgm.segment_name = ius.name ) Used_Space
,ind.DISTINCT_KEYS, ind.Total_Ind_Rows , ind.Total_Leaf_Block,
trunc((ius.bucket_0_access_count / nullif(ius.total_access_count,0)) *100 ,2)Access_0_PCT,
trunc((ius.bucket_1_access_count / nullif(ius.total_access_count,0)) *100 ,2) Access_1_PCT,
trunc((ius.bucket_2_10_access_count / nullif(ius.total_access_count,0)) *100,2) Access_2_10_PCT,
trunc((ius.bucket_11_100_access_count / nullif(ius.total_access_count,0)) *100,2) Access_11_100_PCT,
trunc((ius.bucket_101_1000_access_count / nullif(ius.total_access_count,0)) *100,2) Access_101_1000_PCT,
trunc((ius.bucket_1000_plus_access_count / nullif(ius.total_access_count,0)) *100,2) Access_1000_plus_PCT
from dba_index_usage ius ,
(select ind.OWNER,ind.INDEX_NAME,ind.DISTINCT_KEYS, sum(ind.num_rows)Total_Ind_Rows,sum(ind.LEAF_BLOCKS)Total_Leaf_Block,
trunc(sum(ind.num_rows)/nullif(sum(ind.LEAF_BLOCKS),0),2) RowsInBlocks
from all_indexes ind
where ind.owner = &SchemaName
group by ind.OWNER,ind.INDEX_NAME,ind.DISTINCT_KEYS
) ind
where ius.owner = &SchemaName
and ius.name = ind.INDEX_NAME
此外,您可以添加 v$sql_plan 和 dba_hist_sql_plan 來過濾未使用的索引。
and not exists
(select 'x'
from v$sql_plan pln
where pln.OPERATION = 'INDEX'
and pln.OBJECT_OWNER = ius.owner
and pln.OBJECT_NAME = ius.name)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.