Decode360's Blog

          業(yè)精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          用SQL計算100以內(nèi)的質(zhì)數(shù)
          ?
          ??? 蠻有意思的一段SQL,拿來看一下。
          ?

          ===========================================================
          作者: yangtingkun(
          http://yangtingkun.itpub.net )
          發(fā)表于: 2008.01.07 23:23
          分類: ORACLE
          出處:
          http://yangtingkun.itpub.net/post/468/450278
          -----------------------------------------------------------
          ?
          ??? 以前寫過一篇文章,描述如何使用PL/SQL來計算100以內(nèi)的質(zhì)數(shù),今天重翻那篇文章的時候,突然想到,能不能用SQL來實現(xiàn)同樣的功能。
          ?
          ??? PLSQL計算質(zhì)數(shù): http://yangtingkun.itpub.net/post/468/53770
          ?
          ?
          ?
          ?
          ??? 其實這個功能用PLSQL實現(xiàn)最簡單,思路也很清晰,判斷一個數(shù)是否是質(zhì)數(shù),只需要檢查這個數(shù)能否被比它小的質(zhì)數(shù)整除就可以了。但是這種操作通過SQL來實現(xiàn)就十分的困難,因此這里通過另外一種方式來實現(xiàn)這個功能——構(gòu)造。
          ?
          通過查詢100以內(nèi)的數(shù),去掉所有的合數(shù),剩下的就是質(zhì)數(shù)了:
          ?
          SQL> WITH T
          ? 2 AS
          ? 3 (SELECT ROWNUM RN FROM DUAL CONNECT BY LEVEL < 100)
          ? 4 SELECT RN FROM T
          ? 5 WHERE RN > 1
          ? 6 MINUS
          ? 7 SELECT A.RN * B.RN FROM T A, T B
          ? 8 WHERE A.RN <= B.RN
          ? 9 AND A.RN > 1
          ?10 AND B.RN > 1;
          ?
          ??????? RN
          ----------
          ???????? 2
          ???????? 3
          ???????? 5
          ???????? 7
          ??????? 11
          ??????? 13
          ??????? 17
          ??????? 19
          ??????? 23
          ??????? 29
          ??????? 31
          ??????? 37
          ??????? 41
          ??????? 43
          ??????? 47
          ??????? 53
          ??????? 59
          ??????? 61
          ??????? 67
          ??????? 71
          ??????? 73
          ??????? 79
          ??????? 83
          ??????? 89
          ??????? 97
          ?
          25 rows selected.
          ?
          ?
          ?
          但是這種方法的效率明顯要比PL/SQL的效率要低,如果取10000以內(nèi)的質(zhì)數(shù):
          ?
          ?
          SQL> SET TIMING ON
          SQL> SET AUTOT TRACE STAT
          SQL> WITH T
          ? 2 AS
          ? 3 (SELECT ROWNUM RN FROM DUAL CONNECT BY LEVEL < 10000)
          ? 4 SELECT RN FROM T
          ? 5 WHERE RN > 1
          ? 6MINUS
          ? 7 SELECT A.RN * B.RN FROM T A, T B
          ? 8 WHERE A.RN <= B.RN
          ? 9 AND A.RN > 1
          ?10AND B.RN > 1;
          ?
          1229 rows selected.
          ?
          Elapsed: 00:02:41.54
          ?
          Statistics
          ----------------------------------------------------------
          ??????? 511 recursive calls
          ???????? 81 db block gets
          ???? 180002 consistent gets
          ????? 65131 physical reads
          ??????? 648 redo size
          ????? 17139 bytes sent via SQL*Net to client
          ?????? 1276 bytes received via SQL*Net from client
          ???????? 83 SQL*Net roundtrips to/from client
          ????????? 2 sorts (memory)
          ????????? 1 sorts (disk)
          ?????? 1229 rows processed
          ?
          ?
          這個SQL執(zhí)行了2分半種以上,當(dāng)然這個SQL還可以進(jìn)行一下優(yōu)化,比如A的取值可以小于10000的開方,而B的取值可以小于10000除以最小的質(zhì)數(shù):
          ?
          ?
          SQL> WITH T
          ? 2 AS
          ? 3 (SELECT ROWNUM RN FROM DUAL CONNECT BY LEVEL < 10000)
          ? 4 SELECT RN FROM T
          ? 5 WHERE RN > 1
          ? 6 MINUS
          ? 7 SELECT A.RN * B.RN FROM T A, T B
          ? 8 WHERE A.RN <= B.RN
          ? 9AND A.RN > 1
          ?10 AND A.RN <= 100
          ?11 AND B.RN > 1
          ?12 AND B.RN <= 5000;
          ?
          1229 rows selected.
          ?
          Elapsed: 00:00:00.78
          ?
          Statistics
          ----------------------------------------------------------
          ????????? 2 recursive calls
          ???????? 23 db block gets
          ?????? 1820 consistent gets
          ???????? 16 physical reads
          ??????? 692 redo size
          ????? 17139 bytes sent via SQL*Net to client
          ?????? 1276 bytes received via SQL*Net from client
          ???????? 83 SQL*Net roundtrips to/from client
          ????????? 3 sorts (memory)
          ????????? 0 sorts (disk)
          ?????? 1229 rows processed
          ?
          ?
          優(yōu)化后,SQL的執(zhí)行效率提高了3個數(shù)量級,其實這個SQL仍然是可以優(yōu)化的,考慮除了2以外,所有的質(zhì)數(shù)均為奇數(shù):
          ?
          ?
          SQL> WITH T
          ? 2 AS
          ? 3 (SELECT ROWNUM * 2 + 1 RN FROM DUAL CONNECT BY LEVEL < 4999)
          ? 4 SELECT 2 FROM DUAL
          ? 5 UNION ALL
          ? 6 (
          ? 7 SELECT RN FROM T
          ? 8 WHERE RN > 1
          ? 9 MINUS
          ?10 SELECT A.RN * B.RN FROM T A, T B
          ?11 WHERE A.RN <= B.RN
          ?12 AND A.RN > 1
          ?13 AND A.RN <= 100
          ?14 AND B.RN > 1
          ?15 AND B.RN <= 5000
          ?16 )
          ?17 ;
          ?
          1229 rows selected.
          ?
          Elapsed: 00:00:00.25
          ?
          Statistics
          ----------------------------------------------------------
          ????????? 2 recursive calls
          ???????? 15 db block gets
          ??????? 512 consistent gets
          ????????? 8 physical reads
          ??????? 648 redo size
          ????? 17138 bytes sent via SQL*Net to client
          ?????? 1276 bytes received via SQL*Net from client
          ???????? 83 SQL*Net roundtrips to/from client
          ????????? 3 sorts (memory)
          ????????? 0 sorts (disk)
          ?????? 1229 rows processed
          ?
          雖然通過SQL優(yōu)化已經(jīng)將極大的提高了效率,但是和PLSQL比,效率仍然相去甚遠(yuǎn):
          ?
          ?
          ?
          SQL> DECLARE
          ? 2 TYPE T_RECORD IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
          ? 3 V_RESULT T_RECORD;
          ? 4 I NUMBER DEFAULT 3;
          ? 5 N NUMBER DEFAULT 0;
          ? 6 BEGIN
          ? 7 --DBMS_OUTPUT.PUT_LINE(2);
          ? 8 V_RESULT(1) := 3;
          ? 9 WHILE(I < 10000) LOOP
          ?10 FOR J IN 1..V_RESULT.COUNT LOOP
          ?11 IF V_RESULT(J) * V_RESULT(J) > I THEN
          ?12 --DBMS_OUTPUT.PUT_LINE(I);
          ?13 V_RESULT(V_RESULT.COUNT + 1) := I;
          ?14 EXIT;
          ?15 END IF;
          ?16 IF TRUNC(I/V_RESULT(J)) = I/V_RESULT(J) THEN
          ?17 EXIT;
          ?18END IF;
          ?19 END LOOP;
          ?20 IF N = 2 THEN
          ?21 I := I + 4;
          ?22 N := 1;
          ?23 ELSE
          ?24 I := I + 2;
          ?25 N := N + 1;
          ?26 END IF;
          ?27 END LOOP;
          ?28 V_RESULT(0) := 2;
          ?29 END;
          ?30 /
          ?
          PL/SQL procedure successfully completed.
          ?
          Elapsed: 00:00:00.04
          ?
          這說明使用SQL并不一定就是最佳選擇,有的時候使用PLSQL效率反而會更高。使用合適的方法做適合的事情,一味追求使用單條SQL實現(xiàn)很可能會損失性能。
          ?

          ?
          posted on 2008-12-27 21:31 decode360 閱讀(353) 評論(0)  編輯  收藏 所屬分類: 05.SQL
          主站蜘蛛池模板: 和平区| 分宜县| 弥勒县| 区。| 通河县| 新巴尔虎左旗| 岗巴县| 山西省| 新津县| 阿克陶县| 家居| 兰坪| 三河市| 新平| 景谷| 尖扎县| 永顺县| 明溪县| 神池县| 阿瓦提县| 灌阳县| 宜兴市| 遵化市| 洪雅县| 通化市| 平昌县| 肇庆市| 曲周县| 成武县| 邯郸市| 阳谷县| 大邑县| 太保市| 静海县| 石城县| 确山县| 进贤县| 鄄城县| 平安县| 革吉县| 南澳县|