第一篇:OracleSQL語句的執(zhí)行計(jì)劃優(yōu)化的總結(jié)
通過分析SQL語句的執(zhí)行計(jì)劃優(yōu)化SQL(總結(jié))
第一章、第2章 并不是很重要,是自己的一些想法,關(guān)于如何做一個(gè)穩(wěn)定、高效的應(yīng)用系統(tǒng)的一些想法。
第三章以后都是比較重要的。
附錄的內(nèi)容也是比較重要的。我常用該部分的內(nèi)容。
前言
本文檔主要介紹與SQL調(diào)整有關(guān)的內(nèi)容,內(nèi)容涉及多個(gè)方面:SQL語句執(zhí)行的過程、ORACLE優(yōu)化器,表之間的關(guān)聯(lián),如何得到SQL執(zhí)行計(jì)劃,如何分析執(zhí)行計(jì)劃等內(nèi)容,從而由淺到深的方式了解SQL優(yōu)化的過程,使大家逐步步入SQL調(diào)整之門,然后你將發(fā)現(xiàn)??。
該文檔的不當(dāng)之處,敬請指出,以便進(jìn)一步改正。請將其發(fā)往我的信箱:xu_yu_jin2000@sina.com。
如果引用本文的內(nèi)容,請著名出處!
作者:徐玉金
MSN:sunny_xyj@hotmail.com
Email: xu_yu_jin2000@sina.com
日期:2005.12.12
活躍于:004km.cn;
這樣在分析時(shí)導(dǎo)致查詢出的數(shù)據(jù)過多,不方便,所以用count(a.CHANNEL||B.user_class)來代替,而且count(a.CHANNEL||B.user_class)操作本身并不占用過多的時(shí)間,所以可以接受此種替代。
利用索引查詢出SWD_BILLDETAIL表中所有記錄的方法 SQL> select count(id)from SWD_BILLDETAIL;COUNT(ID)----------
53923574 Elapsed: 00:02:166.00 Execution Plan---------------------------0
SELECT STATEMENT Optimizer=CHOOSE(Cost=18051 Card=1)1
0
SORT(AGGREGATE)2
INDEX(FAST FULL SCAN)OF 'SYS_C001851'(UNIQUE)(Cost=18051 Card=54863946)
Statistics---------------------------
0 recursive calls
1952 db block gets
158776 consistent gets
158779 physical reads
1004 redo size
295 bytes sent via SQL*Net to client
421 bytes received via SQL*Net from client SQL*Net roundtrips to/from client sorts(memory)
0 sorts(disk)rows processed
利用全表掃描從SWD_BILLDETAIL表中取出全部數(shù)據(jù)的方法。SQL> select count(user_class)from swd_billdetail;COUNT(USER_CLASS)-----------------
53923574 Elapsed: 00:11:703.07 Execution Plan---------------------------0
SELECT STATEMENT Optimizer=CHOOSE(Cost=165412 Card=1 Bytes=2)1
0
SORT(AGGREGATE)2
TABLE ACCESS(FULL)OF 'SWD_BILLDETAIL'(Cost=165412 Card=54863946 Bytes=109727892)
Statistics---------------------------
0 recursive calls
8823 db block gets
1431070 consistent gets
1419520 physical reads
0 redo size
303 bytes sent via SQL*Net to client
421 bytes received via SQL*Net from client SQL*Net roundtrips to/from client sorts(memory)
0 sorts(disk)rows processed
select count(a.CHANNEL||B.user_class)from swd_billdetail B, SUPER_USER A where A.cn = B.cn;EXEC_ORDER PLANLINE------------------------
SELECT STATEMENT OPT_MODE:CHOOSE(COST=108968,CARD=1,BYTES=21)
SORT(AGGREGATE)(COST=,CARD=1,BYTES=21)
NESTED LOOPS
(COST=108968,CARD=1213745,BYTES=25488645)
TABLE ACCESS(FULL)OF 'SWORD.SUPER_USER'(COST=2,CARD=2794,BYTES=27940)
TABLE ACCESS(BY INDEX ROWID)OF 'SWORD.SWD_BILLDETAIL'(COST=39,CARD=54863946,BYTES=603503406)
INDEX(RANGE SCAN)OF 'SWORD.IDX_DETAIL_CN'(NON-UNIQUE)(COST=3,CARD=54863946,BYTES=)
這個(gè)查詢耗費(fèi)的時(shí)間很長,需要1個(gè)多小時(shí)。運(yùn)行后的信息如下:
COUNT(A.CHANNEL||B.USER_CLASS)------------------------------
1186387
Elapsed: 01:107:6429.87
Execution Plan---------------------------
0
SELECT STATEMENT Optimizer=CHOOSE(Cost=108968 Card=1 Bytes=21)
0
SORT(AGGREGATE)
NESTED LOOPS(Cost=108968 Card=1213745 Bytes=25488645)
TABLE ACCESS(FULL)OF 'SUPER_USER'(Cost=2 Card=2794Bytes=27940)
TABLE ACCESS(BY INDEX ROWID)OF 'SWD_BILLDETAIL'(Cost=39 Card=54863946 Bytes=603503406)
INDEX(RANGE SCAN)OF 'IDX_DETAIL_CN'(NON-UNIQUE)(Cost=3 Card=54863946)Statistics---------------------------
0 recursive calls db block gets
1196954 consistent gets
1165726 physical reads
0 redo size
316 bytes sent via SQL*Net to client
421 bytes received via SQL*Net from client SQL*Net roundtrips to/from client sorts(memory)
0 sorts(disk)rows processed
將語句中加入hints,讓oracle的優(yōu)化器使用嵌套循環(huán),并且大表作為驅(qū)動(dòng)表,生成新的執(zhí)行計(jì)劃:
select /*+ ORDERED USE_NL(A)*/ count(a.CHANNEL||B.user_class)from swd_billdetail B, SUPER_USER A where A.cn = B.cn;
EXEC_ORDER PLANLINE------------------
SELECT STATEMENT OPT_MODE:CHOOSE(COST=109893304,CARD=1,BYTES=21)
SORT(AGGREGATE)(COST=,CARD=1,BYTES=21)
NESTED LOOPS
(COST=109893304,CARD=1213745,BYTES=25488645)
TABLE ACCESS(FULL)OF 'SWORD.SWD_BILLDETAIL'(COST=165412,CARD=54863946,BYTES=603503406)
TABLE ACCESS(BY INDEX ROWID)OF 'SWORD.SUPER_USER'(COST=2,CARD=2794,BYTES=27940)
INDEX(RANGE SCAN)OF 'SWORD.IDX_SUPER_USER_CN'(NON-UNIQUE)(COST=1,CARD=2794,BYTES=)
這個(gè)查詢耗費(fèi)的時(shí)間較短,才20分鐘,性能比較好。運(yùn)行后的信息如下:
COUNT(A.CHANNEL||B.USER_CLASS)------------------------------
1186387
Elapsed: 00:20:1208.87
Execution Plan---------------------------
0
SELECT STATEMENT Optimizer=CHOOSE(Cost=109893304 Card=1 Bytes=21)
0
SORT(AGGREGATE)
NESTED LOOPS(Cost=109893304 Card=1213745 Bytes=25488645)
TABLE ACCESS(FULL)OF 'SWD_BILLDETAIL'(Cost=165412 Card=54863946 Bytes=603503406)
TABLE ACCESS(BY INDEX ROWID)OF 'SUPER_USER'(Cost=2Card=2794 Bytes=27940)
INDEX(RANGE SCAN)OF 'IDX_SUPER_USER_CN'(NON-UNIQUE)(Cost=1 Card=2794)
Statistics---------------------------
0 recursive calls
8823 db block gets
56650250 consistent gets
1413250 physical reads
0 redo size
316 bytes sent via SQL*Net to client
421 bytes received via SQL*Net from client SQL*Net roundtrips to/from client sorts(memory)
0 sorts(disk)rows processed
總結(jié):
因?yàn)樯蟽蓚€(gè)查詢都是采用nested loop循環(huán),這時(shí)采用哪個(gè)表作為driving table就很重要。在第一個(gè)sql中,小表(SUPER_USER)作為driving table,符合oracle優(yōu)化的建議,但是由于SWD_BILLDETAIL表中cn列的值有很多重復(fù)的,這樣對于SUPER_USER中的每一行,都會(huì)在SWD_BILLDETAIL中有很多行,利用索引查詢出這些行的rowid很快,但是再利用這些rowid去查詢SWD_BILLDETAIL表中的user_class列的值,就比較慢了。原因是這些rowid是隨機(jī)的,而且該表比較大,不可能緩存到內(nèi)存,所以幾乎每次按照rowid查詢都需要讀物理磁盤,這就是該執(zhí)行計(jì)劃比較慢的真正原因。從結(jié)果可以得到驗(yàn)證:查詢出1186387行,需要利用rowid從SWD_BILLDETAIL表中讀取1186387次,而且大部分為從硬盤上讀取。
反其道而行之,利用大表(SWD_BILLDETAIL)作為driving表,這樣大表只需要做一次全表掃描(而且會(huì)使用多塊讀功能,每次物理I/O都會(huì)讀取幾個(gè)oracle數(shù)據(jù)塊,從而一次讀取很多行,加快了執(zhí)行效率),對于讀出的每一行,都與SUPER_USER中的行進(jìn)行匹配,因?yàn)镾UPER_USER表很小,所以可以全部放到內(nèi)存中,這樣匹配操作就極快,所以該sql執(zhí)行的時(shí)間與SWD_BILLDETAIL表全表掃描的時(shí)間差不多(SWD_BILLDETAIL全表用11分鐘,而此查詢用20分鐘)。
另外:如果SWD_BILLDETAIL表中cn列的值唯一,則第一個(gè)sql執(zhí)行計(jì)劃執(zhí)行的結(jié)果或許也會(huì)不錯(cuò)。如果SUPER_USER表也很大,如500萬行,則第2個(gè)sql執(zhí)行計(jì)劃執(zhí)行的結(jié)果反而又可能會(huì)差。其實(shí),如果SUPER_USER表很小,則第2個(gè)sql語句的執(zhí)行計(jì)劃如果不利用SUPER_USER表的索引,查詢或許會(huì)更快一些,我沒有對此進(jìn)行測試。
所以在進(jìn)行性能調(diào)整時(shí),具體問題要具體分析,沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)。
[center]第6章 其它注意事項(xiàng)[/center]
1.不要認(rèn)為將optimizer_mode參數(shù)設(shè)為rule,就認(rèn)為所有的語句都使用基于規(guī)則的優(yōu)化器
不管optimizer_mode參數(shù)如何設(shè)置,只要滿足下面3個(gè)條件,就一定使用CBO。
1)如果使用Index Only Tables(IOTs), 自動(dòng)使用CBO.2)Oracle 7.3以后,如果表上的Paralle degree option設(shè)為>1,則自動(dòng)使用CBO, 而不管是否用rule hints.3)除rlue以外的任何hints都將導(dǎo)致自動(dòng)使用CBO來執(zhí)行語句
總結(jié)一下,一個(gè)語句在運(yùn)行時(shí)到底使用何種優(yōu)化器可以從下面的表格中識(shí)別出來,從上到下看你的語句到底是否滿足description列中描述的條件:
Description
對象是否被分析
優(yōu)化器的類型
~~~~~~~~~~~
~~~~~~~~~~~~
~~~~~~~~~
Non-RBO Object(Eg:IOT)
n/a
#1
Parallelism > 1
n/a
#1
RULE hint
n/a
RULE
ALL_ROWS hint
n/a
ALL_ROWS
FIRST_ROWS hint
n/a
FIRST_ROWS
*Other Hint
n/a
#1
OPTIMIZER_GOAL=RULE
n/a
RULE
OPTIMIZER_GOAL=ALL_ROWS
n/a
ALL_ROWS
OPTIMIZER_GOAL=FIRST_ROWS
n/a
FIRST_ROWS
OPTIMIZER_GOAL=CHOOSE
NO
RULE
OPTIMIZER_GOAL=CHOOSE
YES
ALL_ROWS
#1 表示除非OPTIMIZER_GOAL 被設(shè)置為FIRST_ROWS,否則將使用ALL_ROWS。在PL/SQL中,則一直是使用ALL_ROWS
*Other Hint 表示是指除RULE、ALL_ROWS 和FIRST_ROWS以外的其它提示
2)當(dāng)CBO選擇了一個(gè)次優(yōu)化的執(zhí)行計(jì)劃時(shí), 不要同CBO過意不去, 先采取如下措施: a)檢查是否在表與索引上又最新的統(tǒng)計(jì)數(shù)據(jù)
b)對所有的數(shù)據(jù)進(jìn)行分析,而不是只分析一部分?jǐn)?shù)據(jù)
c)檢查是否引用的數(shù)據(jù)字典表,在oracle 10G之前,缺省情況下是不對數(shù)據(jù)字典表進(jìn)行分析的。
d)試試RBO優(yōu)化器,看語句執(zhí)行的效率如何,有時(shí)RBO能比CBO產(chǎn)生的更好的執(zhí)行計(jì)劃
e)如果還不行,跟蹤該語句的執(zhí)行,生成trace信息,然后用tkprof格式化trace信息,這樣可以得到全面的供優(yōu)化的信息。
3)假如利用附錄的方法對另一個(gè)會(huì)話進(jìn)行trace,則該會(huì)話應(yīng)該為專用連接
4)不要認(rèn)為綁定變量(bind variables)的缺點(diǎn)只有書寫麻煩,而優(yōu)點(diǎn)多多,實(shí)際上使用綁定變量雖然避免了重復(fù)parse,但是它導(dǎo)致優(yōu)化器不能使用數(shù)據(jù)庫中的列統(tǒng)計(jì),從而選擇了較差的執(zhí)行計(jì)劃。而使用硬編碼的SQL則可以使用列統(tǒng)計(jì)。當(dāng)然隨著CBO功能的越來越強(qiáng),這種情況會(huì)得到改善。目前就已經(jīng)實(shí)現(xiàn)了在第一次運(yùn)行綁定變量的sql語句時(shí),考慮列統(tǒng)計(jì)。
5)如果一個(gè)row source 超過10000行數(shù)據(jù),則可以被認(rèn)為大row source
6)有(+)的表不是driving table,注意:如果有外聯(lián)接,而且order hint指定的順序與外聯(lián)結(jié)決定的順序沖突,則忽略order hint
7)影響CBO選擇execution plan的初始化參數(shù):
這些參數(shù)會(huì)影響cost值 ALWAYS_ANTI_JOIN B_TREE_BITMAP_PLANS COMPLEX_VIEW_MERGING DB_FILE_MULTIBLOCK_READ_COUNT FAST_FULL_SCAN_ENABLED HASH_AREA_SIZE HASH_JOIN_ENABLED HASH_MULTIBLOCK_IO_COUNT OPTIMIZER_FEATURES_ENABLE OPTIMIZER_INDEX_CACHING OPTIMIZER_INDEX_COST_ADJ OPTIMIZER_MODE> / GOAL OPTIMIZER_PERCENT_PARALLEL OPTIMIZER_SEARCH_LIMIT PARTITION_VIEW_ENABLED PUSH_JOIN_PREDICATE SORT_AREA_SIZE SORT_DIRECT_WRITES SORT_WRITE_BUFFER_SIZE STAR_TRANSFORMATION_ENABLED V733_PLANS_ENABLED CURSOR_SHARING
第二篇:通過分析SQL語句的執(zhí)行計(jì)劃優(yōu)化SQL(總結(jié))
通過分析SQL語句的執(zhí)行計(jì)劃優(yōu)化SQL(總結(jié))
做DBA快7年了,中間感悟很多。在DBA的日常工作中,調(diào)整個(gè)別性能較差的SQL語句時(shí)一項(xiàng)富有挑戰(zhàn)性的工
作。其中的關(guān)鍵在于如何得到SQL語句的執(zhí)行計(jì)劃和如何從SQL語句的執(zhí)行計(jì)劃中發(fā)現(xiàn)問題??偸窍雽⑷粘?/p>
經(jīng)驗(yàn)的點(diǎn)點(diǎn)滴滴總結(jié)一下,但是直到最近才下定決心,總共花了3個(gè)周末時(shí)間,才將其整理成冊,便于自
己日常工作。不好意思獨(dú)享,所以將其貼出來。
修改日志:
2006.02.20:
根據(jù)網(wǎng)友反饋已做部分修改,但pdf文件沒有做修改,修改部分在“如何產(chǎn)生執(zhí)行計(jì)劃”關(guān)于set
autotraceonly的介紹部分
第一章、第2章 并不是很重要,是自己的一些想法,關(guān)于如何做一個(gè)穩(wěn)定、高效的應(yīng)用系統(tǒng)的一些想法。
第三章以后都是比較重要的。
附錄的內(nèi)容也是比較重要的。我常用該部分的內(nèi)容。
前言
本文檔主要介紹與SQL調(diào)整有關(guān)的內(nèi)容,內(nèi)容涉及多個(gè)方面:SQL語句執(zhí)行的過程、ORACLE優(yōu)化器,表之間 的關(guān)聯(lián),如何得到SQL執(zhí)行計(jì)劃,如何分析執(zhí)行計(jì)劃等內(nèi)容,從而由淺到深的方式了解SQL優(yōu)化的過程,使
大家逐步步入SQL調(diào)整之門,然后你將發(fā)現(xiàn)??。
該文檔的不當(dāng)之處,敬請指出,以便進(jìn)一步改正。請將其發(fā)往我的信箱:xu_yu_jin2000@sina.com。
如果引用本文的內(nèi)容,請著名出處
目錄
第1章 性能調(diào)整綜述 第2章 有效的應(yīng)用設(shè)計(jì)
第3章 SQL語句處理的過程 第4章 ORACLE的優(yōu)化器 第5章 ORACLE的執(zhí)行計(jì)劃 訪問路徑(方法)--access path 表之間的連接
如何產(chǎn)生執(zhí)行計(jì)劃 如何分析執(zhí)行計(jì)劃
如何干預(yù)執(zhí)行計(jì)劃-合并連接(Sort Merge Join(SMJ))嵌套循環(huán)(Nested Loops(NL))哈希連接(Hash Join)
排序-合并連接(Sort Merge Join, SMJ):
a)對于非等值連接,這種連接方式的效率是比較高的。b)如果在關(guān)聯(lián)的列上都有索引,效果更好。c)對于將2個(gè)較大的row source做連接,該連接方法比NL連接要好一些。d)但是如果sort merge返回的row source過大,則又會(huì)導(dǎo)致使用過多的rowid在表中查詢數(shù)據(jù)時(shí),數(shù)據(jù)庫
性能下降,因?yàn)檫^多的I/O。
嵌套循環(huán)(Nested Loops, NL):
a)如果driving row source(外部表)比較小,并且在inner row source(內(nèi)部表)上 有唯一索引,或有高選擇性非唯一索引時(shí),使用這種方法可以得到較好的效率。b)NESTED LOOPS有其它連接方法沒有的的一個(gè)優(yōu)點(diǎn)是:可以先返回已經(jīng) 連接的行,而不必等待所有的連接操作處理完才返回?cái)?shù)據(jù),這可以實(shí)現(xiàn)快速的響應(yīng)時(shí)間。哈希連接(Hash Join, HJ):
a)這種方法是在oracle7后來引入的,使用了比較先進(jìn)的連接理論,一般來說,其效率應(yīng)該好于其它2種連接,但是這種連接只能用在 CBO優(yōu)化器中,而且需要設(shè)置合適的hash_area_size參數(shù),才能取得較好的性能。
b)在2個(gè)較大的row source之間連接時(shí)會(huì)取得相對較好的效率,在一個(gè) row source較小時(shí)則能取得更好的效率。c)只能用于等值連接中
笛卡兒乘積(Cartesian Product)當(dāng)兩個(gè)row source做連接,但是它們之間沒有關(guān)聯(lián)條件時(shí),就會(huì)在兩個(gè)row source中做笛卡兒乘積,這通
常由編寫代碼疏漏造成(即程序員忘了寫關(guān)聯(lián)條件)。笛卡爾乘積是一個(gè)表的每一行依次與另一個(gè)表中的所
有行匹配。在特殊情況下我們可以使用笛卡兒乘積,如在星形連接中,除此之外,我們要盡量使用笛卡兒
乘積,否則,自己想結(jié)果是什么吧!
注意在下面的語句中,在2個(gè)表之間沒有連接。SQL> explain plan for select emp.deptno,dept,deptno from emp,dept
Query Plan------------------------------SLECT STATEMENT [CHOOSE] Cost=5 MERGE JOIN CARTESIAN TABLE ACCESS FULL DEPT SORT JOIN TABLE ACCESS FULL EMP
CARTESIAN關(guān)鍵字指出了在2個(gè)表之間做笛卡爾乘積。假如表emp有n行,dept表有m行,笛卡爾乘積的結(jié)果
就是得到n * m行結(jié)果。
7樓
06-01-12 17:48 [ 大 中 小 ]
SunnyXu 一般會(huì)員
注冊日期: 2004 Nov 來自:
技術(shù)貼數(shù):38 精華貼數(shù):1 論壇積分:267 論壇排名:9743 論壇徽章:0
[center]如何產(chǎn)生執(zhí)行計(jì)劃[/center]
要為一個(gè)語句生成執(zhí)行計(jì)劃,可以有3種方法: 1).最簡單的辦法
Sql> set autotrace on Sql> select * from dual;執(zhí)行完語句后,會(huì)顯示explain plan 與 統(tǒng)計(jì)信息。這個(gè)語句的優(yōu)點(diǎn)就是它的缺點(diǎn),這樣在用該方法查看執(zhí)行時(shí)間較長的sql語句時(shí),需要等待該語句執(zhí)行成
功后,才返回執(zhí)行計(jì)劃,使優(yōu)化的周期大大增長。
如果想得到執(zhí)行計(jì)劃,而不想看到語句產(chǎn)生的數(shù)據(jù),可以采用: Sql> set autotrace traceonly 這樣還是會(huì)執(zhí)行語句。它比set autotrace on的優(yōu)點(diǎn)是:不會(huì)顯示出查詢的數(shù)據(jù),但是還是會(huì)將數(shù)據(jù)輸出
到客戶端,這樣當(dāng)語句查詢的數(shù)據(jù)比較多時(shí),語句執(zhí)行將會(huì)花費(fèi)大量的時(shí)間,因?yàn)楹艽蟛糠謺r(shí)間用在將數(shù)
據(jù)從數(shù)據(jù)庫傳到客戶端上了。我一般不用這種方法。
Sql> set autotrace traceonly explain 如同用explain plan命令。對于select 語句,不會(huì)執(zhí)行select語句,而只是產(chǎn)生執(zhí)行計(jì)劃。但是對于dml
語句,還是會(huì)執(zhí)行語句,不同版本的數(shù)據(jù)庫可能會(huì)有小的差別。這樣在優(yōu)化執(zhí)行時(shí)間較長的select語句時(shí),大大減少了優(yōu)化時(shí)間,解決了“set autotrace on”與“set autotrace traceonly”命令優(yōu)化時(shí)執(zhí)行
時(shí)間長的問題,但同時(shí)帶來的問題是:不會(huì)產(chǎn)生Statistics數(shù)據(jù),而通過tatistics數(shù)據(jù)的物理I/O的次數(shù),我們可以簡單的判斷語句執(zhí)行效率的優(yōu)劣。
如果執(zhí)行該語句時(shí)遇到錯(cuò)誤,解決方法為:(1)在要分析的用戶下:
Sqlplus > @ ?rdbmsadminutlxplan.sql(2)用sys用戶登陸
Sqlplus > @ ?sqlplusadminplustrce.sql Sqlplus > grant plustrace to user_name;-> A)--> C。如果數(shù)據(jù)庫是基于代價(jià)的優(yōu)化器,它會(huì)利用計(jì)
算出的代價(jià)來決定合適的驅(qū)動(dòng)表與合適的連接順序。一般來說,CBO都會(huì)選擇正確的連接順序,如果CBO選
擇了比較差的連接順序,我們還可以使用ORACLE提供的hints來讓CBO采用正確的連接順序。如下所示:
select /*+ ordered */ A.col4 from B,A,C where B.col3 = 10 and A.col1 = B.col1 and A.col2 = C.col2 and C.col3 = 5
既然選擇正確的驅(qū)動(dòng)表這么重要,那么讓我們來看一下執(zhí)行計(jì)劃,到底各個(gè)表之間是如何關(guān)聯(lián)的,從而得
到執(zhí)行計(jì)劃中哪個(gè)表應(yīng)該為驅(qū)動(dòng)表:
在執(zhí)行計(jì)劃中,需要知道哪個(gè)操作是先執(zhí)行的,哪個(gè)操作是后執(zhí)行的,這對于判斷哪個(gè)表為驅(qū)動(dòng)表有用處
。判斷之前,如果對表的訪問是通過rowid,且該rowid的值是從索引掃描中得來得,則將該索引掃描先從
執(zhí)行計(jì)劃中暫時(shí)去掉。然后在執(zhí)行計(jì)劃剩下的部分中,判斷執(zhí)行順序的指導(dǎo)原則就是:最右、最上的操作
先執(zhí)行。具體解釋如下:
得到去除妨礙判斷的索引掃描后的執(zhí)行計(jì)劃: Execution Plan---------------------------0 SELECT STATEMENT Optimizer=CHOOSE 1 0 MERGE JOIN 2 1 SORT(JOIN)3 2 NESTED LOOPS 4 3 TABLE ACCESS(FULL)OF 'B' 5 3 TABLE ACCESS(BY INDEX ROWID)OF 'A' 7 1 SORT(JOIN)8 7 TABLE ACCESS(FULL)OF 'C' 看執(zhí)行計(jì)劃的第3列,即字母部分,每列值的左面有空格作為縮進(jìn)字符。在該列值左邊的空格越多,說明
該列值的縮進(jìn)越多,該列值也越靠右。如上面的執(zhí)行計(jì)劃所示:第一列值為6的行的縮進(jìn)最多,即該行最
靠右;第一列值為4、5的行的縮進(jìn)一樣,其靠右的程度也一樣,但是第一列值為4的行比第一列值為5的行
靠上;談?wù)撋舷玛P(guān)系時(shí),只對連續(xù)的、縮進(jìn)一致的行有效。
從這個(gè)圖中我們可以看到,對于NESTED LOOPS部分,最右、最上的操作是TABLE ACCESS(FULL)OF 'B',所以這一操作先執(zhí)行,所以該操作對應(yīng)的B表為第一個(gè)驅(qū)動(dòng)表(外部表),自然,A表就為內(nèi)部表了。從圖中
還可以看出,B與A表做嵌套循環(huán)后生成了新的row source,對該row source進(jìn)行來排序后,與C表對應(yīng)的
排序了的row source(應(yīng)用了C.col3 = 5限制條件)進(jìn)行MSJ連接操作。所以從上面可以得出如下事實(shí):B表
先與A表做嵌套循環(huán),然后將生成的row source與C表做排序—合并連接。
通過分析上面的執(zhí)行計(jì)劃,我們不能說C表一定在B、A表之后才被讀取,事實(shí)上,B表有可能與C表同時(shí)被
讀入內(nèi)存,因?yàn)閷⒈碇械臄?shù)據(jù)讀入內(nèi)存的操作可能為并行的。事實(shí)上許多操作可能為交叉進(jìn)行的,因?yàn)?/p>
第三篇:網(wǎng)站SEO優(yōu)化每天執(zhí)行計(jì)劃
個(gè)人執(zhí)行計(jì)劃
網(wǎng)站排名對于SEO人員來說重中之重,是SEO行業(yè)都為之關(guān)注的話題。對于企業(yè)站來說排名無非也就是所謂的外鏈與內(nèi)容。執(zhí)行力更是SEO中占據(jù)重要的步驟,有好的策略沒有執(zhí)行力也是空談。今天在這里和大家分享個(gè)人在優(yōu)化網(wǎng)站的執(zhí)行計(jì)劃,如果適合各位所優(yōu)化網(wǎng)站,那么的就非常的高興。反之,希望各位不要取笑。
一、網(wǎng)站內(nèi)容:
每網(wǎng)站一篇原創(chuàng)文章。將今日寫的文章依次收藏到社會(huì)化書簽中,一是可以加快文章的收錄,二是外鏈的一種。這里推薦大家?guī)讉€(gè)社會(huì)化書簽:百度收藏、好網(wǎng)角收藏夾、寶盒網(wǎng)、樂收網(wǎng)絡(luò)收藏夾。
二、友情鏈接
每天堅(jiān)持友鏈2-3個(gè),最好是相關(guān)性的。友情鏈接的交換,看的不是收錄多少,pr值多少。最關(guān)鍵是網(wǎng)站的目標(biāo)關(guān)鍵詞是否在首頁,網(wǎng)站所帶來的流量是多少。友情鏈接重點(diǎn)不是量,質(zhì)才是我們追求的。
三、行業(yè)商鋪:
行業(yè)商鋪的權(quán)重很高,大家可以多搜集一些商鋪,可以找一些行業(yè)性的商鋪。商鋪下我們基本可能做以下形式的鏈接:商鋪友情鏈接、供求信息、求購信息。這里推薦大家一些好的商鋪:行業(yè)中心、環(huán)球廚衛(wèi)網(wǎng)、百業(yè)網(wǎng)、一呼百應(yīng)等等。
四、論壇:
論壇是我們常見做的鏈接形式之一,推薦大家做論壇方法:行業(yè)相關(guān)論壇、權(quán)重較高的門戶網(wǎng)站論壇廣告發(fā)布區(qū)。推薦:搜房論壇、慧聰論壇、落伍者論壇、19樓等等。
五、分類信息與網(wǎng)站目錄:
對于新上線站來說分類信息與網(wǎng)站目錄是個(gè)不錯(cuò)的選擇,可以讓百度蜘蛛快速度收錄網(wǎng)站,但有一些目錄網(wǎng)站對于審核的要求過高,新站初期可以提交一些審核不嚴(yán)格的,后期提交那些權(quán)重高的目錄站。我們常見的分類信息站有:58同城、趕集網(wǎng)、百姓網(wǎng)。權(quán)重高目錄網(wǎng)站:啟發(fā)網(wǎng)站目錄、第一摘網(wǎng)站分類目錄、中國開放網(wǎng)頁目錄.以上的執(zhí)行方式比較適合企業(yè)網(wǎng)站的優(yōu)化流程,當(dāng)然了每個(gè)人執(zhí)行方式都不一樣。這里只是說說自己的看法,希望能幫助各位站長。也希望你們能分享自己的一些經(jīng)驗(yàn),加大一起相互學(xué)習(xí)。
/
第四篇:SQL語句性能優(yōu)化
我也做了很長時(shí)間醫(yī)療軟件,也寫過不少sql優(yōu)化,沒有詳細(xì)記錄下來,個(gè)人感覺下面轉(zhuǎn)載的更符合醫(yī)院醫(yī)療軟件實(shí)際業(yè)務(wù),很認(rèn)可大部分所寫的原則,固轉(zhuǎn)載過來,以作借鑒。軟件的根本還是在于更細(xì)更精,在于從客戶的實(shí)際使用考慮問題。
性能優(yōu)化原則1:永遠(yuǎn)避免困境
利用緩存把字典數(shù)據(jù)取到中間服務(wù)器或是客戶端替代直接sql查詢,如,門診醫(yī)生站把字典下載到客戶端,減少執(zhí)行次數(shù)。
一次性取數(shù)據(jù)到客戶端,然后再逐條處理,而不是分次取數(shù)據(jù),處理好一條數(shù)據(jù)再取下一條再處理。例:門診收費(fèi)取hjcfmxk例子,原來是一張?zhí)幏綏l明細(xì)都查詢一次,查詢后再處理,現(xiàn)改為一次把所有明細(xì)都取過來,然后一條條處理
盡量減少光標(biāo),看能不能用臨時(shí)表
性能優(yōu)化原則2:kiss原則
對于where 條件中的左邊可以利用索引的字段Keep it simple stupid,左邊盡量避免用函數(shù)(substring,isnull,upper,lower),參加計(jì)算+,-*/
例子1:select * from ZY_BRFYMXK where substring(zxrq,1,8)='20081212‘
select * from ZY_BRFYMXK where zxrq between '2008121200' and '2008121224' 例子2:
select * from zy_detail_charge where SUBSTRING(patient_id,1,10)=
substring('000005090600',1,10)這句耗時(shí)30秒以上
select * from zy_detail_charge where patient_id like substring('000005090600',1,10)+'%' 這句耗時(shí)2秒以內(nèi)
性能優(yōu)化原則3:盡可能利用到索引
例:select * from ZY_BRFYMXK a(nolock),VW_LSYZK b(nolock)where a.syxh=3 and a.yzxh=b.xh and a.fylb=0
select * from ZY_BRFYMXK a(nolock),VW_LSYZK b(nolock)where a.syxh=3 and a.yzxh=b.xh and a.fylb=0 and b.syxh=3
性能優(yōu)化原則4:or,避而遠(yuǎn)之
對于索引字段盡力避免用or,普通字段可以用or,解決要么分解成多個(gè)sql,要么用業(yè)務(wù)規(guī)則避免,例:declare @rq1 ut_rq16,@syxh ut_syxh
select @rq1='20081201'
select @syxh=157
性能優(yōu)化原則5:避免大批量數(shù)據(jù)取到前臺(tái)
例: select * from ZY_BRSYK cyrq between ‘20080901’ and ‘20081201‘,對于大醫(yī)院每天100多人,90天是9000條數(shù)據(jù)
性能優(yōu)化原則6:事務(wù),盡可能的短吧
所有計(jì)算、對臨時(shí)表的更新都應(yīng)但放在事務(wù)外,事務(wù)中最好只有更新和插入正式表操作.因?yàn)槭聞?wù)中產(chǎn)生的鎖只有在commit tran是才會(huì)釋放。
性能優(yōu)化原則7:熱表,留在最后吧
熱表是頻繁調(diào)用的表。如:sf_mzcfk,zy_brfymxk,bq_fyqqk.對于熱表盡量放在事務(wù)最后:這樣鎖的時(shí)間短。大家都堅(jiān)持這樣,死鎖的可能性就小。如果都是熱表各個(gè)存儲(chǔ)過程更新表的順序應(yīng)當(dāng)一樣這樣可以避免死鎖
性能優(yōu)化原則8:創(chuàng)建臨時(shí)表一定要避免在事務(wù)中作
如create #tempXX(…)
Select * into #tempXX from …
因?yàn)閯?chuàng)建臨時(shí)表會(huì)鎖tempdb的系統(tǒng)表
例:生成#temp1放在事務(wù)內(nèi)外,用sp_lock2 ‘’觀察結(jié)果
if object_id('tempdb..#temp1','U')is not null
drop table #temp1
begin tran
select * into #temp1 from ZY_BRSYK where ryrq>'20080901‘
select * from #temp1
waitfor delay '00:00:10'
commit
性能優(yōu)化原則9:大的報(bào)表查詢避免與正常業(yè)務(wù)碰撞
如果沒有查詢服務(wù)器,那要在存儲(chǔ)過程中限制不能操作加上如:
declare @rq1 ut_rq16,@rq2 ut_rq16,@now ut_rq16
select @rq1=convert(varchar(8),getdate(),112)+'08:00:00'
select @rq1=convert(varchar(8),getdate(),112)+'11:30:00'
select @now=convert(char(8),getdate(),112)+convert(char(8),getdate(),8)
if @now>@rq1 and @now<@rq2
begin
select '上午繁忙時(shí)間段不能作此查詢'
return
end
性能優(yōu)化原則10:存儲(chǔ)過程避免大的if…else…
這個(gè)常出項(xiàng)在業(yè)務(wù)相同表不同的存儲(chǔ)過程中,因?yàn)檫@樣常到if …else …原來醫(yī)技接口中很多這種存儲(chǔ)過程,當(dāng)時(shí)把門診住院業(yè)務(wù)放在一個(gè)存儲(chǔ)過程中。這樣最大的問題是sql server會(huì)根據(jù)sql語句來compile存儲(chǔ),這個(gè)過程會(huì)生成優(yōu)化計(jì)劃,決定用那個(gè)索引。如果存儲(chǔ)過程用到門診表compile一下,到用到住院表是發(fā)現(xiàn)不對,又會(huì)compile一下,這樣不停compile.compile很號(hào)時(shí)間要1-2秒,而且一個(gè)存儲(chǔ)過成在compile是,所有調(diào)用這個(gè)存儲(chǔ)過程的進(jìn)程都要在排隊(duì)等候,因?yàn)樗麜?huì)獨(dú)占鎖這個(gè)存儲(chǔ)過程
例:usp_yjjk_getwzxxm_old.sql,后改為:
usp_yjjk_getwzxxm.sql, usp_yjjk_getwzxxm_mz.sql,usp_yjjk_getwzxxm_zy.sql
性能優(yōu)化原則11:進(jìn)攻是最好的防守
在普通編程語句對于數(shù)據(jù)校驗(yàn)總是用防守辦法先判斷,后再作相應(yīng)處理。而在sql中先處理再判斷性能會(huì)好很多。
--更新藥品庫存。
If exists(select 1 from YK_YKZKC WHERE idm=100 and kcsl>50)
begin
update YK_YKZKC set kcsl=kcsl-50 where idm=100
End
Else begin
rollback tran
Select ‘F庫存不夠’
return
end
--改為
update YK_YKZKC set kcsl=kcsl-50 where idm=100 and kcsl>50
If @@rowcount<=0
Begin
Rollbakc tran
Select ‘F庫存不夠’
end
--取未執(zhí)行的醫(yī)技項(xiàng)目,日表沒有數(shù)據(jù)就到年表中查找
if exists(select a.* from SF_MZCFK a(nolock),SF_CFMXK b(nolock)
begin
select a.* into #temp1 from SF_MZCFK a(nolock),SF_CFMXK b(nolock)
end
else begin
select a.* into #temp1 from SF_NMZCFK a(nolock),SF_NCFMXK b(nolock)
end
--改為
Insert into #temp1 select a.*
from SF_MZCFK a(nolock),SF_CFMXK b(nolock)
If @@rowcount=0
Begin
Insert into #temp1 select a.*
from SF_NMZCFK a(nolock),SF_NCFMXK b(nolock)
end
性能優(yōu)化原則12:trig最后的手段
Trig(觸發(fā)器)的處理的處理機(jī)制是滿足條件時(shí)就會(huì)在源語句后面加上trig中的代碼進(jìn)行執(zhí)行。
它有兩個(gè)致命的弊端:(1)不清楚有trig的人會(huì)對于執(zhí)行結(jié)果感到迷惑。如常有在插入一張表如果主鍵是indentity的值常取用select @@identity。但如是有trig,tring中有表插入操作,這時(shí)的@@identity可能就不是想要的值。(2)trig會(huì)束縛選擇。如:有一套單據(jù)主表和明細(xì)表,當(dāng)明細(xì)表的金額更新時(shí),要同步主表的金額,當(dāng)程序是一條條更新明細(xì)時(shí)用trig的作法是每當(dāng)更新一條明細(xì)記錄時(shí)都算一處所有明細(xì)表的總金額,再去更新主表的金額。這樣有多少條明細(xì)就要算多少次,好的作法是不要trig,直接在sql語句中明細(xì)更新完明后,一次性算出總金額每條單據(jù)的總金額,再更新主表的金額。
對于trig如果有其他手段就一定要避免用trig.性能優(yōu)化原則13:用戶說好才是真的好
1)有時(shí)sql語句性能難以優(yōu)化,但用戶對于系統(tǒng)響應(yīng)速度還是不滿意。這時(shí)可以從業(yè)務(wù)分析處理。
如:我們退費(fèi)模塊錄入發(fā)票號(hào)原來是用fph like ‘XXX%’。用戶報(bào)怨慢,后來改為先用fph=‘XXX’來查,如查不到再fph like ‘XXX%’。這樣在絕大部情況下速度都非???,同時(shí)也滿足小部分情況下模糊查詢的需求。
如:我們的程序要查日表和年表。如果通過日表union表視圖去查會(huì)非常慢,性能也難以優(yōu)化。程序改為普通情況下不查年表,用戶勾上年表標(biāo)志時(shí)才查年表。
(2)查詢統(tǒng)計(jì)很多數(shù)據(jù)時(shí)間比較長,就以查詢完一部分?jǐn)?shù)據(jù)后可以顯示這部分?jǐn)?shù)據(jù)或是用提示,這樣用戶清楚系統(tǒng)在作事情也知道大概進(jìn)度。這樣情緒上會(huì)好很多。
(3)查詢模塊常有一進(jìn)入時(shí)也默認(rèn)一個(gè)查詢,如果性能好,查詢又合用戶心意,這種設(shè)計(jì)非常好,如果性能不好,那就不是好的設(shè)計(jì)。用戶對于進(jìn)入都困難的模塊是沒有好感的。
(4)有戶的耐心與查詢出的記錄成正比。用戶痛恨等待很久卻沒有查詢出記錄。
對于非常慢的查詢,如果有些子查詢非常快可以先作這樣查詢以避免查詢很久卻沒有數(shù)據(jù)出來的情況。如:按病歷號(hào)查在院病人所有費(fèi)有明細(xì),可以先查一下這個(gè)病歷是不是有對應(yīng)病人。
實(shí)戰(zhàn)技巧1:用exists、in代替distinct
Distinct實(shí)際上是先收集再刪除這樣兩步都耗資源。
Exists,in會(huì)隱式過濾掉重復(fù)的記錄
例查自2009年以來有金額大于100的藥品的病人
select distinct a.blh,a.hzxm from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock)where a.patid=b.patid and b.syxh=c.syxh and c.zxrq>'2009' and c.zje>100--改為
select a.blh,a.hzxm from ZY_BRXXK a where exists(select 1 from ZY_BRSYK
b(nolock),ZY_BRFYMXK c(nolock)where a.patid=b.patid and b.syxh=c.syxh and
c.zxrq>'2009'and c.zje>100)
實(shí)戰(zhàn)技巧2:縮短union
select …from A,B,C,D,E1
where(E1的條件)
and(其他表聯(lián)接條件)
union
select …from A,B,C,D,E2
where(E2的條件)
and(其他表接接條件)
改為
select …from A,B,C,D,(select...from E1where(E1條件)
union
select …from E2where(E2條件))E where(其他條件)
當(dāng)涉及ABCD表部分耗資源而E1,E2不耗資源時(shí)是這樣,如果反過來則改后的性能不一定好。查2009年4月后入院的在院病人在2905病區(qū)發(fā)生的所有費(fèi)用明細(xì)
select a.hzxm,b.cyrq,d.ypmc,d.ypgg,c.ypsl/c.dwxs ypsl, c.ypdw
select a.hzxm,b.cyrq,d.ypmc,d.ypgg,c.ypsl/c.dwxs ypsl, c.ypdw
from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock),YK_YPCDMLK d where a.patid=b.patid and b.ryrq>'200904' and b.brzt not in(3,8,9)and b.syxh=c.syxh and c.bqdm='2905' and c.idm=d.idm
union all
select a.hzxm,b.cyrq,d.name,d.xmgg,c.ypsl/c.dwxs ypsl, c.ypdw
from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock),YY_SFXXMK d where a.patid=b.patid and b.ryrq>'200904' and b.brzt not in(3,8,9)and b.syxh=c.syxh and c.bqdm='2905' and c.ypdm=d.id and c.idm=0
--改為
select a.hzxm,b.cyrq,d.ypmc,d.ypgg,c.ypsl/c.dwxs ypsl, c.ypdw
from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock),(select ypmc,ypgg,ypdm,idm idm from YK_YPCDMLK union select name,xmgg,id,0 from YY_SFXXMK)d
where a.patid=b.patid and b.ryrq>'200904' and b.brzt not in(3,8,9)and b.syxh=c.syxh and c.bqdm='2905' and c.idm=d.idm and c.ypdm=d.ypdm
實(shí)戰(zhàn)技巧3:合并sql
把表和where條件類似的兩個(gè)或是多個(gè)sql合并為一個(gè)sql.--查2009年以后的普通、急診、專家掛號(hào)人數(shù)
declare @ptghs int,@jzghs int,@zjghs int
select @ptghs=0,@jzghs=0,@zjghs=0
select @ptghs=count(*)from GH_GHZDK where ghrq>'2009' and ghlb=0
select @jzghs=count(*)from GH_GHZDK where ghrq>'2009' and ghlb=1
select @zjghs=count(*)from GH_GHZDK where ghrq>'2009' and ghlb=2
select @ptghs,@jzghs,@zjghs
--改為
select @ptghs=0,@jzghs=0,@zjghs=0
select @ptghs=sum(case when ghlb=0 then 1 else 0 end),@jzghs=sum(case when ghlb=1 then 1 else 0 end), @zjghs=sum(case when ghlb=2 then 1 else 0 end)
from GH_GHZDK where ghrq>'2009'
select @ptghs,@jzghs,@zjghs
實(shí)戰(zhàn)技巧4:去掉游標(biāo)
把游標(biāo)當(dāng)作編程語言的for,do---while的方式,很多情況下都可以去掉,如果光標(biāo)中間sql語句只有一條一般都是可以去掉光標(biāo)改為一句sql。
--查當(dāng)天出院出院日期在2009年4月1到9日間病人的zfdj,zfje置為0
declare @syxh ut_syxh
declare cur1 cursor for select syxh from ZY_BRSYK where cyrq>='20090401' and cyrq<'20090410'
open cur1
fetch cur1 into @syxh
while @@fetch_status=0
begin
fetch cur1 into @syxh
end
close cur1
deallocate cur1
--改為
update ZY_BRFYMXK set zfdj=0,zfje=0
from ZY_BRFYMXK a,ZY_BRSYK b
where a.syxh=b.syxh and b.cyrq>='20090401' and b.cyrq<'20090410'
實(shí)戰(zhàn)技巧5:取代count
利用內(nèi)部函數(shù)代替
declare @count int
select * into #tmep1 from ZY_BRFYMXK WHERE zxrq>'200901'
select @count=@@rowcount—可以得到count值
select @count
select @count=count(*)from #tmep1—可以被取代
select @count
利用exists而不count判斷有沒有記錄
declare @count int
Select @count=count(1)from ZY_BRFYMXK WHERE zxrq>'2009‘
If @count>0 … else ….--改為
If exists(Select 1 from ZY_BRFYMXK WHERE zxrq>'2009’)… else ….
第五篇:SQL語句的優(yōu)化方法
SQL語句的優(yōu)化方法
1.1注釋使用
在語句中多寫注釋,注釋不影響SQL語句的執(zhí)行效率。增加代碼的可讀性。
1.2對于事務(wù)的使用
盡量使事務(wù)處理達(dá)到最短,如果事務(wù)太長最好按功能將事務(wù)分開執(zhí)行(如:可以讓用戶在界面上多幾步操作)。事務(wù)太長很容易造成數(shù)據(jù)庫阻塞,用戶操作速度變慢或死機(jī)情況。
1.3對于與數(shù)據(jù)庫的交互
盡量減少與數(shù)據(jù)庫的交互次數(shù)。如果在前端程序?qū)懹醒蛟L問數(shù)據(jù)庫操作,最好寫成將數(shù)據(jù)一次讀到前端再進(jìn)行處理或者寫成存儲(chǔ)過程在數(shù)據(jù)庫端直接處理。
1.4對于SELECT *這樣的語句,不要使用SELECT *這樣的語句,而應(yīng)該使用SELECT table1.column1這樣的語句,明確指出要查詢的列減少數(shù)據(jù)的通訊量并且這樣的代碼可讀性好,便于維護(hù)。
1.5盡量避免使用游標(biāo)
它占用大量的資源。如果需要row-by-row地執(zhí)行,盡量采用非光標(biāo)技術(shù),如:在客戶端循環(huán),用臨時(shí)表,Table變量,用子查詢,用Case語句等等。如果使用了游標(biāo),就要盡量避免在游標(biāo)循環(huán)中再進(jìn)行表連接的操作。
1.6盡量使用count(1)
count函數(shù)只有在統(tǒng)計(jì)表中所有行數(shù)時(shí)使用,而且count(1)比count(*)更有效率。
1.7IN和EXISTS
EXISTS要遠(yuǎn)比IN的效率高。里面關(guān)系到full table scan和range scan。幾乎將所有的IN操作符子查詢改寫為使用EXISTS的子查詢。
1.8注意表之間連接的數(shù)據(jù)類型
避免不同類型數(shù)據(jù)之間的連接。
1.9盡量少用視圖
對視圖操作比直接對表操作慢,可以用stored procedure來代替她。特別的是不要用視圖嵌套,嵌套視圖增加了尋找原始資料的難度。我們看視圖的本質(zhì):它是存放在服務(wù)器上的被優(yōu)化好了的已經(jīng)產(chǎn)生了查詢規(guī)劃的SQL。對單個(gè)表檢索數(shù)據(jù)時(shí),不要使用指向多個(gè)表的視圖,直接從表檢索或者僅僅包含這個(gè)表的視圖上讀,否則增加了不必要的開銷,查詢受到干擾。
1.10沒有必要時(shí)不要用DISTINCT和ORDER BY
這些動(dòng)作可以改在客戶端執(zhí)行,它們增加了額外的開銷。
1.11避免相關(guān)子查詢
一個(gè)列的標(biāo)簽同時(shí)在主查詢和where子句中的查詢中出現(xiàn),那么很可能當(dāng)主查詢中的列值改變之后,子查詢必須重新查詢一次。查詢嵌套層次越多,效率越低,因此應(yīng)當(dāng)盡量避免子查詢。如果子查詢不可避免,那么要在子查詢中過濾掉盡可能多的行。
1.1注意UNion和`UNion all 的區(qū)別
UNION all執(zhí)行效率高。
1.1外鍵關(guān)聯(lián)的列應(yīng)該建立索引
(如子表id)主子表單據(jù)肯定要建視圖,2個(gè)表的關(guān)聯(lián)以2個(gè)表中的MainID為關(guān)系,所以,需要給子表的MainID單獨(dú)建索引,這將很大地提高視圖的速度。例如Gy_InOutSub中的InoutMainid增加索引。