【原創】自己構思2條SQL用於完成相同的功能,並比較它們的效能!

leonarding發表於2012-11-21
構思:想法比較簡單,有3個朋友,編寫SQL語句計算一下他們3個月工資的總和
第一種方法就是直接相加得到結果
[oracle@leonarding1 ~]$ sqlplus / as sysdba
> conn leo1/leo1
Connected.
> create table leo_wage (id number,name varchar(20),wage number,month date);     建立了 id  姓名 工資 三個欄位
Table created.
insert into leo_wage values (1,'leo',100,to_date('2012_01_01','yyyy-mm-dd'));
insert into leo_wage values (2,'leo',200,to_date('2012_02_01','yyyy-mm-dd'));
insert into leo_wage values (3,'leo',300,to_date('2012_03_01','yyyy-mm-dd'));
insert into leo_wage values (4,'sunev_yu',200,to_date('2012_01_01','yyyy-mm-dd'));
insert into leo_wage values (5,'sunev_yu',300,to_date('2012_02_01','yyyy-mm-dd'));
insert into leo_wage values (6,'sunev_yu',400,to_date('2012_03_01','yyyy-mm-dd'));
insert into leo_wage values (7,'tigerfish',300,to_date('2012_01_01','yyyy-mm-dd'));
insert into leo_wage values (8,'tigerfish',400,to_date('2012_02_01','yyyy-mm-dd'));
insert into leo_wage values (9,'tigerfish',500,to_date('2012_03_01','yyyy-mm-dd'));

> commit;
Commit complete.
> select * from leo_wage;                                    現在記錄已經插入了
        ID NAME                     WAGE   MONTH
---------- -------------------- ----------     ---------
         1 leo                         100       01-JAN-12
         2 leo                         200       01-FEB-12
         3 leo                         300       01-MAR-12
         4 sunev_yu                200       01-JAN-12
         5 sunev_yu                300       01-FEB-12
         6 sunev_yu                400       01-MAR-12
         7 tigerfish                  300       01-JAN-12
         8 tigerfish                  400       01-FEB-12
         9 tigerfish                  500       01-MAR-12

> show autotrace;                   檢視執行計劃,是關閉狀態
autotrace OFF
> set autotrace on;                 啟動執行計劃
> show autotrace;
autotrace ON EXPLAIN STATISTICS              已經啟動

> select sum(wage) from leo_wage;
SUM(WAGE)
----------
      2700
Execution Plan
----------------------------------------------------------
Plan hash value: 3461908344
-------------------------------------------------------------------------------
| Id  | Operation          | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |          |     1 |    13 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |          |     1 |    13 |            |          |
|   2 |   TABLE ACCESS FULL| LEO_WAGE |     9 |   117 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------
直接彙總
Note
-----
   - dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          7  consistent gets                                      7次一致性讀
          0  physical reads
          0  redo size
        527  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
show autotrace;               顯示狀態
set autotrace;                語法格式
set autotrace on explain;     即輸出sql結果又輸出執行計劃
set autotrace on statistics;  即輸出sql結果又輸出統計資訊
set autotrace traceonly;      表示不輸出sql結果,只輸出執行計劃和統計資訊
小結:看本次有7次一致性讀,感覺效率蠻好的。

第二種方法就是先計算出每個人的總和再把每個人總和求和
select sum(sum_wage) from (select name,sum(wage) sum_wage from leo_wage group by name);
> select name,sum(wage) sum_wage from leo_wage group by name;                                                                         先計算出每個人的總和
NAME                   SUM_WAGE
-------------------- ----------
leo                         600
tigerfish                  1200                                            還是tiger工資高,這要請吃飯a
sunev_yu                900
> select sum(sum_wage) from (select name,sum(wage) sum_wage from leo_wage group by name);       再把每個人總和求和,結果和上面的一樣
SUM(SUM_WAGE)
-------------
         2700

Execution Plan
----------------------------------------------------------
Plan hash value: 1978181551
---------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |          |     1 |    13 |     4  (25)| 00:00:01 |
|   1 |  SORT AGGREGATE      |          |     1 |    13 |            |          |
|   2 |   VIEW               |          |     9 |   117 |     4  (25)| 00:00:01 |
|   3 |    HASH GROUP BY     |          |     9 |   225 |     4  (25)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| LEO_WAGE |     9 |   225 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------
先做分組->排序->彙總
Note
-----
   - dynamic sampling used for this statement (level=2)

Statistics
----------------------------------------------------------
          4  recursive calls
          0  db block gets
         15  consistent gets                                          15次一致性讀,一致性讀的次數代表sql的效能,一致性讀越少效能越好,這個說法前提,兩者都沒有物理讀
          0  physical reads
          0  redo size
        531  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
小結:第二條SQL明顯比第一條SQL一致性讀次數多了一倍,效能減小了一半,那麼在實際中肯定不會這麼去寫,但這其實可以證明構造2條完全相同功能的SQL由於程式碼編寫的不夠最佳化,它們的效能可能相差甚遠。
 
 

2012.11.21
天津&winter
分享技術~成就夢想

Bloghttp://space.itpub.net/26686207

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26686207/viewspace-749677/,如需轉載,請註明出處,否則將追究法律責任。

相關文章