ORACLE多表查詢最佳化

來源:互聯網
上載者:User

ORACLE有個高速緩衝的概念,這個高速緩衝就是存放執行過的SQL語句,那oracle在執行sql語句的時候要做很多工作,例如解析sql語句,估算索引利用率,綁定變數,讀取資料區塊等等這些操作。假設高速緩衝裡已經儲存了執行過的sql語句,那就直接匹配執行了,少了步驟,自然就快了,但是經過測試會發現高速緩衝只對簡單的表起作用,多表的情況完全沒有效果,例如在查詢單表的時候那叫一個快,但是假設串連多個表,就龜速了。
最重要一點,ORACLE的高速緩衝是全字元匹配的,什麼意思呢,看下面三個select

--No.1
select * from tableA;
--No.2
select * From tableA;
--No.3
select * from tableA;

這三個語句乍一看是一樣的,但是快取是不認的,是全字元匹配的,索引在快取裡會儲存三條不同的語句,說到這裡,又引出一個習慣,就是要保持良好的編程習慣,這個很重要

            

ORACLE多表最佳化我積累了一些,都是常用的,介紹下

一、FROM子句後面的表順序有講究

先說為啥,ORACLE在解析sql語句的時候對FROM子句後面的表名是從右往左解析的,是先掃描最右邊的表,然後在掃描左邊的表,然後用左邊的表匹配資料,匹配成功後就合并。 所以,在對多表查詢中,一定要把小表寫在最右邊,為什麼自己想想就明白了。例如下面的兩個語句:

--No.1  tableA:100w條記錄  tableB:1w條記錄 執行速度十秒
select count(*) from tableA, tableB;

--No.2 執行速度百秒甚至更高
select count(*) from tableB, tableA;

這個估計很多人都知道,但是要確認非常有用。

還有一種是三張表的查詢,例如

select count(1) from tableA a,tableB b ,tableC c where a.id=b.id and a.id=c.id;

上面中tableA 為交叉表,根據oracle對From子句從右向左的掃描方式,應該把交叉表放在最末尾,然後才是最小表,所以上面的應該這樣寫

--tableA a 交叉表 
--tabelB b 100w
--tableC c 1w
select count(1) from tableB b ,tableC c ,tableA a where a.id=b.id and a.id=c.id;

這種寫法對大資料量會非常有用,大家謹記,也是很常用的。

            

二、Where子句後面的條件過濾有講究,ORACLE對where子句後面的條件過濾是自下向上,從右向左掃描的,所以和From子句一樣一樣的,把過濾條件排個序,按過濾資料的大小,自然就是最少資料的那個條件寫在最下面,最右邊,依次類推,例如

--No.1 不可取 效能低下
select * from tableA a where
a.id>500
and a.lx = '2b'
and a.id < (select count(1) from tableA where id=a.id)

--No.2 效能高
select * from tableA a where
a.id < (select count(1) from tableA where id=a.id)
and a.id>500
and a.lx = '2b'

              

三、使用select的時候少用*,多敲敲鍵盤,寫上欄位名吧,因為ORACLE的查詢器會把*轉換為表的全部列名,這個會浪費時間的,所以在大表中少用

          

四、充分利用rowid ,可以用rowid來分頁,刪除查詢重複記錄,很強大的,給兩個例子:

--oracle尋找重複記錄
select * from tableA a where a.rowid>=(select min(rowid) from tableB b where a.column=b.column)


--oracle重複資料刪除記錄
delete from tableA a where a.rowid>=(select min(rowid) from tableB b where a.column=b.column)


--分頁 start=10 limit=10
--end 為 start + limit
--1.查詢要排列的表A
--2.查詢A表的Rownum找出小於end的資料群組成表B
--3.查詢B表通過rownum找出大於start的資料完成
--簡單的說先根據end值過濾資料,然後在根據start過濾資料
SELECT * FROM
(SELECT a.*, ROWNUM rn FROM (SELECT * FROM uim_serv_file_data ORDER BY OUID) a where ROWNUM<=20) b
where rn>10 order by ouid desc

     

五、預存程序中需要注意的,多用commit了,既可以釋放資源,但是要謹慎。

          

六、減少對資料庫表的查詢,這個很重要,能減少就減少,因為在執行語句的時候oracle會做很多初始工作。

          

七、少用in,多用exists來代替

--NO.1  IN的寫法  
SELECT * FROM TABLEA A WHERE
A.ID IN (SELECT ID FORM TABLEB B WHERE B.ID>1)

--NO.2 exists 寫法
SELECT * FROM TABLEA A WHERE
EXISTS (SELECT 1 FROM TABLEB B WHERE A.ID=B.ID AND B.ID>1)
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.