儘可能少用IN操做符,基本上全部的IN操做符均可以用EXISTS代替。 不用NOT IN操做符,能夠用NOT EXISTS或者外鏈接+替代。 Oracle在執行IN子查詢時,首先執行子查詢,將查詢結果放入臨時表再執行主查詢。而EXIST則是首先檢查主查詢,而後運行子查詢直到找到第一個匹配項。NOT EXISTS比NOT IN效率稍高。但具體在選擇IN或EXIST操做時,要根據主子表數據量大小來具體考慮。 不用「<>」或者「!=」操做符。對不等於操做符的處理會形成全表掃描,能夠用「<」 or 「>」代替。 Where子句中出現IS NULL或者IS NOT NULL時,Oracle會中止使用索引而執行全表掃描。能夠考慮在設計表時,對索引列設置爲NOT NULL。這樣就能夠用其餘操做來取代判斷NULL的操做。 當通配符「%」或者「_」做爲查詢字符串的第一個字符時,索引不會被使用。 對於有鏈接的列「||」,最後一個鏈接列索引會無效。儘可能避免鏈接,能夠分開鏈接或者使用不做用在列上的函數替代。 若是索引不是基於函數的,那麼當在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,基於代價的優化方式)時。 咱們能夠總結一下可能引發全表掃描的操做: 在索引列上使用NOT或者「<>」; 對索引列使用函數或者計算; NOT IN操做; 通配符位於查詢字符串的第一個字符; IS NULL或者IS NOT NULL; 多列索引,但它的第一個列並無被Where子句引用; Oracle優化器 Oracle優化器(Optimizer)是Oracle在執行SQL以前分析語句的工具。 Oracle的優化器有兩種優化方式:基於規則的(RBO)和基於代價的(CBO)。 RBO:優化器遵循Oracle內部預約的規則。 CBO:依據語句執行的代價,主要指對CPU和內存的佔用。優化器在判斷是否使用CBO時,要參照表和索引的統計信息。統計信息要在對錶作analyze後纔會有。Oracle8及之後版本,推薦用CBO方式。 Oracle優化器的優化模式主要有四種: Rule:基於規則; Choose:默認模式。根據表或索引的統計信息,若是有統計信息,則使用CBO方式;若是沒有統計信息,相應列有索引,則使用RBO方式。 First rows:與Choose相似。不一樣的是若是表有統計信息,它將以最快的方式返回查詢的前幾行,以得到最佳響應時間。 All rows:即徹底基於Cost的模式。當一個表有統計信息時,以最快方式返回表全部行,以得到最大吞吐量。沒有統計信息則使用RBO方式。 設定優化模式的方式 Instance級別:在init<SID>.ora文件中設定OPTIMIZER_MODE; Session級別:經過SQL> ALTER SESSION SET OPTIMIZER_MODE=;來設定。 語句級別:經過SQL> SELECT /*+ALL+_ROWS*/ ……;來設定。可用的HINT包括/*+ALL_ROWS*/、/*+FIRST_ROWS*/、/*+CHOOSE*/、/*+RULE*/ 等。 要注意的是,若是表有統計信息,則可能形成語句不走索引的結果。能夠用SQL>ANALYZE TABLE table_name DELETE STATISTICS; 刪除索引。 對列和索引更新統計信息的SQL: SQL> ANALYZE TABLE table_name COMPUTE STATISTICS; SQL> ANALYZE INDEX index_name ESTIMATE STATISTICS; SQL> grant execute on SYS.DBMS_LOCK to report_test;