記一次比較 Low 的 SQL 優化經歷

2021-09-19 18:58:26 字數 3036 閱讀 6114

select *

from ( select row_.*, rownum rownum_ 

from ( select

k18.ks1800,

k18.ks1801,k17.ks1701,k17.ks1703,k17.ks1704,' 'as ks1503, '' as ks1504,k04.ks0403,k19.ks1904, k19.ks1905 from ks18 k18, ks17 k17, ks19 k19, ks15 k15, ks04 k04 where k18.ks1700 = k17.ks1700 and k19.ks1800 = k18.ks1800 and k19.ks1500 = k15.ks1500 and k18.ks0400 = k04.ks0400 and k17.bae001='1' and k18.bae001='1' and (k18.ks1804='1' or k18.ks1804='2') and k18.ks1805='1' and k19.bae001 = '1' and k18.ks0400 = '3d4e6569-2ea9-4d62-b8d0-bb2e1cc18c4a' group by k18.ks1800,k18.ks1801,k17.ks1701,k17.ks1703,k17.ks1704,'', '',k04.ks0403,k19.ks1904, k19.ks1905 ) row_ where rownum <= 20) table_alias where table_alias.rownum_ > 0;

一看查詢計畫顯示,ks19 表關聯時,掃瞄了全表,一張表 36w 資料全掃瞄了。這怎麼行,看看是哪個條件導致的。找到相應的耗時的過濾條件行數,發現是刪除標記導致的。

既然全表掃瞄了,那加個索引試試?兩張表的刪除標記都加上索引。

create index index_ks19_bae001 on ks19 (bae001)

create index index_ks17_bae001 on ks17 (bae001)

加上之後,沒用,根本沒有走索引,還是 table access full (全表掃瞄)。

不對啊,才 36w 資料,就算全表掃瞄,只返回 20 條記錄不可能這麼慢啊。

執行alter system flush shared_pool;

alter system flush buffer_cache;

將重新整理快取

試試。去掉了一眼就看出的不必要字段,結果如下。

好像沒什麼不一樣的,但是好像速度快了一點(其實差不多),省去了group by 不必要的字段。

不行,再看看sql,發現關聯了兩張不必要的表,就是 ks04 和 ks15。這怎麼能行,把不必要的關聯去掉,再試試。結果從 3.6s 左右降到了 2.891s。看來不該關聯的表還是不要關聯,不需要的字段,還是不要返回啊。為了準確一點,我繼續清快取,繼續執行語句(十次)

結果分別是

3.014s

3.185s

3.210s

3.242s

2.952s

3.042s

2.873s

2.879s

2.985s

3.032s

再看看解釋查詢計畫

少關聯了不必要的表,少了不必要的返回字段,掃瞄行數少了些,但,ks19 和 ks17 依舊是全表掃瞄。

這怎麼辦,建索引的目的就是為了避免全表掃瞄,導致效率太慢。

先從過濾條件入手,ks18 的 ks0400

select * from user_indexes where table_name='ks18'

看了下 這個表只有乙個索引,就是主鍵索引,這怎麼行,索引建上。

create index index_ks18_ks0400 on ks18 (ks0400)

執行結果,2.421s。還行,看看解釋查詢計畫

走索引了,快了一點(好像),之後的查詢都在 2.4s 左右。

不錯,這個索引建的沒問題。

再看看 ks19 的索引

select * from user_indexes where table_name='ks19'

發現有ks1800 的索引,但是就是不走這個,依然是 table access full。既然這個顯示是標誌位導致全表掃瞄,那我把標誌位刪了怎樣?

刪了之後,再看解釋查詢計畫

還是全表掃瞄,那跟標誌位沒太大關係了。既然這樣不行,換個思路。少關聯 ks17 表,只是兩張表試試怎樣。結果如下

依舊全表掃瞄,用不到 ks19 中的 ks1800索引。我記起來了,使用索引是優化器來選擇的,索引使用的流程是 先去索引數找到對應的值,在把索引樹的索引對應主鍵給拿來,再去主鍵索引裡面,再去取值。這種數量大的,好像全表掃瞄更快?每一行記錄都有個 rowid,rowid才是真正的唯一的。

這樣的話,好像資料量大的話,相當於 in 了,每一條逐條比對,不會去用索引。

這樣解決全表掃瞄,目前來說,我是無能為力了。

小結一下

只返回需要的字段

只關聯需要關聯的表

給經常作為查詢條件的字段加上索引,避免全表掃瞄

如果有人還能給出一些建議的話,感激不盡,謝謝

記一次SQL優化

問題發生在關聯主表a 4w資料量 和副表b 4w資料量 關聯欄位都是openid 當時用的是 left join 直接跑sql,卡死 伺服器也是差 優化1 改left join 為join,兩者區別就是left join查詢時已主表為依據,該是幾條就幾條 就算副表沒有關聯的資料 join如果副表沒有...

記一次簡單的sql優化

統計報警點位所屬裝置的裝置報警總數top100的裝置的報警總數 需要先找出所有裝置的報警次數,按照報警次數進行排序,取前100,然後再對前100的裝置的報警次數進行統計 將報警次數top100的裝置找出來,再對整個資料進行乙個inner join,再疊加乙個count。可以計算出 select co...

一次比較坑的裝系統過程

b color green size large 昨天晚上,幫朋友的thinpad e431系列的電腦重灌64位系統,本來這都不是什麼難事,系統很快就裝了,然後接下來,就是各個驅動了,理想的情況下是系統裝完之後,直接連上無線網,然後下個驅動精靈,或者去官網上下個一鍵安裝驅動包,這樣就很能很快完事。u...