每秒執行6000的簡單SQL優化(二)
繼續前幾天的一次效能調優,這次調優難度不小,而且空間很小,看起來簡直就是絕處逢生的感覺。下面的兩條SQL語句執行頻率極高,每秒達到6000次,希望能夠優化。
select companyname from license
前幾天分析了一下,也嘗試了很多種方法,但是始終無法啟用索引,最後採用IOT的形式才看到效果,這是其一。
還有一點很多明眼人看出來了,為什麼建立了唯一性索引,表license中存在1行記錄,但是卻無法啟用,一個根本原因就是唯一性索引的列沒有非空約束。
為此我又進行了一次測試,新增了主鍵,那麼就會是非空約束和唯一性主鍵。
create table license tablespace users as select * from USERV6.LICENSE ;
alter table license modify(companyname primary key);
exec dbms_stats.gather_table_stats(ownname=>null,tabname=>'LICENSE');
測試結果如下:
可以看到達到了預期的改進效果。但是改進幅度到底有多大呢。
我們抓取了一個awr的報告來看看。
改進前,是全表掃描,每次執行的buffer gets是7
而改進之後的情況如下:
第一條語句的優化暫且到這裡,如果是在11g中,可能result cache還有有一些改進之處。
再來看看第二條語句。
select supdepid from hrmdepartment where id =''
表hrmdepartment這種id是主鍵列,但是查詢使用了id=''
檢視執行計劃可以很明顯看到Filter的處理,裡面的條件很微妙NULL IS NOT NULL
這樣一個語句怎麼優化呢,一個很明顯的處理方式就是在SQL中做檢查,儘可能調整邏輯。
但是讓人尷尬的是這個應用是閉源的,無法直接修改裡面的邏輯。怎麼改進,或者說有什麼是DBA能想辦法緩解的。
首先使用唯一性索引是最高效的索引掃描方式。
能夠沾沾索引的光,其實還真有點門路,那就是建立一個複合索引,基於列supdepid,id
create unique index ind_hrm_id on HRMDEPARTMENT(id,supdepid);
exec dbms_stats.gather_table_stats(ownname=>null,tabname=>'HRMDEPARTMENT',cascade=>true);
這個語句的效果如下:
如果執行已有的主鍵id條件的查詢,就會發現原來的唯一性索引變為了下面的區間掃描。
其實可以在繼續改進,就是建立複合索引,基於列(supdepid,id)
這樣的好處在於不會影響已有的唯一性主鍵索引。
查詢id=''的效果如下:
而根據id的值來查詢,這個是還是走原來的唯一性索引掃描。
這樣做可能看起來效果不大,畢竟掃描返回的行數都是全表的行數。
我們把資料量增大到500萬
create table test_obj as select level object_id ,'obj'||level object_name,'TABLE' object_type from dual connect by level<=5000000;
alter table test_obj modify(object_id primary key);
這個時候Ojbect_type為char型別,修改為varchar2
SQL> ALTER TABLE TEST_OBJ MODIFY(OBJECT_TYPE VARCHAR2(10));
然後把資料簡單的處理一下,讓資料的分佈基本打散。
update test_obj set object_type='VIEW' where object_id>200000 and object_id<1430000;
update test_obj set object_type='SYNONYM' where object_id>2000000 and object_id<3430000;
update test_obj set object_type='SEQUENCE' where object_id>4000000 and object_id<4743000;
資料的分佈情況如下:
SQL> select object_type,count(*)from test_obj group by object_type;
OBJECT_TYP COUNT(*)
---------- ----------
VIEW 1229999
SYNONYM 1429999
SEQUENCE 742999
TABLE 1597003
如果我們建立複合索引基於列(object_type,object_id)
create index ind_test_obj_mx on test_obj(object_type,object_id);
exec dbms_stats.gather_table_stats(ownname=>null,tabname=>'TEST_OBJ');
全表掃描的cost為4342,則索引掃描的cost為3765,相比還是有不小的提高。
而對於這個問題的持續跟進結果就是,應用那邊也做了一些努力,我可以看到的是語句的執行頻率從原來的每小時2000萬降到了200萬。
這個改進的效果有多大。可以參見下面的圖。
橫軸是時間,縱軸是資料庫的負載
綠色的部分是每小時2000萬的時候資料庫的負載曲線
紅色的部分是每小時200萬的時候資料庫的負載曲線
藍色的部分是優化之後,每小時200萬的時候資料庫的負載曲線。
可以看到藍色的曲線還是略微要低於紅色的部分,但是改進的空間在200萬的執行頻率下效果被縮小了。
改進最大的是應用的調整,幅度可不是簡單的幾倍幾十倍,而是根本性的改變。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2127254/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 簡單的執行緒池(二)執行緒
- MySQL效能優化之簡單sql改寫MySql優化
- Oracle效能優化-SQL優化(案例二)Oracle優化SQL
- 簡單實現Laravel獲取當前執行的SQLLaravelSQL
- 對一條基於分割槽的簡單SQL的優化SQL優化
- SQL優化案例-從執行計劃定位SQL問題(三)SQL優化
- 不會看 Explain執行計劃,勸你簡歷別寫熟悉 SQL優化AISQL優化
- 不會看 Explain 執行計劃,勸你簡歷別寫熟悉 SQL 優化AISQL優化
- sql語句執行順序與效能優化(1)SQL優化
- SQL 執行 - 執行器最佳化SQL
- MYSQL sql執行過程的一些跟蹤分析(二.mysql優化器追蹤分析)MySql優化
- sql改寫優化:簡單規則重組實現SQL優化
- 簡單的執行緒池執行緒
- SQL優化案例-單表分頁語句的優化(八)SQL優化
- SQL優化案例-正確的使用索引(二)SQL優化索引
- SQL執行內幕:從執行原理看調優的本質SQL
- [20190125]簡單快速檢視那些sql語句正在執行.txtSQL
- MySQL之SQL優化詳解(二)MySql優化
- 簡單的執行緒池(六)執行緒
- 簡單的執行緒池(四)執行緒
- 簡單的執行緒池(三)執行緒
- 簡單的執行緒池(九)執行緒
- 簡單的執行緒池(八)執行緒
- 簡單的執行緒池(七)執行緒
- Oracle優化案例-從執行計劃定位SQL問題(三)Oracle優化SQL
- MySQL原理簡介—1.SQL的執行流程MySql
- Oracle某行系統SQL優化案例(二)OracleSQL優化
- 面試官:每秒上千訂單的場景下,如何對分散式鎖進行高併發優化?面試分散式優化
- sql優化 面試必問【簡答】SQL優化面試
- 一個left join SQL 簡單優化分析SQL優化
- nginx部署及簡單優化Nginx優化
- 簡單優化容器服務優化
- Oracle - 執行過的SQL、正在執行的SQL、消耗資源最多的SQLOracleSQL
- 深度解析單執行緒的 Redis 如何做到每秒數萬 QPS 的超高處理能力!執行緒Redis
- 分析執行計劃優化SQLORACLE的執行計劃(轉)優化SQLOracle
- SQL優化案例-改變那些CBO無能為力的執行計劃(一)SQL優化
- 計算節點會對收到的SQL 語句做解析、優化、執行並SQL優化
- 多執行緒Demo學習(執行緒的同步,簡單的執行緒通訊)執行緒
- 資料庫查詢優化:使用explain分析sql語句執行效率資料庫優化AISQL