狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

SQL語(yǔ)句優(yōu)化原則

admin
2023年3月7日 23:57 本文熱度 1213

數(shù)據(jù)庫(kù)性能是整個(gè)應(yīng)用程序性能的重要部分。數(shù)據(jù)庫(kù)優(yōu)化涉及的內(nèi)容非常廣泛,各類數(shù)據(jù)庫(kù)都提供眾多的性能指標(biāo)和大量的優(yōu)化工 具。

下面我們簡(jiǎn)單介紹一下優(yōu)化的基本概念。一個(gè)運(yùn)行良好的數(shù)據(jù)庫(kù)至少應(yīng)具有以下特點(diǎn):

合理的物理結(jié)構(gòu)及硬件能力
合理的物理結(jié)構(gòu)指數(shù)據(jù)庫(kù)文件及整個(gè)網(wǎng)絡(luò)的物理分布。硬件能力指是否有足夠的硬件資源來完成應(yīng)用程序功能。合理的物理結(jié)構(gòu)至少帶來兩個(gè)方面的好處:

1、適量的數(shù)據(jù)冗余,提高數(shù)據(jù)安全性。

2、平衡磁盤IO,增強(qiáng)數(shù)據(jù)讀寫能力。

而足夠的硬件能力的作用自然不言而喻。一旦建立好數(shù)據(jù)庫(kù)系統(tǒng)并開始運(yùn)行,數(shù)據(jù)庫(kù)的物理結(jié)構(gòu)就不能改變。

合理的系統(tǒng)參數(shù)
對(duì)應(yīng)數(shù)據(jù)庫(kù)來說,隨著數(shù)據(jù)量的變化,數(shù)據(jù)庫(kù)性能也一直處在變化之中,因此數(shù)據(jù)庫(kù)建立之初設(shè)定的系統(tǒng)參數(shù)會(huì)變的越來越不合適,有時(shí)甚至阻礙了數(shù)據(jù)庫(kù)的正常運(yùn) 行,導(dǎo)致性能瓶頸。因此觀察性能變化,隨時(shí)調(diào)整系統(tǒng)參數(shù),使數(shù)據(jù)庫(kù)一直處于一個(gè)良好的運(yùn)行狀態(tài),就成為管理員最重要的日常工作之一。對(duì)系統(tǒng)參數(shù)的合理調(diào) 整,常常能將數(shù)據(jù)庫(kù)從崩潰的邊緣挽救回來。oracle、sqlserver這樣的高品質(zhì)數(shù)據(jù)庫(kù)都為系統(tǒng)參數(shù)提供了靈活多變的調(diào)整方式。一般來說,只要數(shù) 據(jù)庫(kù)結(jié)構(gòu)設(shè)計(jì)不存在重大缺陷,通過后期的調(diào)整,都可以使數(shù)據(jù)庫(kù)運(yùn)行在一個(gè)良好的狀態(tài)下。

性能優(yōu)良的sql語(yǔ)句
sql語(yǔ)句是在程序開發(fā)階段就已經(jīng)決定了的,由低效率的sql語(yǔ)句給數(shù)據(jù)庫(kù)性能帶來的問題,往往在數(shù)據(jù)庫(kù)開始運(yùn)行一段時(shí)間后才凸現(xiàn)出來(隨著數(shù)據(jù)量的不斷 增加),但發(fā)現(xiàn)后就變的難以改變,成為不可突破的性能瓶頸。因此,作為一名合格的開發(fā)人員,應(yīng)該建立基本的優(yōu)化概念和良好的編程習(xí)慣,從整體上提高應(yīng)用程 序的質(zhì)量。

同時(shí),提高sql語(yǔ)句的執(zhí)行效率,是提高整個(gè)數(shù)據(jù)庫(kù)性能的最立竿見影且價(jià)格低廉的方法之一。因?yàn)閹缀跛械臄?shù)據(jù)庫(kù)都會(huì)不可避免的運(yùn)行一些效率低下的 sql語(yǔ)句。對(duì)數(shù)據(jù)庫(kù)性能的調(diào)整,往往都是從sql語(yǔ)句調(diào)優(yōu)開始的。

下面我們簡(jiǎn)單介紹數(shù)據(jù)庫(kù)是怎么執(zhí)行sql語(yǔ)句的。

sql語(yǔ)句是唯一從應(yīng)用程序發(fā)送到數(shù)據(jù)庫(kù)實(shí)例的命令。數(shù)據(jù)庫(kù)實(shí)例所做的全部工作就是接受、解釋和執(zhí)行sql 語(yǔ)句。

在絕大多數(shù)情況下,我們并不需要關(guān)心sql語(yǔ)句是怎么執(zhí)行的,這是因?yàn)樵诋?dāng)前流行的數(shù)據(jù)庫(kù)軟件中都無(wú)一例外的采用了高性能的優(yōu)化器,而這些優(yōu)化器在 絕大多數(shù)的情況下都能將用戶某些不合理的sql語(yǔ)句結(jié)構(gòu)轉(zhuǎn)換成更合理的形式,從而有效提高sql的執(zhí)行效率。

優(yōu)化器的優(yōu)化原理有兩種:

基于成本的優(yōu)化
對(duì)一條sql語(yǔ)句,優(yōu)化器會(huì)生成所有可能的執(zhí)行方式,估計(jì)這些執(zhí)行方式將使用的硬件成本,相互比較后從中選擇成本最低的執(zhí)行計(jì)劃。缺點(diǎn)是必須收集大量統(tǒng)計(jì) 數(shù)據(jù),對(duì)服務(wù)器造成額外的負(fù)擔(dān)。

基于規(guī)則的優(yōu)化
相對(duì)基于成本的優(yōu)化,基于規(guī)則的優(yōu)化則顯得死板的多。比如sqlserver遇到blog_id=*的情況就會(huì)去找索引,實(shí)在找不到索引才使用全表掃描。 而不考慮有時(shí)候不用索引可能效率更高。顯然有些情況下基于規(guī)則的優(yōu)化并不合適。

/*執(zhí)行計(jì)劃的概念:簡(jiǎn)單的說執(zhí)行計(jì)劃就是指在執(zhí)行sql語(yǔ)句前對(duì)代碼進(jìn)行編譯時(shí)數(shù)據(jù)庫(kù)實(shí)例為sql選擇的執(zhí)行路徑。如一個(gè)sql對(duì)A、B、C三個(gè) 表進(jìn)行聯(lián)合查詢,數(shù)據(jù)庫(kù)會(huì)首先以某種方式對(duì)這3個(gè)表種符合條件的記錄進(jìn)行查詢(全表掃描或其他),再將A、B、C表中符合條件的記錄讀入內(nèi)存,將A、B表 的記錄相比較后得出的結(jié)果集與C表相比較,最后得到符合的結(jié)果集。但實(shí)際情況比這復(fù)雜的多。*/

oracle可以選擇兩種優(yōu)化模式之中的一種,而其他數(shù)據(jù)庫(kù)則是固定的(DB2不清楚,關(guān)于DB2的資料太少了),基本都是基于規(guī)則的優(yōu)化。

然而優(yōu)化器畢竟不是智能的。很多時(shí)候,它不可避免的受到sql語(yǔ)句結(jié)構(gòu)的影響。而SQL優(yōu)化的實(shí)質(zhì)就是在結(jié)果正確的前提下,用優(yōu)化器可以識(shí)別的語(yǔ) 句,充份利用索引,減少表掃描的I/O次數(shù),盡量避免表掃描的發(fā)生。

sql的書寫原則

以下介紹的標(biāo)準(zhǔn)sql的書寫原則是本文的核心,這些原則適用于絕大部分?jǐn)?shù)據(jù)庫(kù)。介紹這些原則的時(shí)候,我會(huì)舉一些簡(jiǎn)單的例子來說明,但這些例子在實(shí)際 生產(chǎn)中可能沒有什么實(shí)際意義。

1、使用索引
如果沒有任何索引,在執(zhí)行sql語(yǔ)句時(shí)必定將做全表掃描。這和我們?cè)诳匆槐緯鴷r(shí),如果沒有目錄,我們只能從第一頁(yè)開始查找,直到找到查詢的內(nèi)容是一個(gè)道 理。全表掃描是效率最低的查詢方式,我們會(huì)看到絕大多數(shù)的低效率sql就是使用的全表掃描。因此在對(duì)一些大表進(jìn)行查詢的時(shí)候,我們需要關(guān)心一下表中是否建 立了索引并盡量使用索引。

總的來說索引可以分為聚集索引和非聚集索引。一個(gè)表中只能有一個(gè)聚集索引。對(duì)一個(gè)表建立一個(gè)聚集索引后,數(shù)據(jù)庫(kù)會(huì)調(diào)整表記錄的順序,使表按照索引的 順序重新排列。而非聚集索引則不會(huì)改變表的結(jié)構(gòu)。

使用的最常見的索引就是主鍵索引。實(shí)際上在表中指定一列為主鍵的時(shí)候,就在這列上建立了唯一值索引并強(qiáng)制該列的值唯一,這就成了主鍵索引。

在下面幾種情況下,應(yīng)該建立索引:

1.   有大量重復(fù)值、且經(jīng)常有范圍查詢(between,>,<,>=,<=)和order by、group by發(fā)生的列,可以考慮使用聚集索引;

2.   在使用最頻繁的列且常常需要使用函數(shù)的時(shí)候,可以考慮使用函數(shù)索引。

3.   在使用最頻繁的列且常常需要對(duì)兩個(gè)或多個(gè)列進(jìn)行聯(lián)合查詢的時(shí)候,可以考慮使用組合索引。

4.   在重復(fù)率較低的列上建立唯一索引。

索引雖有助于提高性能,但不是索引越多越好,恰好相反過多的索引會(huì)導(dǎo)致系統(tǒng)低效。因?yàn)橛脩粼诒碇忻考舆M(jìn)一個(gè)索引,維護(hù)索引集合就要做相應(yīng)的更新工 作,同時(shí)每次有數(shù)據(jù)改變的時(shí)候就需要維護(hù)索引。

因此盡管使用索引非常有必要,但是在以下情況下,我們并不贊成使用索引。

1、  大量對(duì)表數(shù)據(jù)的修改(插入過刪除)

2、  數(shù)據(jù)量很小

關(guān)于怎么使用索引,就是多使用存在索引的列作為查詢條件。但是使用了帶索引的列,也不一定就使用了索引,后面會(huì)提到相應(yīng)的知識(shí)。

2、和任何高級(jí)語(yǔ)言一樣,sql也是越簡(jiǎn)單越好。
大家先看看下面的語(yǔ)句:

select TOP $size$ BLOG_ID AS blogID,

BLOG_DOMINO AS blogDomino,

BLOG_TEMPLATE_ID AS blogTemplateID

from blog

where BLOG_ID NOT IN

(select BLOG_ID

from blog

where BLOG_ID>=$size$+$fromID$)

AND LOCKED=1

orDER BY BLOG_ID DESC;

通過查看執(zhí)行計(jì)劃,我們可以看到執(zhí)行查詢的步驟:

1、子查詢中使用blog.pk_blog(主鍵索引)查詢BLOG中滿足blog>=$size$+$fromID$的記錄,這步占總成本 的46%。

2、使用blog.pk_blog(主鍵索引),查詢BLOG中滿足LOCKED=1的記錄。這步占總成本的44%。

3、使用Merge join。這步占總成本的10%。總成本為0.23。

我們可以看到兩次對(duì)blog表的查詢都使用了blog_id上的主鍵索引,同時(shí)表連接消耗的資源也比較少。應(yīng)該說,對(duì)于子查詢結(jié)構(gòu),這個(gè)查詢的效率 并不低。但是,這和下面的語(yǔ)句完全是等價(jià)的:

select TOP $size$ BLOG_ID AS blogID,

BLOG_DOMINO AS blogDomino,

BLOG_TEMPLATE_ID AS blogTemplateID

from blog

where BLOG_ID<$size$+$fromID$

AND LOCKED=1

orDER BY BLOG_ID DESC;

總成本為0.0035。

優(yōu)化器不是人工智能,在第一個(gè)查詢中指定使用子查詢結(jié)構(gòu),優(yōu)化器就無(wú)法突破這個(gè)限制,盡管兩個(gè)查詢是相同的,優(yōu)化器還是不能將第一種查詢結(jié)構(gòu)等價(jià)的 轉(zhuǎn)換成第二種。所以查詢語(yǔ)句使用的結(jié)構(gòu)對(duì)優(yōu)化器影響重大,我們?cè)谶M(jìn)行多表查詢等復(fù)雜情況的時(shí)候的時(shí)候(如可能需要使用聯(lián)接查詢、子查詢、嵌套查詢、 group by等),應(yīng)多進(jìn)行一些考慮。一個(gè)原則是結(jié)構(gòu)要盡量簡(jiǎn)單,這樣在編譯效率、執(zhí)行效率和程序可讀性方面都有好處。

3、謹(jǐn)慎使用is null和is not null
    不能用null作索引,任何包含null值的列都將不會(huì)被包含在索引中。即使在列上建立了索引,只要這些列中有一個(gè)含有null,該列就會(huì)從索引 中排除。也就是說,如果某列存在空值,即使對(duì)該列建索引也不會(huì)提高性能。同時(shí),任何在where子句中使用is null或is not null的語(yǔ)句優(yōu)化器是不允許使用索引的。

4、in和exists
很多資料都聲稱exists的效率高于in。而實(shí)際情況證明,在子句中使用in和exists效率是一樣的。

select ProductName

from Northwind.dbo.Products

where UnitPrice in

(select UnitPrice

from Northwind.dbo.Products

where ProductName = ‘Sir Rodney’’s Scones’)

select ProductName

from Northwind.dbo.Products b

where exists

(select UnitPrice

from Northwind.dbo.Products a

where a.ProductName = ‘Sir Rodney’’s Scones’

and a.UnitPrice=b.UnitPrice)

查看執(zhí)行計(jì)劃可以看到,上面兩個(gè)語(yǔ)句的執(zhí)行路徑和執(zhí)行成本都完全一樣。

5、in和or
sqlserver會(huì)自動(dòng)將in轉(zhuǎn)換成or,因此對(duì)sqlserver來說下面兩個(gè)語(yǔ)句是一樣的,而其他數(shù)據(jù)庫(kù)中in的效率要高于or。

select blog_name

from blog

where blog_name like ‘AB%’

or blog_name like ‘CD%’

or blog_name like ‘EF%’;

select blog_name

from blog

where blog_name in (‘AB%’,’CD%’,‘EF%’);

6、查詢字段要需要多少,查詢多少
我們每少提取一個(gè)字段,查詢速度就會(huì)有相應(yīng)的上升。這主要是因?yàn)槲锢碜x取成本降低了。所以要避免select *這樣的查詢,需要哪些字段就查詢哪些字段。

7、將行和操作數(shù)減到最少
使用 where 和 HAVING 子句只選擇需要的行,可以將 select 語(yǔ)句返回的行數(shù)減到最少。盡量少用不等于運(yùn)算符 <> 或 !=。數(shù)據(jù)庫(kù)將必須在表或索引中掃描所有的值,以查看它們是否不等于表達(dá)式中給定的值。可以使用范圍重寫表達(dá)式:

where KeyColumn < ‘TestValue’ AND KeyColumn > ‘TestValue’8、盡量少用格式轉(zhuǎn)換,防止出現(xiàn)隱含的格式轉(zhuǎn)換。
舉個(gè)簡(jiǎn)單的例子:

某個(gè)表中有一個(gè)時(shí)間字段time date型,現(xiàn)在開發(fā)人員需要寫一個(gè)sql:查詢出在2004-04-21到2005-04-21之間,注冊(cè)了多少blog新用戶。我們比較下面兩個(gè)語(yǔ) 句:

select *

from blog

where to_char(create_time,yyyymmdd) between ’20040421’and ’20050421’;

――將time轉(zhuǎn)換成字符型,和’20040421’及’20050421’做比較。

select *

from blog

where create_time<=to_date(‘2004-04-21’,’yyyy-mm-dd’)

and create_time<=to_date(‘2005-04-21’,’yyyy-mm-dd’);

――將20040421及20050421轉(zhuǎn)換成date型,和create_time做比較。

(PL/SQL)

第二個(gè)語(yǔ)句的性能明顯優(yōu)于第一個(gè)。這是因?yàn)榈谝粋€(gè)sql數(shù)據(jù)庫(kù)必須將每一行記錄的create_time都轉(zhuǎn)換一次,而第一個(gè)只需要對(duì)常量做一次轉(zhuǎn) 換。(第二個(gè)語(yǔ)句的性能明顯優(yōu)于第一個(gè)的另一個(gè)重要原因就是第一個(gè)查詢不能使用create_time上的索引)。

隱含的格式轉(zhuǎn)換既是數(shù)據(jù)庫(kù)在必要時(shí)會(huì)自動(dòng)將一個(gè)數(shù)據(jù)類型轉(zhuǎn)換成另一種可兼容的數(shù)據(jù)類型:

最常見的情況,一個(gè)字段sort_id varchar(10)型,現(xiàn)在要查詢出所有sort_id為3的用戶。

select * from blog where sort_id=3;

如果用戶沒有查看表結(jié)構(gòu),很可能認(rèn)為sort_id是int型而寫出上面的語(yǔ)句。同時(shí),數(shù)據(jù)庫(kù)不會(huì)報(bào)錯(cuò),這是因?yàn)榫幾g引擎自動(dòng)做了一次數(shù)據(jù)類型轉(zhuǎn) 換。這就是一個(gè)隱藏轉(zhuǎn)換的典型例子。在查詢大量數(shù)據(jù)的時(shí)候,這樣不必要的轉(zhuǎn)換會(huì)降低sql的效率。

9、帶通配符(%)的like語(yǔ)句
要求在blog表中查詢名字中包含“我”的人。可以采用如下的查詢SQL語(yǔ)句:

select * from blog where blog_name like ‘%我%’;

這里由于通配符(%)在搜尋詞首出現(xiàn),所以O(shè)racle將不使用blog_name的索引。在很多情況下可能無(wú)法避免這種情況,但是一定要心中有 底,通配符如此使用會(huì)降低查詢速度。然而當(dāng)通配符出現(xiàn)在字符串其他位置時(shí),優(yōu)化器就能利用索引。在下面的查詢中索引得到了使用:

select * from blog where blog_name like ‘c%’;

對(duì)于sqlserver,這種情況沒有影響。

10、ORDER BY和GROPU BY
對(duì)于ORDER BY和GROUP BY短語(yǔ),任何一種索引都有助于select的性能提高。但是使用聚集索引的效率最高。如blog表,blog_id 為主鍵索引,blog_name上有一個(gè)聚集索引。

select *

from blog

order by blog_name;

由于聚集索引一個(gè)表中只能有一個(gè),因此在無(wú)法使用聚集索引的情況下,使用其他索引也能提高查詢效率。

11、禁止進(jìn)行列運(yùn)算
任何對(duì)列的操作都將導(dǎo)致表掃描,原因是對(duì)列進(jìn)行運(yùn)算將直接導(dǎo)致無(wú)法使用該列上的索引(除非建立了函數(shù)索引)。它包括數(shù)據(jù)庫(kù)函數(shù)、計(jì)算表達(dá)式等等。因此,查 詢時(shí)要盡可能將操作移至等號(hào)右邊。

select *

from blog

where blog_id=3;

觀察執(zhí)行計(jì)劃,發(fā)現(xiàn)使用了索引blog.PK_blog,整個(gè)查詢消耗了cpu time:0.00008;I/O成本:0.0032。預(yù)計(jì)成本:0.0032。而如果改成:

select *

from blog

where cast(blog_id as char)=’3’;

――將blog_id轉(zhuǎn)換為char型后與’3’相比較。

觀察執(zhí)行計(jì)劃,發(fā)現(xiàn)使用了索引blog.IX_plogs_blog_id(這里使用這個(gè)索引的原因是由于無(wú)法使用 blog.PK_blog,sqlserver退而求其次,使用了建立在plogs_blog_id字段上的索引),整個(gè)查詢消耗了cpu time:0.264;I/O成本:0.345。預(yù)計(jì)成本:0.61。性能下降了200倍!

同樣,應(yīng)將類似:where blog_id*1000>28847;的語(yǔ)句改為:where blog_id>28.847;

12、使用表提示
使用表提示的本質(zhì)是影響優(yōu)化器,使優(yōu)化器按照指定的執(zhí)行計(jì)劃來執(zhí)行sql語(yǔ)句(通常是制定多表連接時(shí)的連接方式)。一般情況下并不需要使用表提示,因?yàn)閮?yōu) 化器總是能選擇適當(dāng)?shù)膱?zhí)行計(jì)劃。這種做法只是增加了性能優(yōu)化的可能性,并不一定會(huì)產(chǎn)生好的影響。

由于使用表提示有時(shí)反而會(huì)降低執(zhí)行效率,因此,只有當(dāng)我們發(fā)現(xiàn)一些sql在低效運(yùn)行且認(rèn)為有必要干預(yù)sql執(zhí)行計(jì)劃的時(shí)候(可能已經(jīng)嚴(yán)重影響了應(yīng)用 程序的運(yùn)行)才使用。同時(shí)需要通過反復(fù)調(diào)試來達(dá)到最佳的效果。

使用表提示的方法:Oracle中使用hint提示,sqlserver中使用option子句。

13、慎用游標(biāo)
在某些必須使用游標(biāo)的場(chǎng)合,可考慮將符合條件的數(shù)據(jù)行轉(zhuǎn)入臨時(shí)表中,再對(duì)臨時(shí)表定義游標(biāo)進(jìn)行操作,這樣可使性能得到明顯提高。

14、關(guān)于多表連接和子查詢
在實(shí)際應(yīng)用中我們常常會(huì)遇到需要使用多表連接或子查詢的情況。同時(shí)我們會(huì)發(fā)現(xiàn),很多時(shí)候這兩種查詢結(jié)構(gòu)可以做等量的轉(zhuǎn)換。下面的例子就是這樣: select ProductNamefrom Northwind.dbo.Productswhere UnitPrice in(select UnitPricefrom Northwind.dbo.Productswhere ProductName = ‘Sir Rodney’’s Scones’) select Prd1.ProductNamefrom Northwind.dbo.Products AS Prd1JOIN Northwind.dbo.Products AS Prd2  ON (Prd1.UnitPrice = Prd2.UnitPrice)where Prd2.ProductName = ‘Sir Rodney’’s Scones’

(T-sql。使用的是northwind示例數(shù)據(jù)庫(kù)中的表)

子查詢和不包括子查詢但語(yǔ)義上等效的語(yǔ)句在性能方面通常沒有區(qū)別。但是,在一些必須檢查存在性的情況中,使用聯(lián)接會(huì)產(chǎn)生更好的性能。否則,為確保消 除重復(fù)值,必須為外部查詢的每個(gè)結(jié)果都處理嵌套查詢。所以在這些情況下,聯(lián)接方式會(huì)產(chǎn)生更好的效果。如下面兩個(gè)等效的sql:

select distinct a.blog_name

from blog a

where exists(

select b.blog_id

from blog_note b

where a.blog_id=b.blog_id

And b.create_time<’2005-04-25’ );

select distinct a.blog_name

from blog a,blog_note b

where a.blog_id=b.blog_id  

And b.create_time<’2005-04-25’;

分析結(jié)果:

查詢執(zhí)行計(jì)劃可以看到執(zhí)行成本:語(yǔ)句一:使用exists子查詢,總成本0.0567語(yǔ)句二:聯(lián)接查詢,總成本0.0535。

15、增加執(zhí)行計(jì)劃的重復(fù)使用率
執(zhí)行計(jì)劃生成后便駐留在高速緩存中。很多時(shí)候一段sql代碼并不是執(zhí)行一次就完了,同樣的代碼會(huì)連續(xù)執(zhí)行很多次。如一個(gè)用戶查詢了自己的用戶資料,0.1 秒后另一個(gè)用戶執(zhí)行了相同的操作。如果數(shù)據(jù)庫(kù)能識(shí)別出這兩次sql語(yǔ)句是同樣的,在第二次執(zhí)行時(shí)就不會(huì)再次編譯sql,而是直接使用駐留在高速緩存中的執(zhí) 行計(jì)劃。在某些大型系統(tǒng)中一些基礎(chǔ)的sql可能會(huì)每秒執(zhí)行上千次。因此重復(fù)使用執(zhí)行計(jì)劃可以大大縮短sql的執(zhí)行時(shí)間。但是有的時(shí)候數(shù)據(jù)庫(kù)不能識(shí)別出類似 的sql語(yǔ)句,比如用戶查詢自己資料的例子:

第一個(gè)用戶:

select * from blog where blog_id=1;

第二個(gè)用戶查詢的是:

select * from blog where blog_id=455;

sql文本的變化導(dǎo)致數(shù)據(jù)庫(kù)認(rèn)為這是兩個(gè)不同的查詢,無(wú)法重復(fù)使用執(zhí)行計(jì)劃。為了提高執(zhí)行計(jì)劃的重復(fù)使用率,建議:

1、  使用對(duì)象(如表和視圖)的完全合法名稱。如:

select * from blogctynnd.dbo.blog;

2、  oracle強(qiáng)烈建議在應(yīng)用程序中大量使用“綁定變量”,如下:

將:select * from blog where blog_id=1;

改為:

SQL>declarevid int default 1;res varchar(4);beginexecute immediate ’select * from blog where blog_id =:x’ into res using vid;dbms_output.put_line(res);  –oracle系統(tǒng)包,用于輸出。end;/(PL/SQL。這一招的用意很明顯就是 固定sql文本,把編譯器騙過去,有點(diǎn)瞞天過海的意思。其他數(shù)據(jù)庫(kù)使用綁定變量的方法也是一樣的,只是使用的語(yǔ)句稍有不同。)

對(duì)于sqlserver來說使用綁定變量意義不大,因?yàn)閟qlserver數(shù)據(jù)庫(kù)引擎可以識(shí)別出上面給出的例子,綁定變量具有一定的優(yōu)勢(shì),但并不明 顯。

另外需要說明的是在優(yōu)化器內(nèi)部對(duì)執(zhí)行計(jì)劃會(huì)存在一個(gè)衰減列表,到一定時(shí)間后執(zhí)行計(jì)劃還沒有被重復(fù)使用,就會(huì)被清除出這個(gè)列表,這時(shí)再執(zhí)行sql語(yǔ)句 就必須重新編譯了。

其實(shí)SQL的性能優(yōu)化是一個(gè)復(fù)雜的過程,上述這些只是在應(yīng)用層次的一種體現(xiàn),深入研究還會(huì)涉及數(shù)據(jù)庫(kù)層的資源配置、網(wǎng)絡(luò)層的流量控制以及操作系統(tǒng)層 的總體設(shè)計(jì)。另外,不同的數(shù)據(jù)庫(kù)使用的優(yōu)化原則不同,導(dǎo)致對(duì)同樣的sql語(yǔ)句,做出完全不同的執(zhí)行計(jì)劃。即使是同樣的數(shù)據(jù)庫(kù)、同樣的語(yǔ)句,在數(shù)據(jù)庫(kù)運(yùn)行的 不同時(shí)期執(zhí)行效率也會(huì)發(fā)生很大的變化。因此,對(duì)數(shù)據(jù)庫(kù)的優(yōu)化更多的時(shí)候是對(duì)數(shù)據(jù)庫(kù)的觀察和調(diào)試,而不是教條式的簡(jiǎn)單修改。有興趣的同事可以使用下面的方式 查看sql語(yǔ)句的執(zhí)行計(jì)劃,而執(zhí)行計(jì)劃反映了此刻sql語(yǔ)句的執(zhí)行過程,使用的資源等等,是sql語(yǔ)句效率高低的量化數(shù)據(jù)。

oracle:

sql>@rdbms/admin/utlxplan.sql――運(yùn)行utlxplan.sql腳本,會(huì)自動(dòng)創(chuàng)建一個(gè)plan_table。 這步只需要做一次。建立后每次進(jìn)入sqlplus時(shí):

sql>set autotrace on

這時(shí)每次執(zhí)行sql,都會(huì)顯示出相應(yīng)的執(zhí)行計(jì)劃。

Sqlserver:

在sqlserver中查看執(zhí)行計(jì)劃非常簡(jiǎn)單:進(jìn)入查詢分析器,在窗體中輸入T-sql語(yǔ)句。點(diǎn)擊【查詢預(yù)計(jì)的執(zhí)行計(jì)劃】(該按鈕在切換數(shù)據(jù)庫(kù)下拉 菜單的左邊。或ctrl+l)。這時(shí)執(zhí)行計(jì)劃就會(huì)顯示在窗體下端。

其他數(shù)據(jù)庫(kù)查看執(zhí)行計(jì)劃的方式如有需要可以上網(wǎng)查找。歡迎多交流。

后記

對(duì)于現(xiàn)有的每一種數(shù)據(jù)庫(kù)來說,標(biāo)準(zhǔn)SQL的功能顯然太弱了。因此,每一種數(shù)據(jù)庫(kù)都對(duì)標(biāo)準(zhǔn)SQL進(jìn)行了性能擴(kuò)展。對(duì)于oracle是PL/SQL。 Sqlserver是T-sql。

在本文中列舉的例子,并不一定在你的數(shù)據(jù)庫(kù)中也能成功執(zhí)行。同時(shí),本文中的某些原則,可能對(duì)于特定數(shù)據(jù)庫(kù)、特定優(yōu)化模式下的sql性能并不能起到明 顯改善的作用。

比如在使用通配符的例子中:

select * from employee where last_name like ‘%cliton%’;

對(duì)于oracle,將無(wú)法使用last_name上的索引,導(dǎo)致這個(gè)查詢會(huì)發(fā)生全表掃描。而對(duì)于sqlserver來說,仍然可以正常使用索引。

盡管如此,在開發(fā)過程中對(duì)一些小細(xì)節(jié)的注意,不僅可以保證在大多數(shù)數(shù)據(jù)庫(kù)中有較高的執(zhí)行效率,還可以使sql語(yǔ)句在今后數(shù)據(jù)庫(kù)運(yùn)行的過程中或某些特 殊情況下(如系統(tǒng)遷移),也能長(zhǎng)期保持穩(wěn)定的狀態(tài)。


該文章在 2023/3/7 23:59:39 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved