避免動態SQL(一)

LuiseDalian發表於2014-01-16
動態SQL在執行過程中編譯,而普通SQL是在執行前就已經編譯過了。
案例1

點選(此處)摺疊或開啟

  1. --create.sql
  2. --建立Luise使用者和相應的優化指令碼包
  3. conn / as sysdba;

  4. drop user luise cascade;
  5. CREATE USER luise IDENTIFIED BY luise;
  6. GRANT DBA TO luise;
  7. grant select any dictionary to luise;

  8. conn luise/luise

  9. CREATE OR REPLACE VIEW STATS AS
  10. SELECT \'STAT...\' || a.name AS name, b.value FROM v$statname a, v$mystat b WHERE a.statistic# = b.statistic#
  11. UNION ALL
  12. SELECT \'LATCH.\' || name, gets FROM v$latch;

  13. ---------------------------------------------------------------------------------------
  14. DROP TABLE run_stats;
  15. CREATE GLOBAL TEMPORARY TABLE run_stats
  16. (
  17.   runid VARCHAR2(15),
  18.   name VARCHAR2(80),
  19.   value INT
  20. )ON COMMIT PRESERVE ROWS;

  21. --------------------------------------------------------------------------------------
  22. CREATE OR REPLACE PACKAGE runstats_pkg
  23. AS
  24. PROCEDURE rs_start;
  25. PROCEDURE rs_middle;
  26. PROCEDURE rs_stop(p_difference_threshold IN NUMBER DEFAULT 0);
  27. END;
  28. /
  29.     
  30. ----------------------------------------------------------------------------------------
  31. CREATE OR REPLACE PACKAGE BODY runstats_pkg
  32. AS
  33.   g_start NUMBER;
  34.   g_run1 NUMBER;
  35.   g_run2 NUMBER;

  36.   PROCEDURE rs_start
  37.   IS
  38.   BEGIN
  39.     DELETE FROM run_stats;
  40.     INSERT INTO run_stats
  41.     SELECT \'before\', stats.* FROM stats;
  42.     g_start := dbms_utility.get_time;
  43. END;


  44.   PROCEDURE rs_middle
  45.   IS
  46.   BEGIN
  47.     g_run1 := (dbms_utility.get_time - g_start);
  48.     INSERT INTO run_stats SELECT \'after 1\', stats.* FROM stats;
  49.     g_start := dbms_utility.get_time;
  50.   END;

  51.   PROCEDURE rs_stop(p_difference_threshold IN NUMBER DEFAULT 0)
  52.   IS
  53.   BEGIN
  54.     g_run2 := (dbms_utility.get_time - g_start);
  55.     dbms_output.put_line(\'Run1 ran in \' || g_run1 || \'hsec\');
  56.     dbms_output.put_line(\'Run2 ran in \' || g_run2 || \'hsec\');
  57.     dbms_output.put_line(\'run 1 ran in \' || round(g_run1/g_run2 * 100, 2)|| \'% of the time\');
  58.     dbms_output.put_line(chr(9));
  59.  
  60.     INSERT INTO run_stats SELECT \'after 2\',stats.* FROM STATS;
  61.     dbms_output.put_line(rpad(\'Name\',30) || lpad(\'Run1\',10)|| lpad(\'Run2\',10) || lpad(\'Diff\',10));

  62.     FOR x IN(SELECT rpad(a.name,30) || to_char(b.value - a.value,\'9,999,999\') ||
  63.                          to_char(c.value-b.value,\'9,999,999\') ||
  64.                          to_char(((c.value - b.value)-(b.value - a.value)),\'9,999,999\') AS data
  65.              FROM run_stats a, run_stats b, run_stats c
  66.              WHERE a.name = b.name
  67.                AND b.name=c.name
  68.                AND a.runid=\'before\'
  69.                AND b.runid=\'after 1\'
  70.                AND c.runid=\'after 2\'
  71.                AND (c.value - a.value) > 0
  72.                AND abs((c.value - b.value) - (b.value - a.value)) > p_difference_threshold
  73.              ORDER BY abs((c.value - b.value) - (b.value - a.value)))
  74.     LOOP
  75.       dbms_output.put_line(x.data);
  76.     END LOOP;

  77.     dbms_output.put_line(chr(9));
  78.     dbms_output.put_line(\'Run1 latches total versus runs ----difference and pct\');
  79.     dbms_output.put_line(lpad(\'Run1\',10) || lpad(\'Run2\',10) || lpad(\'Diff\',10) || lpad(\'Pct\',8));

  80.     FOR x IN(SELECT to_char(run1,\'9,999,999\') || to_char(run2,\'9,999,999\') ||
  81.                     to_char(diff,\'9,999,999\') || to_char(round(run1/run2*100, 2), \'999.99\') || \'%\' AS DATA
  82.              FROM (SELECT sum(b.value-a.value) AS run1, sum(c.value-b.value) AS run2,
  83.                      sum((c.value - b.value) - (b.value - a.value)) AS diff
  84.                    FROM run_stats a, run_stats b, run_stats c
  85.                    WHERE a.name = b.name
  86.                    AND b.name = c.name
  87.                    AND a.runid = \'before\'
  88.                    AND b.runid = \'after 1\'
  89.                    AND c.runid = \'after 2\'
  90.                    AND a.name LIKE \'LATCH%\'))
  91.     LOOP
  92.       dbms_output.put_line(x.data);
  93.     END LOOP;
  94.   END;
  95. END;
  96. /
  97. --下面的實驗是為了說明動態SQL在效能上不如靜態SQL
  98. CREATE TABLE t(col1 NUMBER(10));
  99. INSERT INTO t SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 100000;
  100. COMMIT;

  101. set serveroutput on;
  102. luise@TESTDB11>exec runstats_pkg.rs_start;
  103. --動態SQL
  104. BEGIN
  105.   EXECUTE IMMEDIATE \'DELETE FROM t\';
  106.   COMMIT;
  107. END;
  108. /

  109. alter system flush shared_pool;
  110. alter system flush buffer_cache;
  111. truncate table t;
  112. INSERT INTO t SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 100000;
  113. COMMIT;

  114. luise@TESTDB11>exec runstats_pkg.rs_middle;
  115. --靜態SQL
  116. BEGIN
  117.   DELETE FROM t;
  118.   COMMIT;
  119. END;
  120. /

  121. luise@TESTDB11>exec runstats_pkg.rs_stop(5000);
  122. Run1 ran in 32048hsec
  123. Run2 ran in 6504hsec
  124. run 1 ran in 492.74% of the time
  125.         
  126. Name Run1 Run2 Diff
  127. STAT...buffer is not pinned co 5,447 306 -5,141
  128. STAT...buffer is not pinned co 5,447 173 -5,274
  129. STAT...buffer is not pinned co 5,447 173 -5,274
  130. STAT...buffer is not pinned co 5,447 173 -5,274
  131. STAT...sorts (rows) 6,264 852 -5,412
  132. STAT...consistent gets 7,108 1,666 -5,442
  133. STAT...consistent gets from ca 7,108 1,666 -5,442
  134. STAT...sorts (rows) 6,264 751 -5,513
  135. LATCH.enqueue hash chains 7,070 1,251 -5,819
  136. STAT...consistent gets from ca 7,108 1,209 -5,899
  137. STAT...consistent gets 7,108 1,209 -5,899
  138. STAT...recursive calls 6,641 704 -5,937
  139. LATCH.enqueue hash chains 7,070 1,078 -5,992
  140. STAT...sorts (rows) 6,264 216 -6,048
  141. LATCH.SQL memory manager worka 7,575 1,457 -6,118
  142. STAT...consistent gets from ca 7,108 977 -6,131
  143. STAT...consistent gets 7,108 977 -6,131
  144. STAT...recursive calls 6,641 504 -6,137
  145. STAT...recursive calls 6,641 495 -6,146
  146. STAT...recursive calls 6,641 459 -6,182
  147. STAT...sorts (rows) 6,264 7 -6,257
  148. LATCH.enqueue hash chains 7,070 788 -6,282
  149. LATCH.enqueue hash chains 7,070 689 -6,381
  150. LATCH.SQL memory manager worka 7,575 1,178 -6,397
  151. STAT...consistent gets from ca 7,108 617 -6,491
  152. STAT...consistent gets 7,108 617 -6,491
  153. LATCH.SQL memory manager worka 7,575 830 -6,745
  154. LATCH.SQL memory manager worka 7,575 673 -6,902
  155. LATCH.shared pool simulator 6,952 48 -6,904
  156. LATCH.shared pool simulator 6,952 40 -6,912
  157. LATCH.shared pool simulator 6,952 34 -6,918
  158. LATCH.shared pool simulator 6,952 17 -6,935
  159. STAT...file io wait time 8,172 1,166 -7,006
  160. STAT...file io wait time 8,172 555 -7,617
  161. STAT...file io wait time 8,172 555 -7,617
  162. STAT...file io wait time 8,172 267 -7,905
  163. LATCH.cache buffers lru chain 11,348 3,372 -7,976
  164. LATCH.cache buffers lru chain 11,348 3,356 -7,992
  165. LATCH.cache buffers lru chain 11,348 3,343 -8,005
  166. LATCH.cache buffers lru chain 11,348 3,330 -8,018
  167. LATCH.object queue header oper 27,193 5,798 -21,395
  168. LATCH.object queue header oper 27,193 5,778 -21,415
  169. LATCH.object queue header oper 27,193 5,758 -21,435
  170. LATCH.object queue header oper 27,193 5,744 -21,449
  171. LATCH.shared pool 60,100 1,563 -58,537
  172. LATCH.shared pool 60,100 1,394 -58,706
  173. LATCH.shared pool 60,100 1,165 -58,935
  174. LATCH.shared pool 60,100 531 -59,569
  175. STAT...session pga memory max 65,536 0 -65,536
  176. STAT...session pga memory max 65,536 0 -65,536
  177. STAT...session pga memory max 65,536 0 -65,536
  178. STAT...session pga memory max 65,536 0 -65,536
  179. LATCH.row cache objects 84,484 1,689 -82,795
  180. LATCH.row cache objects 84,484 1,424 -83,060
  181. LATCH.row cache objects 84,484 1,008 -83,476
  182. LATCH.row cache objects 84,484 593 -83,891
  183. STAT...session logical reads 115,455 208,500 93,045
  184. STAT...session logical reads 115,455 208,901 93,446
  185. STAT...session logical reads 115,455 209,180 93,725
  186. STAT...session logical reads 115,455 209,678 94,223
  187. STAT...redo entries 103,487 201,299 97,812
  188. STAT...redo entries 103,487 201,314 97,827
  189. STAT...redo entries 103,487 201,329 97,842
  190. STAT...redo entries 103,487 201,344 97,857
  191. STAT...buffer is pinned count 100,965 199,710 98,745
  192. STAT...buffer is pinned count 100,965 199,710 98,745
  193. STAT...buffer is pinned count 100,965 199,710 98,745
  194. STAT...buffer is pinned count 100,965 199,710 98,745
  195. STAT...HSC Heap Segment Block 101,118 200,015 98,897
  196. STAT...HSC Heap Segment Block 101,118 200,030 98,912
  197. STAT...HSC Heap Segment Block 101,118 200,045 98,927
  198. STAT...HSC Heap Segment Block 101,118 200,060 98,942
  199. STAT...db block gets 108,347 207,883 99,536
  200. STAT...db block gets from cach 108,347 207,883 99,536
  201. STAT...db block gets from cach 108,347 207,924 99,577
  202. STAT...db block gets 108,347 207,924 99,577
  203. STAT...db block gets from cach 108,347 207,971 99,624
  204. STAT...db block gets 108,347 207,971 99,624
  205. STAT...db block gets from cach 108,347 208,012 99,665
  206. STAT...db block gets 108,347 208,012 99,665
  207. STAT...table scan rows gotten 122,040 229,260 107,220
  208. STAT...session uga memory max 130,952 0 -130,952
  209. STAT...session uga memory max 130,952 0 -130,952
  210. STAT...session uga memory max 130,952 0 -130,952
  211. STAT...session uga memory max 130,952 0 -130,952
  212. STAT...table scan rows gotten 122,040 272,388 150,348
  213. STAT...session uga memory 158,352 0 -158,352
  214. STAT...table scan rows gotten 122,040 301,140 179,100
  215. STAT...session uga memory 158,352 -38,096 -196,448
  216. STAT...session uga memory 158,352 -38,096 -196,448
  217. STAT...session uga memory 158,352 -38,096 -196,448
  218. STAT...db block changes 206,351 404,116 197,765
  219. STAT...db block changes 206,351 404,176 197,825
  220. STAT...db block changes 206,351 404,246 197,895
  221. STAT...db block changes 206,351 404,305 197,954
  222. STAT...table scan rows gotten 122,040 337,080 215,040
  223. STAT...session pga memory 262,144 0 -262,144
  224. STAT...redo synch time (usec) 458,442 148,810 -309,632
  225. STAT...redo synch time (usec) 458,442 148,810 -309,632
  226. STAT...redo synch time (usec) 458,442 148,810 -309,632
  227. STAT...redo synch time (usec) 458,442 148,810 -309,632
  228. LATCH.cache buffers chains 727,405 1,221,577 494,172
  229. LATCH.cache buffers chains 727,405 1,222,490 495,085
  230. LATCH.cache buffers chains 727,405 1,223,807 496,402
  231. LATCH.cache buffers chains 727,405 1,224,848 497,443
  232. STAT...cell physical IO interc 2,646,016 212,992-2,433,024
  233. STAT...physical read bytes 2,646,016 212,992-2,433,024
  234. STAT...physical read total byt 2,646,016 212,992-2,433,024
  235. STAT...physical read total byt 2,646,016 131,072-2,514,944
  236. STAT...physical read total byt 2,646,016 131,072-2,514,944
  237. STAT...physical read bytes 2,646,016 131,072-2,514,944
  238. STAT...physical read bytes 2,646,016 131,072-2,514,944
  239. STAT...cell physical IO interc 2,646,016 131,072-2,514,944
  240. STAT...cell physical IO interc 2,646,016 131,072-2,514,944
  241. STAT...physical read bytes 2,646,016 73,728-2,572,288
  242. STAT...physical read total byt 2,646,016 73,728-2,572,288
  243. STAT...cell physical IO interc 2,646,016 73,728-2,572,288
  244. STAT...undo change vector size##############################
  245. STAT...undo change vector size##############################
  246. STAT...undo change vector size##############################
  247. STAT...undo change vector size##############################
  248. STAT...redo size ##############################
  249. STAT...redo size ##############################
  250. STAT...redo size ##############################
  251. STAT...redo size ##############################
  252. STAT...logical read bytes from##############################
  253. STAT...logical read bytes from##############################
  254. STAT...logical read bytes from##############################
  255. STAT...logical read bytes from##############################
  256.         
  257. Run1 latches total versus runs ----difference and pct
  258. Run1 Run2 Diff Pct
  259. 3,879,348 5,027,245 1,147,897 77.17%

  260. PL/SQL procedure successfully completed.
  261. --結論: 動態SQL的時間為靜態SQL的492.74%,還可以看出動態SQL在栓鎖、物理讀等的消耗上大大超過了靜態
  262. --     SQL語句. 因此要儘可能地尋找將動態SQL轉換為靜態SQL的機會,即使因此導致程式碼更復雜也是值得的.

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

相關文章