每秒執行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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 每秒執行6000的簡單SQL優化(一)SQL優化
- msyql 簡單的sql優化SQL優化
- 通過分析SQL語句的執行計劃優化SQL 二SQL優化
- greenplum 簡單sql優化案例SQL優化
- 簡單的執行緒池(二)執行緒
- MySQL幾個簡單SQL的優化MySql優化
- 34條簡單的SQL優化準則SQL優化
- MySQL效能優化之簡單sql改寫MySql優化
- 增加複合索引優化SQL的簡單過程索引優化SQL
- linux shell 每秒執行Linux
- Oracle效能優化-SQL優化(案例二)Oracle優化SQL
- 對一條基於分割槽的簡單SQL的優化SQL優化
- 化繁為簡-優化sql優化SQL
- 簡單實現Laravel獲取當前執行的SQLLaravelSQL
- 使用leading(,)優化sql執行計劃優化SQL
- 執行長達2分多鐘的大型sql優化SQL優化
- SQL優化引出的問題(二)SQL優化
- Linuxcrontab實現每秒執行Linux
- react 簡單優化React優化
- 通過分析SQL語句的執行計劃優化SQL(總結)SQL優化
- 通過分析SQL語句的執行計劃優化SQL語句SQL優化
- SQL優化案例-從執行計劃定位SQL問題(三)SQL優化
- 簡單易懂的 webpack 打包後 JS 的執行過程(二)WebJS
- 不會看 Explain執行計劃,勸你簡歷別寫熟悉 SQL優化AISQL優化
- 不會看 Explain 執行計劃,勸你簡歷別寫熟悉 SQL 優化AISQL優化
- SQL Server之旅(11):簡單說說sqlserver的執行計劃SQLServer
- 簡單的執行緒池執行緒
- AutoTRACE是分析SQL的執行計劃,執行效率的一個非常簡單方便的工具SQL
- 一條簡單的sql語句執行15天的原因分析SQL
- sql語句執行順序與效能優化(1)SQL優化
- Oracle 優化器與sql查詢執行順序Oracle優化SQL
- SQL Server調優系列進階篇(查詢優化器的執行方式)SQLServer優化
- SQL 執行 - 執行器最佳化SQL
- SQL優化(二)(聯合索引的使用)SQL優化索引
- Oracle+高效能SQL引擎剖析:SQL優化與調優機制詳解-筆記之執行計劃(二)OracleSQL優化筆記
- 一條簡單的SQL語句優化-新年新氣象SQL優化
- MYSQL sql執行過程的一些跟蹤分析(二.mysql優化器追蹤分析)MySql優化
- sql改寫優化:簡單規則重組實現SQL優化