亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Oracle > 正文

Oracle Index 的三個問題

2024-08-29 13:46:27
字體:
來源:轉載
供稿:網友

  索引( Index )是常見的數據庫對象,它的設置好壞、使用是否得當,極大地影響數據庫應用程序和Database 的性能。雖然有許多資料講索引的用法, DBA 和 Developer 們也經常與它打交道,但筆者發現,還是有不少的人對它存在誤解,因此針對使用中的常見問題,講三個問題。 此文所有示例所用的數據庫是 Oracle 8.1.7 OPS on HP N series ,示例全部是真實數據,讀者不需要注重具體的數據大小,而應注重在使用不同的方法后,數據的比較。本文所講基本都是陳詞濫調,但是筆者試圖通過實際的例子,來真正讓您明白事情的要害。

  第一講、索引并非總是最佳選擇

  假如發現Oracle 在有索引的情況下,沒有使用索引,這并不是Oracle 的優化器出錯。在有些情況下,Oracle 確實會選擇全表掃描(Full Table Scan),而非索引掃描(Index Scan)。這些情況通常有:

  1. 表未做statistics, 或者 statistics 陳舊,導致 Oracle 判定失誤。

  2. 根據該表擁有的記錄數和數據塊數,實際上全表掃描要比索引掃描更快。

  對第1種情況,最常見的例子,是以下這句sql 語句:

select count(*) from mytable;
  在未作statistics 之前,它使用全表掃描,需要讀取6000多個數據塊(一個數據塊是8k), 做了statistics 之后,使用的是 INDEX (FAST FULL SCAN) ,只需要讀取450個數據塊。但是,statistics 做得不好,也會導致Oracle 不使用索引。

  第2種情況就要復雜得多。一般概念上都認為索引比表快,比較難以理解什么情況下全表掃描要比索引掃描快。為了講清楚這個問題,這里先介紹一下Oracle 在評估使用索引的代價(cost)時兩個重要的數據:CF(Clustering factor) 和 FF(Filtering factor).

  CF: 所謂 CF, 通俗地講,就是每讀入一個索引塊,要對應讀入多少個數據塊。

  FF: 所謂 FF, 就是該sql 語句所選擇的結果集,占總的數據量的百分比。

  大約的計算公式是:FF * (CF + 索引塊個數) ,由此估計出,一個查詢, 假如使用某個索引,會需要讀入的數據塊塊數。需要讀入的數據塊越多,則 cost 越大,Oracle 也就越可能不選擇使用 index. (全表掃描需要讀入的數據塊數等于該表的實際數據塊數)

  其核心就是, CF 可能會比實際的數據塊數量大。CF 受到索引中數據的排列方式影響,通常在索引剛建立時,索引中的記錄與表中的記錄有良好的對應關系,CF 都很??;在表經過大量的插入、修改后,這種對應關系越來越亂,CF 也越來越大。此時需要 DBA 重新建立或者組織該索引。

  假如某個sql 語句以前一直使用某索引,較長時間后不再使用,一種可能就是 CF 已經變得太大,需要重新整理該索引了。

  FF 則是Oracle 根據 statistics 所做的估計。比如, mytables 表有32萬行,其主鍵myid的最小值是1,最大值是409654,考慮以下sql 語句:

Select * from mytables where myid>=1; 和

Select * from mytables where myid>=400000
  這兩句看似差不多的 sql 語句,對Oracle 而言,卻有巨大的差別。因為前者的 FF 是100%, 而后者的 FF 可能只有 1%。假如它的CF 大于實際的數據塊數,則Oracle 可能會選擇完全不同的優化方式。而實際上,在我們的數據庫上的測試驗證了我們的猜測. 以下是在HP 上執行時它們的 eXPlain plan:

  第一句:

SQL> select * from mytables where myid>=1;
  已選擇325917行。

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3132 Card=318474 Byt es=141402456)

1 0 TABLE access (FULL) OF 'MYTABLES' (Cost=3132 Card=318474 Byt es=141402456)

Statistics

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

7 recursive calls

89 db block gets

41473 consistent gets

19828 physical reads

0 redo size

131489563 bytes sent via SQL*Net to client

1760245 bytes received via SQL*Net from client

21729 SQL*Net roundtrips to/from client

1 sorts (memory)

0 sorts (disk)

325917 rows PRocessed
  第二句:


Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=346 Card=663 Bytes=2 94372)

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'MYTABLES' (Cost=346 Card=663

Bytes=294372)

2 1 INDEX (RANGE SCAN) OF 'PK_MYTABLES' (UNIQUE) (Cost=5 Card=663)

Statistics

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

1278 recursive calls

0 db block gets

6647 consistent gets

292 physical reads

0 redo size

3544898 bytes sent via SQL*Net to client

42640 bytes received via SQL*Net from client

524 SQL*Net roundtrips to/from client

1 sorts (memory)

0 sorts (disk)

7838 rows processed
  顯而易見,第1句沒有使用索引,第2句使用了主鍵索引pk_mytables. FF的巨大影響由此可見一斑。由此想到,我們在寫sql 語句時,假如預先估計一下 FF, 你就幾乎可以預見到 Oracle 會否使用索引。
  第二講、索引也有好壞

  索引有 B tree 索引, Bitmap 索引, Reverse b tree 索引, 等。最常用的是 B tree 索引。 B 的全稱是Balanced , 其意義是,從 tree 的 root 到任何一個leaf ,要經過同樣多的 level. 索引可以只有一個字段(Single column), 也可以有多個字段(Composite),最多32個字段,8I 還支持 Function-based index. 許多developer 都傾向于使用單列B 樹索引。

  所謂索引的好壞是指:

  1,索引不是越多越好。非凡是大量從來或者幾乎不用的索引,對系統只有損害。OLTP系統每表超過5個索引即會降低性能,而且在一個sql 中, Oracle 從不能使用超過 5個索引。

  2,很多時候,單列索引不如復合索引有效率。

  3,用于多表連結的字段,加上索引會很有作用。

  那么,在什么情況下單列索引不如復合索引有效率呢?有一種情況是顯而易見的,那就是,當sql 語句所查詢的列,全部都出現在復合索引中時,此時由于 Oracle 只需要查詢索引塊即可獲得所有數據,當然比使用多個單列索引要快得多。(此時,這種優化方式被稱為 Index only access path)

  除此之外呢?我們還是來看一個例子吧:

  在 HP(Oracle 8.1.7) 上執行以下語句:

select count(1) from mytabs where coid>=130000 and issuedate >= to_date ('2001-07-20', 'yyyy-mm-dd')。
  一開始,我們有兩個單列索引:I_mytabs1(coid), I_mytabs2(issuedate), 下面是執行情況:

COUNT(1)

----------

6427

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=384 Card=1 Bytes=11)

1 0 SORT (AGGREGATE)

2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_MYTABS' (Cost=384 Card

=126 Bytes=1386)

3 2 INDEX (RANGE SCAN) OF 'I_MYTABS2' (NON-UNIQUE) (Cost=11

Card=126)

Statistics

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

172 recursive calls

1 db block gets

5054 consistent gets

2206 physical reads

0 redo size

293 bytes sent via SQL*Net to client

359 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

5 sorts (memory)

0 sorts (disk)

1 rows processed
  可以看到,它讀取了7000個數據塊來獲得所查詢的 6000多行。

  現在,去掉這兩個單列索引,增加一個復合索引I_mytabs_test ( coid, issuedate), 重新執行,結果如下:


COUNT(1)

----------

6436



Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=11)

1 0 SORT (AGGREGATE)

2 1 INDEX (RANGE SCAN) OF 'I_MYTABS_TEST' (NON-UNIQUE) (Cost=3 Card=126 Bytes=1386)

Statistics

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

806 recursive calls

5 db block gets

283 consistent gets

76 physical reads

0 redo size

293 bytes sent via SQL*Net to client

359 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

3 sorts (memory)

0 sorts (disk)

1 rows processed
  可以看到,這次只讀取了300個數據塊。

  7000塊對300塊,這就是在這個例子中,單列索引與復合索引的代價之比。這個例子提示我們, 在許多情況下,單列索引不如復合索引有效率。

  可以說,在索引的設置問題上,其實有許多工作可以做。正確地設置索引,需要對應用進行總體的分析。
  第三講、索引再好,不用也是白搭

  拋開前面所說的,假設你設置了一個非常好的索引,任何傻瓜都知道應該使用它,但是Oracle 卻偏偏不用,那么,需要做的第一件事情,是審閱你的 sql 語句。

  Oracle 要使用一個索引,有一些最基本的條件:

  1, where 子句中的這個字段,必須是復合索引的第一個字段;

  2, where 子句中的這個字段,不應該參與任何形式的計算

  具體來講,假設一個索引是按 f1, f2, f3的次序建立的,現在有一個 sql 語句, where 子句是 f2 = : var2, 則因為 f2 不是索引的第1個字段,無法使用該索引。

  第2個問題,則在我們之中非常嚴重。以下是從 實際系統上面抓到的幾個例子:

Select jobid from mytabs where isReq='0' and to_date (updatedate) >= to_Date ( '2001-7-18', 'YYYY-MM-DD');

………
  以上的例子能很輕易地進行改進。請注重這樣的語句天天都在我們的系統中運行,消耗我們有限的cpu 和 內存資源。

  除了1,2這兩個我們必須牢記于心的原則外,還應盡量熟悉各種操作符對 Oracle 是否使用索引的影響。這里我只講哪些操作或者操作符會顯式(explicitly)地阻止 Oracle 使用索引。以下是一些基本規則:

  1, 假如 f1 和 f2 是同一個表的兩個字段,則 f1>f2, f1>=f2, f1

  2, f1 is null, f1 is not null, f1 not in, f1 !=, f1 like ‘%pattern%’;

  3, Not exist

  4, 某些情況下,f1 in 也會不用索引;

  對于這些操作,別無辦法,只有盡量避免。比如,假如發現你的 sql 中的 in 操作沒有使用索引,也許可以將 in 操作改成 比較操作 + union all。筆者在實踐中發現很多時候這很有效。

  但是,Oracle 是否真正使用索引,使用索引是否真正有效,還是必須進行實地的測驗。合理的做法是,對所寫的復雜的 sql, 在將它寫入應用程序之前,先在產品數據庫上做一次explain . explain 會獲得Oracle 對該 sql 的解析(plan),可以明確地看到 Oracle 是如何優化該 sql 的。

  假如經常做 explain, 就會發現,喜愛寫復雜的 sql 并不是個好習慣,因為過分復雜的sql 其解析計劃往往不盡如人意。事實上,將復雜的 sql 拆開,有時候會極大地提高效率,因為能獲得很好的優化。當然這已經是題外話了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产亚洲成av人片在线观看桃| 福利视频一区二区| 欧美中文在线字幕| 九九热这里只有精品免费看| 97在线看免费观看视频在线观看| 九九视频直播综合网| 久久精品国产亚洲精品| 欧美日韩成人在线视频| 久久久国产精品免费| 青草青草久热精品视频在线观看| 一本色道久久综合狠狠躁篇怎么玩| 国产91ⅴ在线精品免费观看| 精品人伦一区二区三区蜜桃免费| 国产精品视频公开费视频| 98精品国产高清在线xxxx天堂| 亚洲视频欧美视频| 亚洲欧美变态国产另类| 日韩精品电影网| 亚洲男人第一网站| 亚洲欧美一区二区三区情侣bbw| 欧美激情一区二区三区高清视频| 中文字幕日韩精品在线观看| 精品成人乱色一区二区| 久久精品视频网站| 久久久亚洲精品视频| 隔壁老王国产在线精品| 乱亲女秽乱长久久久| 色综合久久精品亚洲国产| 第一福利永久视频精品| 国产精品视频精品视频| 中文字幕亚洲一区在线观看| 成人春色激情网| 欧美激情va永久在线播放| 亚洲已满18点击进入在线看片| 欧美激情亚洲激情| 国模精品视频一区二区| 亚洲伦理中文字幕| 黄色成人av在线| 亚洲精选在线观看| 97视频在线观看成人| 日日狠狠久久偷偷四色综合免费| 一区二区三区久久精品| 国产999精品| 国产精品亚洲精品| 国内精品久久久久影院 日本资源| 亚洲男人的天堂在线播放| 色狠狠av一区二区三区香蕉蜜桃| 国产最新精品视频| 久久成人一区二区| 国产美女扒开尿口久久久| 日韩精品免费在线视频观看| 欧美日韩人人澡狠狠躁视频| 91在线网站视频| 欧美午夜视频一区二区| 国产成人一区三区| 亚洲国产高清高潮精品美女| 日韩av免费观影| 欧美成人在线免费| 国产69久久精品成人| 久久久精品在线| 亚洲第一精品久久忘忧草社区| 伊人伊成久久人综合网小说| 中文字幕免费精品一区高清| 中文字幕av一区二区| 久久久久久久国产| 久久精品国产久精国产一老狼| 26uuu国产精品视频| 国产精品欧美日韩一区二区| 亚洲成人av资源网| 欧美贵妇videos办公室| 亚洲国产精品99久久| 亚洲视频在线观看视频| 日韩最新在线视频| 91国产美女视频| 一区二区三区视频在线| 国产成人精品久久二区二区91| 国产精自产拍久久久久久蜜| 国产视频综合在线| 97精品国产aⅴ7777| 日韩成人中文电影| 国产精品视频免费观看www| 欧美亚洲第一区| 国产黑人绿帽在线第一区| 亚洲欧美一区二区精品久久久| 国产在线久久久| 97国产精品视频人人做人人爱| 欧美日本高清视频| 国产精品1区2区在线观看| 国产欧美一区二区三区久久| 日本aⅴ大伊香蕉精品视频| 高清亚洲成在人网站天堂| 欧美精品在线第一页| 成人网在线免费观看| 日韩黄色高清视频| 91精品视频大全| 国外日韩电影在线观看| 欧美另类极品videosbest最新版本| 在线国产精品播放| 国产精品久久久久77777| 久久精品中文字幕| 欧美黑人xxxⅹ高潮交| 亚洲最大福利视频网| 国产精品激情av在线播放| 精品国产91久久久| 欧美激情xxxxx| 97久久精品视频| 国产一区二区三区中文| 91免费福利视频| 97精品视频在线播放| 国产精品视频精品| 欧美高跟鞋交xxxxhd| 2020欧美日韩在线视频| 亚洲xxxx做受欧美| 欧美一区二区影院| 九九热这里只有精品免费看| 久久天天躁狠狠躁夜夜躁2014| 久久久精品999| 欧美中文在线视频| 97在线免费观看视频| 久久91亚洲精品中文字幕奶水| 久久九九亚洲综合| 最近中文字幕日韩精品| 久久免费视频在线观看| 清纯唯美亚洲综合| 久久天堂电影网| 成人羞羞国产免费| 日韩在线激情视频| 久久久日本电影| 久久久久久久电影一区| 日韩av在线天堂网| 久久久这里只有精品视频| 国产噜噜噜噜噜久久久久久久久| 日韩av在线天堂网| 亚洲精品日产aⅴ| 国产99久久精品一区二区 夜夜躁日日躁| 久久夜精品香蕉| 欧美福利在线观看| 综合网中文字幕| 久久精品亚洲精品| 亚洲性69xxxbbb| 亚洲国产成人精品久久久国产成人一区| 久久久久久美女| 青草热久免费精品视频| 久久精品久久久久久国产 免费| 久久97久久97精品免视看| 国产成人鲁鲁免费视频a| 日韩精品极品在线观看播放免费视频| 国产精品自拍小视频| 日本精品一区二区三区在线播放视频| 久久久人成影片一区二区三区观看| 91精品国产91久久久久久最新| 亚洲曰本av电影| 日韩美女在线观看一区| 不卡毛片在线看| 最新国产成人av网站网址麻豆| 精品视频偷偷看在线观看| 亚洲激情视频在线观看| 国产精品亚洲自拍| 不卡伊人av在线播放| 国产精品久久久久久超碰| 国产视频精品一区二区三区| 日韩在线小视频| 亚洲最大在线视频| 精品无人区太爽高潮在线播放|