HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

[中]Oracle Row Shipping

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2009-12-25 01:21:17

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

    为了降低服务端的负荷,oracle引入一些特性,将部分工作移到客户端去处理。Row shipping就是其中之一。
 

    我们知道,Oracle对于SQL的处理由几个步骤组成:解析(Parse)->优化(Optimize)->生产数据源(Row Source Generate)->返回结果(Result Product)。在传统模式下,数据源生成组件(Row Source Generator)要做一步工作就是从记录中找出SELECT子句的中出现的字段,返回给客户端,这一过程称为投射(Projection)。我们可以通过DBMS_XPLAN(10g)查看查询计划中的投射字段信息:

SQL代码
  1. HELLODBA.COM>create table WIDE_TBL as select * from sys.gv_$session;   
  2.   
  3. Table created.   
  4.   
  5. HELLODBA.COM>explain plan for select sid,audsid,serial# from WIDE_TBL;   
  6.   
  7. Explained.   
  8.   
  9. HELLODBA.COM>select * from table(dbms_xplan.display(null,null,'ADVANCED'));   
  10.   
  11. PLAN_TABLE_OUTPUT   
  12. ---------------------------------------------------------------------------------------------------------   
  13. Plan hash value: 1188828058   
  14.   
  15. ------------------------------------------------------------------------------   
  16. | Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |   
  17. ------------------------------------------------------------------------------   
  18. |   0 | SELECT STATEMENT  |          |    25 |   975 |     3   (0)| 00:00:01 |   
  19. |   1 |  TABLE ACCESS FULL| WIDE_TBL |    25 |   975 |     3   (0)| 00:00:01 |   
  20. ------------------------------------------------------------------------------   
  21.   
  22. ...   
  23.   
  24. Column Projection Information (identified by operation id):   
  25. -----------------------------------------------------------   
  26.   
  27.    1 - "SID"[NUMBER,22], "SERIAL#"[NUMBER,22], "AUDSID"[NUMBER,22]   
  28.   
  29. Note   
  30. -----   
  31.    - dynamic sampling used for this statement   
  32.   
  33. 36 rows selected.   

    对字段的投射是需要消耗CPU的,尤其是一些“宽表(Wide Table)”,含有大量字段,并且需要选择其中大部分字段时,CPU的消耗就更大。Row shipping就是为降低数据源生成组件在服务器消耗的CPU而在10g中引入的一个新机制。其基本思想就是将返回的记录完整的传输(ship)给客户端,并且将投射的工作由服务器端转交给客户端完成。参数_enable_row_shipping控制是否启用该特性,_row_shipping_threshold则控制当投射多少字段时激活该特性(即投射字段数小于该值时不会启用row shipping)。此外,参数_row_shipping_explain控制是否在查询计划中包含该特性是否已被激活的信息,但其并不会影响该特性是否被启用。我们看下该特性给SQL执行带来的变化:
 

SQL代码
  1. HELLODBA.COM>analyze table WIDE_TBL compute statistics for table for all columns;   
  2.   
  3. Table analyzed.   
  4.   
  5. HELLODBA.COM>select num_rows*avg_row_len from dba_tables where table_name='WIDE_TBL';   
  6.   
  7. NUM_ROWS*AVG_ROW_LEN   
  8. --------------------   
  9.                 8492   
  10.   
  11. HELLODBA.COM>set autot trace stat   
  12. HELLODBA.COM>alter session set "_enable_row_shipping" = FALSE;   
  13.   
  14. Session altered.   
  15.   
  16. HELLODBA.COM>alter session set events '10079 trace name context forever, level 2';   
  17.   
  18. Session altered.   
  19.   
  20. HELLODBA.COM>select sid,audsid from WIDE_TBL;   
  21.   
  22. 22 rows selected.   
  23.   
  24. Statistics  
  25. ----------------------------------------------------------   
  26.           1  recursive calls   
  27.           0  db block gets   
  28.           6  consistent gets   
  29.           0  physical reads   
  30.           0  redo size  
  31.         846  bytes sent via SQL*Net to client   
  32.         396  bytes received via SQL*Net from client   
  33.           3  SQL*Net roundtrips to/from client   
  34.           0  sorts (memory)   
  35.           0  sorts (disk)   
  36.          22  rows processed   
  37.   
  38. HELLODBA.COM>alter session set events '10079 trace name context off';   
  39.   
  40. Session altered.   
  41.   
  42. HELLODBA.COM>conn demo/demo@erdb   
  43. Connected.   
  44. HELLODBA.COM>set autot trace   
  45. HELLODBA.COM>alter session set "_enable_row_shipping" = TRUE;   
  46.   
  47. Session altered.   
  48.   
  49. HELLODBA.COM>alter session set "_row_shipping_explain" = TRUE;   
  50.   
  51. Session altered.   
  52.   
  53. HELLODBA.COM>alter session set "_row_shipping_threshold" = 2;   
  54.   
  55. Session altered.   
  56.   
  57. HELLODBA.COM>alter session set events '10079 trace name context forever, level 2';   
  58.   
  59. Session altered.   
  60.   
  61. HELLODBA.COM>select sid,audsid from WIDE_TBL;   
  62.   
  63. 22 rows selected.   
  64.   
  65. Execution Plan   
  66. ----------------------------------------------------------   
  67. Plan hash value: 1188828058   
  68.   
  69. ------------------------------------------------------------------------------   
  70. | Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |   
  71. ------------------------------------------------------------------------------   
  72. |   0 | SELECT STATEMENT  |          |    22 |   132 |     3   (0)| 00:00:01 |   
  73. |   1 |  TABLE ACCESS FULL| WIDE_TBL |    22 |   132 |     3   (0)| 00:00:01 |   
  74. ------------------------------------------------------------------------------   
  75.   
  76. Note   
  77. -----   
  78.    - row shipping is enabled for this statement   
  79.   
  80. Statistics  
  81. ----------------------------------------------------------   
  82.         358  recursive calls   
  83.           0  db block gets   
  84.          38  consistent gets   
  85.           0  physical reads   
  86.           0  redo size  
  87.        9223  bytes sent via SQL*Net to client   
  88.         396  bytes received via SQL*Net from client   
  89.           3  SQL*Net roundtrips to/from client   
  90.           6  sorts (memory)   
  91.           0  sorts (disk)   
  92.          22  rows processed   
  93.   
  94. HELLODBA.COM>alter session set events '10079 trace name context off';   
  95.   
  96. Session altered.  

    可以看到,因为Row Shipping影响的是Row Source Generator,所以Logical IO并没有变化。但是,从SQL*Net发送到客户端的字节数可以看到其产生的变化:尽管只需要返回2个字段的数据,Row Shipping将记录的全部字段(通过平均值大致估算为8492字节)都直接发送到了客户端,再加上字段本身的信息(名称、类型、长度),因而row shipping发送到客户端的数据是9223字节。
 

    而如果对通过10079事件捕捉到的SQLNet的内容我们也可以看出Row Shipping和传统方式的这一不同之处:
 

SQL代码
  1. ...   
  2. A798440 53038001 80015359 3016C506 FF2D2531  [...SYS.....01%-.]   
  3. A798450 4E4908FF 49544341 44094556 43494445  [..INACTIVE.DEDIC]   
  4. A798460 44455441 53038001 68075359 676E6175  [ATED...SYS.huang]   
  5. A798470 32096465 3A363932 34343737 434F4F0E  [ed.2296:7744.OOC]   
  6. A798480 5C4D444C 4E415548 07444547 4E415548  [LDM\HUANGED.HUAN]   
  7. A798490 0C444547 71736C70 7665646C 6578652E  [GED.plsqldev.exe]   
  8. A7984A0 45535504 01000152 04FFFF80 5432B92C  [.USER.......,.2T]   
  9. A7984B0 0423C506 0D146339 327A6E33 35763036  [..#.9c..3nz260v5]   
  10. A7984C0 6E717764 FF800176 10FFFFFF 532F4C50  [dwqnv.......PL/S]   
  11. A7984D0 44204C51 6C657665 7265706F 5B0CC506  [QL Developer...[]   
  12. A7984E0 0C40430E 6E69614D 73657320 6E6F6973  [.C@.Main session]   
  13. A7984F0 4A12C506 FF5B5020 480CC304 02C2031E  [...J P[....H....]   
  14. ...   

    此外,在传统方式下,为了减少网络流量,Oracle通过SQL*Net传输数据时,会先对数据进行压缩后再传输,而以row shipping传输的数据则基本没有进行压缩:
 

SQL代码
  1. HELLODBA.COM>create table WIDE_TBL2 as select a.* from WIDE_TBL a, WIDE_TBL b, WIDE_TBL c;   
  2.   
  3. Table created.   
  4.   
  5. HELLODBA.COM>analyze table WIDE_TBL2 compute statistics for table for all columns;   
  6.   
  7. Table analyzed.   
  8.   
  9. HELLODBA.COM>select num_rows*avg_row_len from dba_tables where table_name='WIDE_TBL2';   
  10.   
  11. NUM_ROWS*AVG_ROW_LEN   
  12. --------------------   
  13.              4110128   
  14.   
  15. HELLODBA.COM>conn demo/demo@erdb   
  16. Connected.   
  17. HELLODBA.COM>set autot trace stat   
  18. HELLODBA.COM>alter session set "_enable_row_shipping" = TRUE;   
  19.   
  20. Session altered.   
  21.   
  22. HELLODBA.COM>select * from WIDE_TBL2;   
  23.   
  24. 10648 rows selected.   
  25.   
  26. Statistics  
  27. ----------------------------------------------------------   
  28.           0  recursive calls   
  29.           0  db block gets   
  30.        1268  consistent gets   
  31.           0  physical reads   
  32.           0  redo size  
  33.     4260321  bytes sent via SQL*Net to client   
  34.        8184  bytes received via SQL*Net from client   
  35.         711  SQL*Net roundtrips to/from client   
  36.           0  sorts (memory)   
  37.           0  sorts (disk)   
  38.       10648  rows processed   
  39.   
  40. HELLODBA.COM>alter session set "_enable_row_shipping" = FALSE;   
  41.   
  42. Session altered.   
  43.   
  44. HELLODBA.COM>select * from WIDE_TBL2;   
  45.   
  46. Statistics  
  47. ----------------------------------------------------------   
  48.           1  recursive calls   
  49.           0  db block gets   
  50.        1268  consistent gets   
  51.           0  physical reads   
  52.           0  redo size  
  53.      258356  bytes sent via SQL*Net to client   
  54.        8184  bytes received via SQL*Net from client   
  55.         711  SQL*Net roundtrips to/from client   
  56.           0  sorts (memory)   
  57.           0  sorts (disk)   
  58.       10648  rows processed  

    可以看到,尽管是获取到表的全部内容,Row Shipping方式传输的数据量是表数据量加元数据信息之和,而传统方式下,经过压缩后传输的字节数远远小于表数据的字节数。这样做的目的也是为了减少数据压缩在服务端带来的负荷。
 

    从前面的分析看,Row Shipping带来的最大好处就是减少了Row Source Generator在服务端的消耗,按理我们可以从Row Source的相关统计数据看到这些变化,遗憾的是,如果一旦打开_rowsource_execution_statistics或者SQL Trace(10046)进行统计数据收集时,Row Shipping就不会被激活,这使得我们无法获取到相关性能统计数据做比较。
 

    --- Fuyuncat Mark ---

Top

Copyright ©2005,HelloDBA.Com 保留一切权利

申明
by fuyuncat