提高SQL效率

2021-08-31 22:55:53 字數 4640 閱讀 6206

下面就某些sql 語句的 where 子句編寫中需要注意的問題作詳細介紹。在這些 where 子句中,即使某些列存在索引,但是由於編寫了劣質的 sql ,系統在執行該 sql 語句時也不能使用該索引,而同樣使用全表掃瞄,這就造成了響應速度的極大降低。 

1. is null 與  is not null 

不能用null 作索引,任何包含 null 值的列都將不會被包含在索引中。即使索引有多列這樣的情況下,只要這些列中有一列含有 null ,該列就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高效能。 

任何在where 子句中使用 is null 或 is not null 的語句優化器是不允許使用索引的。 

2. 聯接列 

對於有聯接的列,即使最後的聯接值為乙個靜態值,優化器是不會使用索引的。我們一起來看乙個例子,假定有乙個職工表(employee ),對於乙個職工的姓和名分成兩列存放( first_name 和 last_name ),現在要查詢乙個叫比爾 . 柯林頓( bill cliton )的職工。 

下面是乙個採用聯接查詢的sql 語句, 

select * from employss 

where 

first_name||'||last_name ='beill cliton' 

上面這條語句完全可以查詢出是否有bill cliton 這個員工,但是這裡需要注意,系統優化器對基於 last_name 建立的索引沒有使用。 

當採用下面這種sql 語句的編寫, oracle 系統就可以採用基於 last_name 建立的索引。 

select * from employee 

where 

first_name ='beill' and last_name ='cliton' 

遇到下面這種情況又如何處理呢?如果乙個變數(name )中存放著 bill cliton 這個員工的姓名,對於這種情況我們又如何避免全程遍歷,使用索引呢?可以使用乙個函式,將變數 name 中的姓和名分開就可以了,但是有一點需要注意,這個函式是不能作用在索引列上。下面是 sql 查詢指令碼: 

select * from employee 

where 

first_name = substr('&&name',1,instr('&&name',' ')-1) 

and 

last_name = substr('&&name',instr('&&name』,' ')+1) 

3. 帶萬用字元( % )的 like 語句 

同樣以上面的例子來看這種情況。目前的需求是這樣的,要求在職工表中查詢名字中包含cliton 的人。可以採用如下的查詢 sql 語句: 

select * from employee where last_name like '%cliton%' 

這裡由於萬用字元(% )在搜尋詞首出現,所以 oracle 系統不使用 last_name 的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,萬用字元如此使用會降低查詢速度。然而當萬用字元出現在字串其他位置時,優化器就能利用索引。在下面的查詢中索引得到了使用: 

select * from employee where last_name like 'c%' 

4. order by語句

order by語句決定了 oracle 如何將返回的查詢結果排序。 order by 語句對要排序的列沒有什麼特別的限制,也可以將函式加入列中(象聯接或者附加等)。任何在 order by 語句的非索引項或者有計算表示式都將降低查詢速度。 

仔細檢查order by 語句以找出非索引項或者表示式,它們會降低效能。解決這個問題的辦法就是重寫 order by 語句以使用索引,也可以為所使用的列建立另外乙個索引,同時應絕對避免在 order by 子句中使用表示式。 

5. not 

我們在查詢時經常在where 子句使用一些邏輯表示式,如大於、小於、等於以及不等於等等,也可以使用 and (與)、 or (或)以及 not (非)。 not 可用來對任何邏輯運算符號取反。下面是乙個 not 子句的例子: 

... where not (status ='valid') 

如果要使用not ,則應在取反的短語前面加上括號,並在短語前面加上 not 運算子。 not 運算子包含在另外乙個邏輯運算子中,這就是不等於( <>; )運算子。換句話說,即使不在查詢 where 子句中顯式地加入 not 詞, not 仍在運算子中,見下例: 

... where status <>;'invalid' 

再看下面這個例子: 

select * from employee where salary<>;3000; 

對這個查詢,可以改寫為不使用not : 

select * from employee where salary<3000 or salary>;3000; 

雖然這兩種查詢的結果一樣,但是

第二種查詢方案會比第一種查詢方案更快些

。第二種查詢允許oracle 對 salary 列使用索引,而第一種查詢則不能使用索引。 

6. in和 exists 

有時候會將一列和一系列值相比較。最簡單的辦法就是在where 子句中使用子查詢。在 where 子句中可以使用兩種格式的子查詢。 

第一種格式是使用in 操作符: 

... where column in(select * from ... where ...); 

第二種格式是使用exist 操作符: 

... where exists (select 'x' from ...where ...); 

我相信絕大多數人會使用第一種格式,因為它比較容易編寫,而實際上第二種格式要遠比第一種格式的效率高。在oracle 中可以幾乎將所有的 in 操作符子查詢改寫為使用 exists 的子查詢。 

第二種格式中,子查詢以『select 'x' 開始。運用 exists 子句不管子查詢從表中抽取什麼資料它只檢視 where 子句。這樣優化器就不必遍歷整個表而僅根據索引就可完成工作(這裡假定在 where 語句中使用的列存在索引)。相對於 in 子句來說, exists 使用相連子查詢,構造起來要比 in 子查詢困難一些。 

通過使用exist , oracle 系統會首先檢查主查詢,然後執行子查詢直到它找到第乙個匹配項,這就節省了時間。 oracle 系統在執行 in 子查詢時,首先執行子查詢,並將獲得的結果列表存放在在乙個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以後再執行主查詢。這也就是使用 exists 比使用 in 通常查詢速度快的原因。 

同時應盡可能使用not exists 來代替 not in ,儘管二者都使用了 not (不能使用索引而降低速度), not exists 要比 not in 查詢效率更高。

******************************另外的一篇文章*********************************************==

基本的sql編寫注意事項

當萬用字元「%」或者「_」作為查詢字串的第乙個字元時,索引不會被使用。 對於有連線的列「||」,最後乙個連線列索引會無效。盡量避免連線,可以分開連線或者使用不作用在列上的函式替代。 如果索引不是基於函式的,那麼當在where子句中對索引列使用函式時,索引不再起作用。 where子句中避免在索引列上使用計算,否則將導致索引失效而進行全表掃瞄。

對資料型別不同的列進行比較時,會使索引失效。 用「>=」替代「>」。 union操作符會對結果進行篩選,消除重複,資料量大的情況下可能會引起磁碟排序。如果不需要刪除重覆記錄,應該使用union all。 oracle從下到上處理where子句中多個查詢條件,所以表連線語句應寫在其他where條件前,可以過濾掉最大數量記錄的條件必須寫在where子句的末尾。

oracle從右到左處理from子句中的表名,所以在from子句中包含多個表的情況下,將記錄最少的表放在最後。(只在採用rbo優化時有效,下文詳述) order by語句中的非索引列會降低效能,可以通過新增索引的方式處理。嚴格控制在order by語句中使用表示式。 不同區域出現的相同的sql語句,要保證查詢字元完全相同,以利用sga共享池,防止相同的sql語句被多次分析。 多利用內部函式提高sql效率。

當在sql語句中連線多個表時,使用表的別名,並將之作為每列的字首。這樣可以減少解析時間。

需要注意的是,隨著oracle的公升級,查詢優化器會自動對sql語句進行優化,某些限制可能在新版本的oracle下不再是問題。尤其是採用cbo(cost-based optimization,基於代價的優化方式)時。

我們可以總結一下可能引起全表掃瞄的操作:

oracle優化器

oracle優化器(optimizer)是oracle在執行sql之前分析語句的工具。

oracle的優化器有兩種優化方式:基於規則的(rbo)和基於代價的(cbo)。

oracle優化器的優化模式主要有四種:

設定優化模式的方式

要注意的是,如果表有統計資訊,則可能造成語句不走索引的結果。可以用sql>analyze table table_name delete statistics; 刪除索引。

對列和索引更新統計資訊的sql:

sql> analyze table table_name compute statistics;

sql> analyze index index_name estimate statistics;

sql 如何提高SQL查詢的效率?

如何提高sql查詢的效率?原創猴子聊人物 發布於2019 10 31 21 00 00 閱讀數 11195 收藏 展開 題目 我們公司的資料量非常大,需要的不僅僅是提取資料,要了解sql方案優化的。一般在寫sql時需要注意哪些問題,可以提高查詢的效率?解題思路 資料量大的情況下,不同的sql語句,消...

提高SQL執行效率的方法

oracle提供了多種方法用於減少花在剖析oracle sql表示式上的時間,在執行帶有大量執行計畫的複雜查詢時剖析過程會拖累系統的效能。現在我們來簡要地看看這些方法中的幾種。1 使用ordered提示 oracle必須花費大量的時間來剖析多 的合併,用以確定 合併的最佳順序。如果sql表示式涉及七...

提高sql查詢效率速成寶典

一 建立索引是提高查詢效率最直接的方式.1 表的主鍵 外來鍵必須有索引 2 資料量超過1000的表建議新增索引 3 經常與其他表進行關聯的表,在連線欄位上應該建立索引 4 經常出現在where子句中的字段,特別是大表的字段,應該建立索引 5 作為order by 條件的字段,也可以考慮新增索引 6 ...