日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用优化器提示(Optimizer Hints)

發(fā)布時間:2025/3/20 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用优化器提示(Optimizer Hints) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

優(yōu)化器提示(Optimizer Hints)可以用在SQL語句中改變執(zhí)行計劃。

?

理解優(yōu)化器提示

提示讓你作出決定,這決定一般由優(yōu)化器來作出。作為一個應(yīng)用的設(shè)計者,你知道一些優(yōu)化器不知道的關(guān)于你的數(shù)據(jù)的信息。提示提供了一種機(jī)制來指導(dǎo)優(yōu)化器基于特殊條件下選擇某個查詢執(zhí)行計劃。
例如,對于某些查詢,你知道一個索引更具選擇性。在這些信息基礎(chǔ)上,你可以比優(yōu)化器選擇出一個更有效率的執(zhí)行計劃。在這樣的情況下,使用提示來指導(dǎo)優(yōu)化器使用最優(yōu)執(zhí)行計劃。
注意:使用提示包含了必須管理、檢查和控制的額外代碼。

?

提示的類型
提示包括以下類型:
1. Single-table:Single-table提示是特定在一個表或視圖上。INDEX和USE_NL是single-table提示的例子。
2. Multi-table:Multi-table提示與single-table提示相似,除了它可以特定在一個或多個表或視圖上。LEADING是multi-table提示的一個例子。注意USE_NL(table1 table2)不能認(rèn)為是multi-table提示,因?yàn)樗鼘?shí)際是USE_NL(table1)和USE_NL(table2)的快捷方式。
3. Query block:Query block提示在單個查詢塊中操作。STAR_TRANSFORMATION和UNNEST是query block提示的例子。
4. Statement:Statement提示應(yīng)用在整個SQL語句中。ALL_ROWS是Statement提示的一個例子。

?

提示分成以下幾種分類:
1. 用于優(yōu)化方法和目標(biāo)的提示
2. 用于訪問路徑的提示
3. 用于查詢轉(zhuǎn)換的提示
4. 用于連接順序的提示
5. 用于連接操作的提示
6. 用于平行執(zhí)行的提示
7. 其他提示

?

用于優(yōu)化方法和目標(biāo)(Optimization Approaches)的提示
以下提示讓你在優(yōu)化方法和目標(biāo)之間選擇:
1. ALL_ROWS
2. FIRST_ROWS(n)
如果一個SQL語句有一個提示來指定優(yōu)化的方法和目標(biāo),那么優(yōu)化器會使用指定的方法,而不管統(tǒng)計信息是否存在,或者OPTIMIZER_MODE初始化參數(shù)的值,或者ALTER SESSION語句的OPTIMIZER_MODE參數(shù)。
注意:優(yōu)化器的目標(biāo)只會應(yīng)用在直接提交的查詢。使用提示為任何從PL/SQL中提交的SQL語句指定訪問路徑。ALTER SESSION ... SET OPTIMIZER_MODE語句不會影響到PL/SQL中運(yùn)行的SQL語句。
如果你在SQL語句中指定ALL_ROWS或FIRST_ROWS(n)的其中一個提示,并且如果數(shù)據(jù)字段沒有語句要訪問的表的統(tǒng)計信息,那么優(yōu)化器會使用默認(rèn)值,例如那些表的分配存儲空間,來估計缺少的統(tǒng)計信息,然后選擇一個執(zhí)行計劃。這些估計可能沒有用DBMS_STATS包收集的信息精確,所以你應(yīng)該用DMBS_STATS包來收集統(tǒng)計信息。
如果你連同ALL_ROWS或FIRST_ROWS(n)一起來為訪問路徑或連接操作指定提示,那么優(yōu)化器會優(yōu)先選擇由提示指定的訪問路徑和連接操作。

?

用于訪問路徑(Access Paths)的提示
以下每種提示都指導(dǎo)優(yōu)化器使用一種特定的訪問路徑來訪問表:
1. FULL
2. CLUSTER
3. HASH
4. INDEX
5. NO_INDEX
6. INDEX_ASC
7. INDEX_COMBINE
8. INDEX_JOIN
9. INDEX_DESC
10. INDEX_FFS
11. NO_INDEX_FFS
12. INDEX_SS
13. INDEX_SS_ASC
14. INDEX_SS_DESC
15. NO_INDEX_SS
指定這些提示中的一個會引起優(yōu)化器特定的訪問路徑,但只有在這個訪問路徑基于索引或簇的存在且SQL語句中語法的正確時才可用。如果提示指定的是一個不可用的訪問路徑,那么優(yōu)化器會忽略它。
你必須在語句中指定要訪問的表。如果語句中用了別名來引用表,那么在提示要用別名而不是表名。如果語句中有方案名,提示中的表名不要包含方案名。
注意:對于訪問路徑提示,如果你在SELECT語句中的FROM子句部分指定了SAMPLE選項(xiàng),那么Oracle會忽略這個提示。

?

用于查詢轉(zhuǎn)換(Query Transformation)的提示
以下的提示各指導(dǎo)優(yōu)化器使用一種特定的SQL查詢轉(zhuǎn)換:
1. NO_QUERY_TRANSFORMATION
2. USE_CONCAT
3. NO_EXPAND
4. REWRITE
5. NO_REWRITE
6. MERGE
7. NO_MERGE
8. STAR_TRANSFORMATION
9. NO_STAR_TRANSFORMATION
10. FACT
11. NO_FACT
12. UNNEST
13. NO_UNNEST

?

用于連接順序(Join Orders)的提示
以下提示為連接順序提供建議:
1. LEADING
2. ORDERED

?

用于連接操作(Join Operations)的提示
以下每個提示都可以指導(dǎo)優(yōu)化器對表使用一種特定的連接操作:
1. USE_NL
2. NO_USE_NL
3. USE_NL_WITH_INDEX
4. USE_MERGE
5. NO_USE_MERGE
6. USE_HASH
7. NO_USE_HASH
推薦與任何連接順序提示(join order hint)一起使用USE_NL和USE_MERGE提示。當(dāng)引用的表被強(qiáng)制為連接中的內(nèi)部表時,Oracle使用這些提示;如果引用的表是外部表,那么這些提示會被忽略。

?

用于平行執(zhí)行(Parallel Execution)的提示
當(dāng)使用平行執(zhí)行時,以下提示是指導(dǎo)優(yōu)化器如何平行化或非平行化語句的。
1. PARALLEL
2. PQ_DISTRIBUTE
3. PARALLEL_INDEX
4. NO_PARALLEL_INDEX

?

其他提示(Additional Hints)
以下是一些其他提示:
1. APPEND
2. NOAPPEND
3. CACHE
4. NOCACHE
5. PUSH_PRED
6. NO_PUSH_PRED
7. PUSH_SUBQ
8. NO_PUSH_SUBQ
9. QB_NAME
10. CURSOR_SHARING_EXACT
11. DRIVING_SITE
12. DYNAMIC_SAMPLING
13. MODEL_MIN_ANALYSIS

?

指定提示(Specifying Hints)
提示只對它們出現(xiàn)在的語句塊的優(yōu)化起作用。一個語句塊是指以下語句或語句的一部分:
1. 一個簡單的SELECT,UPDATE或DELETE語句
2. 一個父語句或一個復(fù)雜語句的子查詢
3. 一個組合查詢的一部分
例如,一個由兩個通過UNION操作符構(gòu)成組件查詢(component queries)組成的組合查詢有兩個塊,每個都對應(yīng)一個組件查詢。因此,在第一個組件查詢的提示只對它自己的優(yōu)化起作用,而不會去優(yōu)化第二個組件查詢。

?

指定提示的Full Set
當(dāng)使用提示時,有些情況下,你需要指定提示的full set來確保最優(yōu)執(zhí)行計劃。例如,如果你有一個非常復(fù)雜的查詢,包含多個表連接,并且你只對其中一個給定的表指定了INDEX提示,那么優(yōu)化器需要決定剩余的要使用的訪問路徑和相關(guān)的連接方法。因此,盡管你給定了INDEX提示,優(yōu)化器可能不會使用該提示,因?yàn)橛蓛?yōu)化器選擇的連接方法和訪問路徑不會使用這個請求的索引。
在下面的例子中,LEADING提示指定了要被使用的確實(shí)連接順序;同時也指定了在不同表上使用的連接方法。

[java]?view plain?copy
  • SELECT???/*+?LEADING(e2?e1)?USE_NL(e1)?INDEX(e1?emp_emp_id_pk)??
  • ?????????????USE_MERGE(j)?FULL(j)?*/??
  • ?????????e1.first_name,?e1.last_name,?j.job_id,?sum(e2.salary)?total_sal??
  • FROM?????employees?e1,?employees?e2,?job_history?j??
  • WHERE????e1.employee_id?=?e2.manager_id??
  • ??AND????e1.employee_id?=?j.employee_id??
  • ??AND????e1.hire_date?=?j.start_date??
  • GROUP?BY?e1.first_name,?e1.last_name,?j.job_id??
  • ORDER?BY?total_sal;??
  • ?

    在提示中指定查詢塊(Query Block)
    要識別一個查詢中的查詢塊,可以在提示中使用一個可選的查詢塊名來指定要對哪個查詢塊進(jìn)行提示。查詢塊參數(shù)的語法是@queryblock的形式,這里的queryblock是在查詢中指定查詢塊的識別符。識別符queryblock可以是系統(tǒng)產(chǎn)生的,也可以是用戶指定的。
    1. 用EXPLAIN PLAN來查看查詢可以得到系統(tǒng)產(chǎn)生的識別符??梢酝ㄟ^運(yùn)行EXPLAIN PLAN來決定用NO_QUERY_TRANSFORMATION提示的查詢的預(yù)轉(zhuǎn)換查詢塊(pre-transformation query block)的名字。
    2. 用戶指定的名字可以用QB_NAME提示來設(shè)置。
    在下面的例子中,查詢塊名字被用來連同NO_UNNEST提示在視圖上的SELECT語句指定查詢塊。

    [java]?view plain?copy
  • CREATE?OR?REPLACE?VIEW?v?AS??
  • ??SELECT?e1.first_name,?e1.last_name,?j.job_id,?sum(e2.salary)?total_sal??
  • ????FROM?employees?e1,??
  • ??????(?SELECT?*??
  • ??????????FROM?employees?e3)?e2,?job_history?j??
  • ?????????WHERE?e1.employee_id?=?e2.manager_id??
  • ??????????AND?e1.employee_id?=?j.employee_id??
  • ??????????AND?e1.hire_date?=?j.start_date??
  • ??????????AND?e1.salary?=?(?SELECT?max(e2.salary)???
  • ?????????????????????????????FROM?employees?e2???
  • ?????????????????????????????WHERE?e2.department_id?=?e1.department_id?)???
  • ??GROUP?BY?e1.first_name,?e1.last_name,?j.job_id??
  • ??ORDER?BY?total_sal;??

  • 在為查詢運(yùn)行EXPLAIN PLAN并顯示計劃表(plan table)輸出后,你就可以看到系統(tǒng)產(chǎn)生的查詢塊識別符。例如,下面例子中顯示的輸出:
    [java]?view plain?copy
  • SELECT?PLAN_TABLE_OUTPUT?FROM?TABLE(DBMS_XPLAN.DISPLAY(NULL,?NULL,?'SERIAL'));??
  • ...??
  • Query?Block?Name?/?Object?Alias?(identified?by?operation?id):??
  • -------------------------------------------------------------??
  • ...??
  • 10?-?SEL$4????????/?E2@SEL$4??
  • ?
    ? 知道查詢塊名稱后,就可以使用到下面的SQL語句中:
    [java]?view plain?copy
  • SELECT?/*+?NO_UNNEST(?@SEL$4?)?*/??
  • ??*??
  • ?FROM?v;??
  • ?

    指定全局表(Global Table)提示
    通常指定表的提示一般是引用提示所在的DELETE,SELECT或UPDATE查詢塊中,而不是語句引用的視圖里的表。當(dāng)你想要為一個出現(xiàn)在視圖內(nèi)部的表指定提示時,Oracle推薦使用全局提示來代替嵌入提示到視圖中。在本章描述的表提示可以通過使用一個擴(kuò)展的包含表名和視圖名的tablespec語法來轉(zhuǎn)換成全局提示。
    除此之外,可以在tablespec語法之前設(shè)置一個可選的查詢塊名稱。
    使用以下的語法來指定一個表的提示:
    tablespec::=[view.]table
    其中:
    1. view指定了視圖的名稱
    2. table指定了表名或表的別名

    ?

    如果指定了視圖的路徑,提示是從左到右處理的,這樣第一個視圖必須在FROM子句中,然后每個后續(xù)的視圖必須在前一個視圖的FROM子句中。
    例如,在下面的例子中,視圖v用來返回雇員的性和名,他的工作和他的下屬各個部門最高工資的雇員的工資總和。當(dāng)查詢數(shù)據(jù)時,你想在視圖e2中對表e3強(qiáng)制使用索引emp_job_ix。

    [java]?view plain?copy
  • CREATE?OR?REPLACE?VIEW?v?AS??
  • SELECT??
  • ????e1.first_name,?e1.last_name,?j.job_id,?sum(e2.salary)?total_sal??
  • FROM?employees?e1,??
  • ????????(?SELECT?*??
  • ??????????FROM?employees?e3)?e2,?job_history?j??
  • WHERE?e1.employee_id?=?e2.manager_id??
  • ?????AND?e1.employee_id?=?j.employee_id??
  • ?????AND?e1.hire_date?=?j.start_date??
  • ?????AND?e1.salary?=?(?SELECT??
  • ???????????????????????max(e2.salary)??
  • ???????????????????????FROM?employees?e2??
  • ???????????????????????WHERE?e2.department_id?=?e1.department_id)??
  • GROUP?BY?e1.first_name,?e1.last_name,?j.job_id??
  • ORDER?BY?total_sal;??

  • 通過使用全局提示,你可以避免修改視圖v來在視圖e2中指定索引提示。要強(qiáng)制在表e3中使用索引emp_job_ix,可以用以下一種方法:
    [java]?view plain?copy
  • SELECT?/*+?INDEX(v.e2.e3?emp_job_ix)?*/??*???
  • ??FROM?v;??
  • ??
  • SELECT?/*+?INDEX(@SEL$2?e2.e3?emp_job_ix)?*/?*???
  • ??FROM?v;??
  • ??
  • SELECT?/*+?INDEX(@SEL$3?e3?emp_job_ix)?*/?*???
  • ??FROM?v;??

  • 全局提示語法也可以用在非融合視圖中,如下:
    [java]?view plain?copy
  • CREATE?OR?REPLACE?VIEW?v1?AS??
  • ??SELECT?*??
  • ????FROM?employees??
  • ????WHERE?employee_id?<?150;??
  • ??
  • CREATE?OR?REPLACE?VIEW?v2?AS??
  • ??SELECT?v1.employee_id?employee_id,?departments.department_id?department_id??
  • ????FROM?v1,?departments??
  • ????WHERE?v1.department_id?=?departments.department_id;??
  • ??
  • SELECT?/*+?NO_MERGE(v2)?INDEX(v2.v1.employees?emp_emp_id_pk)?
  • ????????????????????????FULL(v2.departments)?*/?*??
  • ??FROM?v2??
  • ??WHERE?department_id?=?30;??

  • 這個提示導(dǎo)致v2不被融合,且指定了employees和departments表的訪問連接。這些提示都下推到(非融合的)視圖v2里。

    ?

    指定復(fù)雜索引(Complex Index)提示
    指定一個索引的提示可以使用單個索引名稱或用括號括起來的字段列表,如下:
    indexspec::=index|([table.]column{1,})
    其中:
    1. table指定表名
    2. column指定特定表的字段名
    2.1 在字段前面可以可選地加上表限定詞作為前綴,這樣可以允許在索引字段不在索引表的情況下指定位圖連接索引。如果使用了表限定詞,那么必須使用全名,而不能用別名。
    2.2 索引中的每個字讀必須是特定表的基礎(chǔ)字段,而不是表達(dá)式?;诤瘮?shù)的索引不能用于字讀特定提示,除非索引說明指定的字段形成基于函數(shù)的索引的前綴。
    3. index指定索引名

    ?

    這種提示是這樣處理的:
    1. 如果指定了index名稱,那么只考慮索引。
    2. 如果指定了字段列表,且這個列表與一個存在的索引在指定的字段和順序上吻合,那么只考慮這個索引。如果沒有那樣的索引存在,那么表上的任何含有指定字段作為前綴的索引都會被考慮。任何一種情況,都會像用戶在所有符合的索引上指定相同的提示。
    例如,下面的例子中,job_history表有一個在employee_id字段上的單字段索引和一個連接了employee_id和start_date字段的索引。要特定地指導(dǎo)優(yōu)化器使用索引,查詢要這樣提示:

    [java]?view plain?copy
  • SELECT?/*+?INDEX(v.j?jhist_employee_ix?(employee_id?start_date))?*/?*?FROM?v;??
  • ?

    與視圖一起使用提示
    Oracle不建議在視圖(或子查詢)里面或本身上面使用提示。這是因?yàn)槟憧梢栽谝粋€上下文中定義視圖,然后在另一個中使用它們。還有,那樣的提示可能導(dǎo)致不確定的執(zhí)行計劃。特別地,在視圖內(nèi)部或本身上的提示根據(jù)視圖是否可以跟頂層查詢?nèi)诤蟻聿煌靥幚怼?/p>


    如果你想在視圖或子查詢中為一個表指定提示,那么推薦使用全局提示語法。


    雖然如此,如果你決定與視圖一起使用提示,那下面部分給出每種情況的描述。

    ?

    提示與復(fù)雜視圖
    默認(rèn)地,提示不會擴(kuò)展到一個復(fù)雜視圖的內(nèi)部。例如,如果你在一個選擇復(fù)雜視圖的查詢中指定了提示,那么那個提示不會產(chǎn)生作用,因?yàn)樗荒芡频揭晥D的內(nèi)部。

    注意:如果視圖是一個單表,那么提示提示不會被擴(kuò)展。


    除非提示是在基視圖的內(nèi)部,否則它們是不會在一個對于該視圖的查詢中起作用的。

    ?

    提示和可融合的視圖
    優(yōu)化方法和目標(biāo)(Optimation approach and goal)提示可以發(fā)生在頂層查詢或視圖內(nèi)部。
    1. 如果在頂層查詢中有那樣一個提示,那么提示會被使用而無視任何在視圖內(nèi)部的那種提示。
    2. 如果沒有頂層優(yōu)化器模式提示,那么在引用視圖里的模式提示將和視圖中的索引模式提示一起使用。
    3. 如果兩個或多個在引用視圖中的模式提示沖突的話,那么忽略所有在視圖里的模式提示,并且使用會話模式,不管是默認(rèn)或者是用戶指定的。

    ?

    在引用的視圖上的訪問路徑和連接提示會被忽略,除非視圖包含一個單表(或者應(yīng)用的是一個和單表一起的其他提示的視圖)。對于那些單表視圖,訪問路徑提示或連接提示會應(yīng)用到視圖內(nèi)部的表中。

    ?

    訪問路徑和連接提示可以出現(xiàn)在視圖的定義里。
    1. 如果視圖是一個內(nèi)聯(lián)視圖(即如果它出現(xiàn)在SELECT語句的FROM子句里),那么視圖內(nèi)部的所有訪問路徑和連接提示在與頂層查詢?nèi)诤蠒r都會保留下來。
    2. 對于不是內(nèi)聯(lián)視圖來說,視圖內(nèi)的訪問路徑和連接提示只有在引用的查詢不引用其他表或視圖(即如果SELECT語句的FROM子句只包含這個視圖)時才保留下來。

    ?

    在視圖上的PARALLEL,NO_PARALLEL,PARALLEL_INDEX和NO_PARALLEL_INDEX提示會被遞歸地應(yīng)用到引用視圖的索引表中。在頂層查詢的平行執(zhí)行提示會覆蓋引用視圖內(nèi)部的那些提示。

    ?

    視圖內(nèi)部的PARALLEL,NO_PARALLEL,PARALLEL_INDEX和NO_PARALLEL_INDEX提示在當(dāng)視圖與頂層查詢?nèi)诤蠒r保留下來。在頂層查詢的平行執(zhí)行提示會覆蓋引用視圖內(nèi)部的那些提示。

    ?

    提示和非融合視圖
    對于非融合視圖,視圖內(nèi)的優(yōu)化方法和目標(biāo)提示被忽略;頂層查詢決定優(yōu)化模式。
    因?yàn)榉侨诤弦晥D是從頂層查詢中分開優(yōu)化的,所以視圖內(nèi)部的訪問路徑和連接提示會被保留下來。相同原因,頂層查詢里的視圖上的訪問路徑提示會被忽略。
    盡管如此,頂層查詢里的視圖上的連接提示會被保留,因?yàn)槟欠N情況下,非融合視圖類似一個表。

    總結(jié)

    以上是生活随笔為你收集整理的使用优化器提示(Optimizer Hints)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。