楼主: lastwinner

[精华] sql求解200万内质数各种算法点评

[复制链接]
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
21#
发表于 2014-3-11 20:37 | 只看该作者
貌似改为直接函数调用也没事

SQL> with
  2  t0 AS (
  3      SELECT 2*level+1 rn FROM dual connect by level <= (:n)/2-1   --原SQL为(:n)/2-1-1有误,特做此更正——by lastwinner
  4      ),
  5  t as(SELECT rn from t0 where mod(rn,3)<>0 and mod(rn,5)<>0 and mod(rn,7)<>0 and mod(rn,11)<>0 and mod(rn,13)<>0 and mod(rn,17)<>0 and mod(rn,19)<>0)
  6  SELECT COUNT(*)+1+7 --2,3,5,7,11,13,17,19
  7     FROM (SELECT rn from t
  8           MINUS
  9           SELECT t1.rn * t2.rn
10             FROM t t1, t t2
11           WHERE t1.rn <= t2.rn
12                 AND t1.rn BETWEEN 21 AND SQRT(:n)
13                 AND t1.rn * t2.rn <:n
14         )
15  ;

COUNT(*)+1+7--2,3,5,7,11,13,17,19
----------------------------------------
                                  148933

已用时间:  00: 00: 16.22

执行计划
----------------------------------------------------------
Plan hash value: 2858566071

-------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                           |     1 |       |     8   (0)| 00:00:01 |
|   1 |  TEMP TABLE TRANSFORMATION      |                           |       |       |            |          |
|   2 |   LOAD AS SELECT                | SYS_TEMP_0FD9D6618_C88BEC |       |       |            |          |
|*  3 |    VIEW                         |                           |     1 |    13 |     2   (0)| 00:00:01 |
|*  4 |     CONNECT BY WITHOUT FILTERING|                           |       |       |            |          |
|   5 |      FAST DUAL                  |                           |     1 |       |     2   (0)| 00:00:01 |
|   6 |   SORT AGGREGATE                |                           |     1 |       |            |          |
|   7 |    VIEW                         |                           |     1 |       |     6   (0)| 00:00:01 |
|   8 |     MINUS                       |                           |       |       |            |          |
|   9 |      SORT UNIQUE                |                           |     1 |    13 |     2   (0)| 00:00:01 |
|  10 |       VIEW                      |                           |     1 |    13 |     2   (0)| 00:00:01 |
|  11 |        TABLE ACCESS FULL        | SYS_TEMP_0FD9D6618_C88BEC |     1 |    13 |     2   (0)| 00:00:01 |
|  12 |      SORT UNIQUE                |                           |     1 |    26 |     4   (0)| 00:00:01 |
|* 13 |       FILTER                    |                           |       |       |            |          |
|  14 |        NESTED LOOPS             |                           |     1 |    26 |     4   (0)| 00:00:01 |
|* 15 |         VIEW                    |                           |     1 |    13 |     2   (0)| 00:00:01 |
|  16 |          TABLE ACCESS FULL      | SYS_TEMP_0FD9D6618_C88BEC |     1 |    13 |     2   (0)| 00:00:01 |
|* 17 |         VIEW                    |                           |     1 |    13 |     2   (0)| 00:00:01 |
|  18 |          TABLE ACCESS FULL      | SYS_TEMP_0FD9D6618_C88BEC |     1 |    13 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(MOD("RN",3)<>0 AND MOD("RN",5)<>0 AND MOD("RN",7)<>0 AND MOD("RN",11)<>0 AND
              MOD("RN",13)<>0 AND MOD("RN",17)<>0 AND MOD("RN",19)<>0)
   4 - filter(LEVEL<=TO_NUMBER(:N)/2-1)
  13 - filter(SQRT(TO_NUMBER(:N))>=21)
  15 - filter("T1"."RN">=21 AND "T1"."RN"<=SQRT(TO_NUMBER(:N)))
  17 - filter("T1"."RN"<="T2"."RN" AND "T1"."RN"*"T2"."RN"<TO_NUMBER(:N) AND "T2"."RN">=21)


统计信息
----------------------------------------------------------
         13  recursive calls
        535  db block gets
     124484  consistent gets
        520  physical reads
        660  redo size
        381  bytes sent via SQL*Net to client
        472  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          3  sorts (memory)
          0  sorts (disk)
          1  rows processed

使用道具 举报

回复
求职 : 数据库开发
论坛徽章:
7
2013年新春福章
日期:2013-02-25 14:51:24ITPUB社区千里马徽章
日期:2013-06-09 10:15:34宝马
日期:2013-09-17 17:12:562014年新春福章
日期:2014-02-18 16:49:31马上有钱
日期:2014-02-18 16:49:31马上加薪
日期:2014-04-25 19:34:55
22#
发表于 2014-3-11 21:58 | 只看该作者
学习。。。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
23#
 楼主| 发表于 2014-3-12 01:08 | 只看该作者
〇〇 发表于 2014-3-11 20:15
这个写法是故意的吗?
AND (SELECT SQRT(:n) FROM DUAL)

可以直接写为SQRT(:n)
我比较过,时间上没差别

使用道具 举报

回复
论坛徽章:
0
24#
发表于 2014-3-12 11:21 | 只看该作者
helonten 发表于 2014-3-10 08:27
这种分析问题的方法非常值得我们学习

学习了啊,值得学习

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
25#
 楼主| 发表于 2014-3-19 02:20 | 只看该作者
增加了“8、分段求解”,详见8楼

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
26#
 楼主| 发表于 2014-3-19 02:24 | 只看该作者
lastwinner 发表于 2014-3-10 04:04
8、分段求解
虽然sql没法像pl/sql那样有效的利用之前的计算结果,但部分做到还是可行的吧?我们来尝试一下 ...

但newkid的写法不能使用此思路,想想看为什么?

如果没想出来,那么看看如下的sql,其中 :n 赋值为400000,看看输出结果,就能大概想明白了
with b as (select 1 r from dual union all select 2 from dual),
c as (select rownum from b,b,b,b,b),
d as (select rownum from c,c,c,c),
e as (select rownum rn from d), --只需要一半
t0 AS (
    SELECT 2*rn+1 rn FROM e where rn <= (:n)/2-1   --原SQL为(:n)/2-1-1有误,特做此更正——by lastwinner
    ),
t1 as(SELECT rn from t0 where mod(rn,3)<>0 and mod(rn,5)<>0 and mod(rn,7)<>0 and mod(rn,11)<>0 and mod(rn,13)<>0 and mod(rn,17)<>0 and mod(rn,19)<>0),
u1 as (select rn from t1 where rn<=sqrt(:n)),
u2 as (select rn from t1 where rn>sqrt(:n) and rn<=:n),
v1 as (SELECT rn from u1
         MINUS
         SELECT t1.rn * t2.rn
           FROM u1 t1, u1 t2
         WHERE t1.rn <= t2.rn
               AND t1.rn BETWEEN 21 AND sqrt(SQRT(:n))+1
               AND t1.rn * t2.rn <=sqrt(:n)+1),
u3 as (select * from u2 union select * from v1),
v2 as (SELECT rn from u2
         MINUS
         SELECT t1.rn * t2.rn
           FROM v1 t1, u3 t2
         WHERE t1.rn <= t2.rn
               AND t1.rn BETWEEN 21 AND SQRT(:n)
               AND
               t1.rn * t2.rn <=:n)
, u as (select rn n from t1)
, z as (select * from u minus
select * from u a where exists (select /*+ USE_MERGE (a b)*/ 0 from u b where b.n<=sqrt(a.n) and mod(a.n, b.n)=0))
select * from v2 minus select * from z
/

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
27#
发表于 2014-3-19 03:22 | 只看该作者
有哪种方法能比PLSQL相比吗?

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
28#
发表于 2014-3-19 06:28 | 只看该作者
newkid 发表于 2014-3-19 03:22
有哪种方法能比PLSQL相比吗?

java

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
29#
 楼主| 发表于 2014-3-19 11:46 | 只看该作者
newkid 发表于 2014-3-19 03:22
有哪种方法能比PLSQL相比吗?

目前最快的是你的筛选法
但我相信,当N大到一定程度后,比如超过10亿,我的分段求解法的效率会更高
因为随着数字的增大,质数会越来越稀疏,而筛选法所需要做的乘法会越来越多,这会导致筛选效率快速下降

至于是不是存在一个临界点N,使得我在8#中的分段求解能优于筛选法,还不好下结论

使用道具 举报

回复
论坛徽章:
2
2012新春纪念徽章
日期:2012-01-04 11:54:26优秀写手
日期:2014-02-20 06:00:12
30#
发表于 2014-3-21 15:53 | 只看该作者
牛啊,分析很相近,很高深。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表