<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>seasar</title>
    <description>seasar,a beautiful and powfull Framework of java without little configration.Less config,More happiness</description>
    <link>http://seasar.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>How do you become an expert?</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/210068" style="color:red;">http://seasar.javaeye.com/blog/210068</a>&nbsp;
          发表时间: 2008年07月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>How do you become an expert?</p>
<p><em>The answer is the same in all the fields I've seen:</em>
<p>&nbsp;&nbsp;&nbsp;&nbsp; Andrew Koenig</p>
</p>
<li>1. Learn the basics. </li>
<li>2. Study the same material again - but this time , concentrate on the details you didn't realize were important the first time around. </li>
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/210068#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 Jul 2008 11:29:21 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/210068</link>
        <guid>http://seasar.javaeye.com/blog/210068</guid>
      </item>
      <item>
        <title>程序语言的新星:走近Erlang的世界</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/202913" style="color:red;">http://seasar.javaeye.com/blog/202913</a>&nbsp;
          发表时间: 2008年06月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>　　提起Erlang语言，相信许多人都会挠头，因为它实在是太陌生了。在2007年6月由TIOBE Programming Community提供的程序语言排名中，Erlang占有率仅为0.08%，排名第49位。与之形成鲜明对比的是，Java以20.025%的占有率高居榜首，紧随其后的是C（15.967%）、C++（11.118%）、VB （9.332%）、PHP（8.871%）、Perl（6.177%）、C#（3.483%）、Python（3.161%）、JavaScript （2.616%）和Ruby（2.132%）。相对于传统老牌&ldquo;大佬&rdquo;语言相比，Erlang语言绝对算得上是一种&ldquo;小众&rdquo;语言，但其未来的发展前景却是无法估量的，因为它可以解决传统语言很难解决在并行计算中的难题，甚至有专家预言可能成为下一个Java，在正在迅猛发展的并行计算时代，Erlang将会迅速的崛起。</p>
<p>　　<strong>认识Erlang</strong></p>
<p>　　Erlang并非一门新语言，它出现于1987年，只是当时对并发、分布式需求还没有今天这么普遍，当时可谓英雄无用武之地。Erlang语言创始人Joe Armstrong当年在爱立信做电话网络方面的开发，他使用Smalltalk，可惜那个时候Smalltalk太慢，不能满足电话网络的高性能要求。但Joe实在喜欢Smalltalk，于是定购了一台Tektronix Smalltak机器。但机器要两个月时间才到，Joe在等待中百无聊赖，就开始使用Prolog，结果等Tektronix到来的时候，他已经对 Prolog更感兴趣，Joe当然不满足于精通Prolog，经过一段时间的试验，Joe给Prolog加上了并发处理和错误恢复，于是Erlang就诞生了。这也是为什么Erlang的语法和Prolog有不少相似之处，比如它们的List表达都是[Head | Tail]。</p>
<p>　　1987年Erlang测试版推出，并在用户实际应用中不断完善，于1991年向用户推出第一个版本，带有了编译器和图形接口等更多功能。1992年，Erlang迎来更多用户，如RACE项目等。同期Erlang被移植到 VxWorks、PC和 Macintosh等多种平台，两个使用Erlang的产品项目也开始启动。1993爱立信公司内部独立的组织开始维护和支持Erlang实现和 Erlang工具。</p>
<p>　　目前，随着网络应用的兴起，对高并发、分布部署、持续服务的需求增多，Erlang的特性刚好满足这些需求，于是Erlang开始得到更多人的关注。</p>
<p>　　<strong>Erlang特性</strong></p>
<p>　　Erlang是一种函数式语言，使用Erlang编写出的应用运行时通常由成千上万个轻量级进程组成，并通过消息传递相互通讯。使用Erlang来编写分布式应用比其它语言简单许多，因为它的分布式机制是透明的，即对于程序而言并不知道自己是在分布式运行。Erlang运行环境是一个虚拟机，有点类似于Java虚拟机，代码一经编译，同样可以随处运行。它的运行时系统甚至允许代码在不被中断的情况下更新。另外如果需要更高效的话，字节代码也可以编译成本地代码运行。</p>
<p align="center"><img src="http://www.lupaworld.com/attachments/2007/12/22802_200712200918411.jpg" alt="" /></p>
<p class="pictext" align="center">Erlang的结构图</p>
<p>　　相较于其它语言，Erlang有很多天生的适应现代网络服务需求的特性:</p>
<p>　　◆并发性，Erlang具有超强的轻量级进程，这种进程对内存的需求是动态变化的，并且它没有共享内存和通过异步消息传送的通讯。Erlang支持超大量级的并发线程，并且不需要操作系统具有并发机制。</p>
<p>　　◆分布式，Erlang被设计用于运行在分布式环境下。一个Erlang虚拟机被成为Erlang节点。一个分布式Erlang系统是多个Erlang节点组成的网络（通常每个处理器被作为一个节点）。一个Erlang节点能够创建运行在其它节点上的并行线程，而其它节点可以使用其余的操作系统。线程依赖不同节点之间的通讯，这完全和它依赖于单一节点一样。</p>
<p>　　◆ 软实时性 Erlang支持可编程的&ldquo;软&rdquo;实时系统，这种系统需要反应时间在毫秒级。而在这种系统中，长时间的垃圾收集（garbage collection）延迟是无法接受的，因此Erlang使用了递增式垃圾收集技术。</p>
<p>　　◆ 热代码升级 一些系统不能由于软件维护而停止运行。Erlang允许程序代码在运行系统中被修改。旧代码能被逐步淘汰而后被新代码替换。在此过渡期间，新旧代码是共存的。这也使得安装Bug补丁、在运行系统上升级而不干扰系统操作成为了可能。</p>
<p>　　◆ 递增式代码装载 用户能够控制代码如何被装载的细节。在嵌入式系统中，所有代码通常是在启动时就被完全装载。而在开发系统中，代码是按需装载的，甚至在系统运行时被装载。如果测试到了未覆盖的Bug，只需替换具有Bug的代码即可。</p>
<p>　　<strong>Erlang应用场合</strong></p>
<p>　　未来的计算是并发计算。现今甚至桌面CPU也是多核的，当用户给服务器购买了越来越多的CPU时，他们更期望能最大限度地利用他们的新投资，但是今天的许多软件系统并不能很好地做到这一点。</p>
<p>　　整个软件行业也在发生重大变革，由卖工具软件转向卖服务（软件免费，这也是开源软件兴起的过程），由单纯客户端向B/S或C/S转化，相应的存储和计算向服务器端转移，由原来的PC客户端向客户端多元化（如手机、PDA、电视机顶盒等）转化。这些变革趋势，使得用户可以更方便地访问到服务的同时，服务器也要承受越来越高的负荷，并行/分布的需求逐渐增加。</p>
<p>　　Erlang语言不是用来解决所有问题的语言，至少现在还不是。Erlang最初专门为通信应用设计的，比如控制交换机或者变换协议等，非常适合于构建分布式，实时软并行计算系统。它是一门专注的语言，可以适应现代服务器要求高负荷、高可靠、持续服务的需求。它要解决的问题域包括:高并发、分布式、持续服务、热升级和高可靠等问题。</p>
<p>　　<strong>Erlang应用实例</strong></p>
<p>　　典型的Erlang应用是由很多被分配不同任务的&ldquo;节点(Node)&rdquo;组成的&ldquo;集群 (Cluster)&rdquo;。一个Erlang节点就是一个Erlang虚拟机的实例，用户可以在一台机器(服务器、台式机或者笔记本)上运行多个节点。 Erlang节点自动跟踪所有连接着的其他节点。要添加一个节点仅仅需要将其指向任何一个已建节点就可以了。只要这两个节点建立了连接，所有其他节点马上就会感应到新加入的节点。Erlang进程使用进程ID向其他进程传递报文，进程ID包含着运行此进程的节点信息。因此进程不需要理会正在与其交流的其他进程实际在何处运行。一组相互连接的Erlang节点可以看作是一个网格计算体或者一台超级计算机。</p>
<p align="center"><img src="http://www.lupaworld.com/attachments/2007/12/22802_200712200923041.jpg" alt="" /></p>
<p class="pictext" align="center">erlang的odbc应用程序结构图</p>
<p>　　Yaws是一个Erlang写的Web服务器。ErLang本身带有一个HTTP Server,叫做inet。Yaws对于inet，就相当于Servlet对于Http Server。Yaws也可说是一个Web开发框架，Yaws的ehtml类似于jsp、 php、ruby template。Yaws并发能力是Apache的15倍，有人利用16台集群服务器所做的显示，Yaws可以承受超八万并发活动，Apache在四千就宕机了。</p>
<p align="center"><img src="http://www.lupaworld.com/attachments/2007/12/22802_200712200923451.jpg" alt="" /></p>
<p class="pictext" align="center">erlang和ruby的简单测试</p>
<p>　　Ejabberd也是Erlang很好的应用实例，也是目前可扩展性最好的一种 Jabber/XMPP服务器，支持分布多个服务器，并且具有容错处理，单台服务器失效不影响整个集群运作。Ejabberd基于ErLang+ Mnesia构建，项目已成功发展5年，占据30%左右Jabber服务器市场。</p>
<p>　　Tsung则是多协议分布式压力测试工具,可用于测试Http、Soap、Postgresql和Jabber/XMPP服务器。而Wings则是一个3D建模程序，软件支持Windows、Mac OSX和Linux等操作系统，这两个项目都基于Erlang构建。</p>
<!--分页-->
<p>　　Erlang将会成为一个非常重要的语言。如果有了大公司的支持，它甚至可能成为下一个Java。因为它是个开源项目，非常适合多核处理、Web服务等领域。事实上，它也是编写在多核机器上运行的高可靠性系统的唯一成熟语言。</p>
<p>　　Erlang始于20年前，是一个并发性Prolog，Joe Armstrong创造了它。第一个大型Erlang项目是一个由几百人创建的电信交换系统，系统有数百万行代码。系统主要关注的就是可靠性，并且系统有难以置信的可靠性历史。据Joe介绍，&ldquo;它有99.9999999%的可靠性&rdquo;。</p>
<p>　　这意味着每10亿秒才有1秒宕机时间，或者说10亿分钟有1分钟宕机时间。十亿秒大概是30年，10亿分钟大概有2000年。99.999%的可靠性大概是每年宕机5分钟，这已经是很好的了。了解可靠性的人都知道，可靠性系统有 99.9999%的，甚至99.99999%的，但是估计没听过有99.9999999%可靠性的，可基于Erlang的系统实现了。</p>
<p>　　但这还不是令Erlang壮大的理由，因为不是什么人都关注可靠性。也不是因为 Erlang是一个函数式语言，更不是并行Erlang是个面向对象语言。其发展迅速的主要原因是唯一一个有可靠实现和完善类库的成熟的并行开发语言，在不久的将来所有的桌面系统、笔记本电脑都将是多核的，而要让程序在多核上更快的运行就要使程序能充分利用多核处理的能力。</p>
<p>　　Erlang带有一组类库。多数类库是用于构建各类Internet服务的。 Erlang有Web服务器和数据库。Erlang社区认为它是构建可靠Web服务器和Web服务的首选语言。Erlang是一个构建可靠系统的框架/平台，它构建的平台可以持续运行而无需关闭，可以每天更新软件，甚至可以定期的更换硬件。这些特性是电信应用所需要的，它还是在线银行、在线商城等各类在线应用所迫切需要的。</p>
<p>　　Joe Armstrong最近写了本书《Programming.Erlang》,所有关注Erlang的人都值得一读。Erlang符合所有面向对象语言特性，虽然它是个函数式语言，而不是面向对象语言。Erlang区分与面向对象语言的一个方面就是它的错误处理。在某消息出错时，进程不是抛出出错的部分，而是直接进程纠错。系统结构被设计为底部是工作进程（它们可能会失败），上层是管理进程，它们可以重新启动失败的进程。</p>
<p>　　我不相信其它语言能迅速赶上Erlang。对其它语言而言，加入像Erlang这样的语言特征是很容易的。但这将花费他们大量的时间构建一个高质量的VM和成熟的并发性与可靠性类库。因此Erlang很自然会成功。如果将来要在多核系统上进行开发，Erlang是非常理想的选择。</p>
<p>　　<strong>Erlang在中国</strong></p>
<p>　　目前，Erlang在全球都还是个小众语言，其在中国影响力就更小了，好在有国内的 Erlang爱好者已经组织起来，在进行相关的工作，成立了Erlang-china.org，发布了部分Erlang相关中文文档，并且组织了两次 Erlang爱好者聚会，Erlang-China.org将继续为对Erlang感兴趣的中文用户提供便利，促进用户彼此之间的交流，推动对这一语言的深入研究，促成一些Erlang开源项目，帮助中文用户为整个Erlang社区做出贡献。</p>
<p>　　Erlang没有类似Java、C++的语法，它不是面向对象语言，它是函数编程语言(Functional programming Language)。大量程序员并不熟悉函数式编程，我们的计算机教育里也都是基于面向对象和面向过程语言的，这会是所有想尝试Erlang的用户遇到的首要问题，这会使得培训成本加大，决策人员也需要足够勇气来选择一个新语言来构建应用。</p>
<p>　　另外，Erlang虽然内建了并行、分布的支持，但是程序员还需要学习和掌握并行的思维模式，并行的思维模式也许是更加难以跨越的门槛。</p>
<p>　　要解决计算时代，可伸缩性、容错性以及运行时可更新系统需求，就目前而言，只有 Erlang语言可以很好的解决。Erlang语言也正面临这一场大的变革，从默默无闻走向更多人视野，会向更广的网络应用领域渗透。也许，不久的将来，当你听到Erlang时，就如同听说Java一样平常。</p>
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/202913#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 13 Jun 2008 12:43:13 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/202913</link>
        <guid>http://seasar.javaeye.com/blog/202913</guid>
      </item>
      <item>
        <title>C和C++里面的lvalue 和 rvalue的释义</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/201370" style="color:red;">http://seasar.javaeye.com/blog/201370</a>&nbsp;
          发表时间: 2008年06月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h2><span id="siteindexid_0">C和C++里面的lvalue 和 rvalue的释义</span></h2>
<div class="t_msgfont" id="postmessage_7496286"><span id="siteindexid_1">在看GCC的文档的时候，看到一个词lvalue，查了金山词霸其释义为 lvalue [计] 左值。因为的确在介绍编译原理的课程中听过这个词，大致知道其意思就没有多想。但是看完GCC文档的这个篇幅，都无法明白全篇在说什么。问题还是出在了lvalue这个词的&ldquo;左值&rdquo;是什么意思的理解上了。再找M-W</span><span class="inline-search-anchor" id="site_index_aid_1" onmouseover="this.className=&quot;inline-search-anchor-hover&quot;" onclick="showinlinesearchbox(&quot;1&quot;,&quot;字典&quot;)" onmouseout="this.className=&quot;inline-search-anchor&quot;"><span id="siteindexid_2">字典</span></span><span id="siteindexid_3">，却告知没有这个词。于是google了一把，的确很多地方都称其为左值，我仍然不得要领。最后在一个百科网站About Site上找到该词的准确释义，摘贴如下：</span><br /><span id="siteindexid_4">Definition: C and C++ have the notion of lvalues and rvalues associated with variables and constants. The rvalue is the data value of the variable, that is, what information it contains. The "r" in rvalue can be thought of as "read" value. A variable also has an associated lvalue. The "l" in lvalue can be though of as location, meaning that a variable has a location that data or information can be put into. This is contrasted with a constant. A constant has some data value, that is an rvalue. But, it cannot be written to. It does not have an lvalue.</span><br /><br /><span id="siteindexid_5">Another view of these terms is that objects with an rvalue, namely a variable or a constant can appear on the right hand side of a statement. They have some data value that can be manipulated. Only objects with an lvalue, such as variable, can appear on the left hand side of a statement. An object must be addressable to store a value.</span><br /><br /><span id="siteindexid_6">Here are two examples.</span><br /><br /><span id="siteindexid_7">int x;</span><br /><br /><span id="siteindexid_8">x = 5; // This is fine, 5 is an rvalue, x can be an lvalue.</span><br /><span id="siteindexid_9">5 = x; // This is illegal. A literal constant such as 5 is not</span><br /><span id="siteindexid_10">&nbsp; &nbsp;&nbsp; &nbsp;// addressable. It cannot be a lvalue.</span><br /><br /><span id="siteindexid_11">这段就说的很明白 lvalue中的l其实指的表示该值的存储地址属性，而另外一个相对的词rvalue值中的r指得是read的属性，和左右根本没有任何关系。</span></div>
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/201370#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 08 Jun 2008 17:14:32 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/201370</link>
        <guid>http://seasar.javaeye.com/blog/201370</guid>
      </item>
      <item>
        <title>2年来的困惑，一夜之间，柳岸花明(转)</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/196334" style="color:red;">http://seasar.javaeye.com/blog/196334</a>&nbsp;
          发表时间: 2008年05月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>From:http://blog.csdn.net/luyang1016/archive/2007/09/10/1778862.aspx <br />（原创：闭月羞花猫 2007/09/10） <br />&nbsp;&nbsp;&nbsp;&nbsp; 前一段时间对工作，对未来一直很迷茫。并在这期间，陆续的发表了一些文章。在这一段时间，几乎对软件生产失去了信心，对程序员的生存状态产生了担忧。 <br /><br />&nbsp;&nbsp;&nbsp;&nbsp; 当然，中国的软件产业来说，我们只能思考，去思考自己如何适应其发展，如何寻找出路。 如何在这一团团迷雾中找到属于自己的天空。 <br /><br />中国程序员的现状： <br />1 人员结构不合理 <br />2 人员知识面泛而不精 <br />3 程序员的廉价趋势越来越明显 <br /><br />造成上述问题的根本原因是：中国人太多！ <br /><br />造成程序员廉价的重要原因： <br />1 &nbsp;中国的软件行业由于发展缓慢，技术上距离欧美，日本差距非常明显。 <br />所以中国并不具备大型独立的软件产品研发的能力，中国软件的发展，大部分集中在企业级应用和门户网站的建设上。 <br />2&nbsp; 随着企业级开发的日益简单化（技术层面），对软件人才的要求变得越来越低。以前少数人能干的事情，现在大部分人似乎都能干的起来。以前的门槛或许要重点本科计算机相关专业，现在的门槛似乎只要你上过大学，似乎都可以来搞软件， 什么信息管理这样的专业毕业，似乎都可以毫不费力的搞程序。（在这里绝对没有贬低这些专业的意思） <br />3&nbsp; 以上两个条件，加上中国的一个最大的国情-&ldquo;人太多，就压压力巨大&rdquo;，决定了中国软件的另一条出路-&ldquo;软件外包&rdquo; <br />软件外包行业已经越来越多的成为软件发展的宠儿，软件外包这个词汇也频频出现在各大杂志上。 <br />&nbsp;&nbsp;&nbsp; 软件外包行业由于其特殊性，决定了其门槛比较低，不需要很强的技术能力。&nbsp;软件外包，究其本质，和建筑工程外包的性质没有任何的区别。大部分的成员，不是专家，不是管理层，而是工人，也就是我们通常所说的民工。而中国从来就不缺少民工。为了缓解巨大的就业压力， 国家还会继续培养这样的&ldquo;人才&rdquo;。不是经常有杂志上动辄就是说，中国的外包人才的缺口有几十万么？ <br />&nbsp;&nbsp;&nbsp; 这几十万不是技术人才，使民工！ <br />&nbsp;&nbsp;&nbsp; 你是不是觉得现在的程序员要价越来越上不去了？你是不是觉得你要求加工资的时候，成功率低了？ <br />你是不是觉得找工作困难了？ <br /><br />&nbsp;&nbsp; 《性工作者十日谈》里面有这么一句话，出自香港本地性工作者：那些该死的北妹（中国大陆），把价格要的这么低，我们的日子没法过了。 <br />&nbsp;&nbsp;&nbsp; 随着企业级应用开发的简单化，随着工具的智能化，随着从业人员的日趋庞大，中国程序员的日子可能会越来越难过。 <br />以前体面的白领，也会逐渐沦落成为软件生产流水线的一个普通的工人。加班加点，工资微薄，未老先衰。 <br />&nbsp;&nbsp;&nbsp; 我预言：5年以内，软件外包的门槛就是高中生，一个月薪水不超过社会平均生活水平的一半。所以在软件外包公司走技术路线，是没有前途的。 <br /><br />&nbsp;&nbsp;&nbsp; 那么面对这样的局面我们应该怎样积极的面对，因为这个局面我们无法控制，也无法改变。 上面所讲的企业级开发日益简单化，仅仅是局限于技术层面。 相反，企业的业务越来越复杂，式样也越来越难以把握。针对这样的情况，现在的SOA也是吵得沸沸扬扬。所以业务理解，设计型的人员越来越受到欢迎。工作也越来越重要。 <br />&nbsp;&nbsp;&nbsp; 那么我们可不可以转型成为业务，设计为主的人呢。 同时，软件工人多了，相对应的管理人员不是也需要增加么？是不是可以考虑往管理上发展呢？ 这一点，在软件外包公司表现的很明显。欧美外包，印度模式，大量的软件工人，庞大的团队，需要良好的业务理解能力的人来理解发包公司的需求，理解发包公司的设计。理解之后，再来把信息传递给代码工人 <br />来实装，来完成。代码生产的过程中，不断对生产的产品进行监督与控制。使其按照需求正常有序的进行下去。 <br />&nbsp;&nbsp; 对日外包，现在国内非常火。上面分析过，中国适合开展外包。但是由于语言，文化等因素，在欧美外包方面，和印度阿三比显然不具备优势。 因此对日软件外包自然成为了最好的选择。 对日软件外包，更是需要业务把握的人才，而事实上业务式样工程师，实际的待遇等，包括在公司中的地位，显然比普通的代码工人要高的多。 <br />&nbsp;&nbsp; 原因有2个：&nbsp;&nbsp;第一，在中国目前既了解技术，又具有设计经验，而且精通日语的人非常的少。这类人才才是奇缺。&nbsp; <br />&nbsp;&nbsp; 第二，还是中国人太多，软件工人太多。而这些软件工人普遍素质又差，再加上对日语又不懂，如何保证这部分人能够正确理解式样呢？那就是给这些人一个 <br />交流的桥梁，引导他们按照需求来完成产品。 <br /><br />&nbsp;&nbsp; 而上面说的这一类人，才是中国软件外包行业真正的希望！才是外包行业的根本。 <br /><br />&nbsp;&nbsp; 2年来，我一直过分的关注于技术，一直以来把技术能力摆在一个很高的地位。我曾经甚至很看不起技术差的人。 <br />这也是造成我2年以来迷茫的根本原因所在，因为2年啦我越来越发现，在软件外包行业技术路线是很难走通的。 <br /><br />&nbsp;&nbsp; 我甚至感觉，走业务系统工程师路线，远离程序的人，甚至是日语专业毕业，根本不懂技术本身的人，受重用程度和地位前途比代码工人高多了。 <br />&nbsp;&nbsp; 2年来，很多人只关心程序本身，不管业务，到头来终究还是一个民工的角色，这样的人，在我身边随便抓抓一大把，当然也包括我在内。 <br /><br />&nbsp;&nbsp; 那一天，我幡然醒悟：技术路线根本走不通，远离编码，才是软件工程的一种高的境界。 <br />&nbsp;&nbsp; 资质有限，也醒悟的太晚，但不管怎么说，终于醒悟了。 <br /><br />&nbsp;&nbsp;&nbsp; 针对上述问题，我不是抱怨，我也知道还是有很多有能力的人走技术路线可以搞得很好的，但是对我来说,由于天赋有限,还是考虑放弃技术,走业务路线了. <br />相信看到这篇文章的人,大部分人最后都会发现,自己不适合做技术,软件外包不需要技术.中国软件没有技术.</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/196334#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 24 May 2008 11:42:29 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/196334</link>
        <guid>http://seasar.javaeye.com/blog/196334</guid>
      </item>
      <item>
        <title>互联网的主要模式</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/196328" style="color:red;">http://seasar.javaeye.com/blog/196328</a>&nbsp;
          发表时间: 2008年05月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          互联网的主要模式<br /><br />一、网络门户 <br /><br />所谓网络门户就是进入因特网的大门，它具备强大的信息检索信息交流和信息传递功能，有综合性门户和垂直门户之分，广告是他们主要的收入来源。 <br /><br />1．雅虎（YAHOO）和美国在线（AOL）：华裔科学家杨致远创办的雅虎网站，它把网络门户的概念首先引进到网络经济，在综合性门户开始衰弱之前，他就利用自己巨大的访问量优势，成功的发展电子商务、网络通信等等。美国在线拥有 30000000注册用户，在并购时代-华纳公司之后，前来要求合作的网络公司非常踊跃：有出价亿美元买下三年之内对美国在线用户的唯一电话接入权，有人花3000万美元征得它的旅游代理权，有人支付2500万美元购买花卉特许经营权。去年圣诞节一家服装公司向优惠20%，结果售出的服装所有服装比纽约以外加起来还要多。看起来综合网站的人气还是大有利用价值。 <br /><br />2．专业垂直门户：综合性门户之战大局已定，较小的门户将被吞并，代之而兴起的是垂直门户，讲究某类专业信息的专深而不是广泛。例如 Healtheon.com，是面向网上医药销售的每个流程，将医生、病人、保险机构的联系在一起。美国人每年在健康投资上的花费估计高达10000亿美元，这一类网站的前途非常光明。 <br /><br />3．综合垂直门户：这是一种结合了多个专业垂直门户的网站，比如Vertical.com,其创办者发现，有许多行业，比如废水处理、固体垃圾处理，虽然大众不太关注，但市场容量不小，只要网站上的内容丰富、深刻、有趣，该专业的人士就会聚拢过来，于是广告就跟着来了，交易也可以在这里进行。它像一家出版社，创办了很多专业杂志，承包给别人， 一“本”就收入7000美元/年。 <br /><br />4．搜索引擎：是网络门户必备的工具，但由于它不能直接赚钱，独立的搜索引擎站点很难生存。所以想继续独立的搜索引擎中必须不断提高技术和含量。1999年下半年，新一代搜索引擎粉墨登场，如northernlight.com & goole.com，变得更加聪明，更能体贴入微地找到用户想找的东西，深得用户欢心。 <br /><br />二、网上销售 <br /><br />网上购物几乎是最显而易见的电子商务。能在网上买到东西无奇不有，形式无非是百货店和某一类商品的专卖店，学问就在于如何为顾客服务。 <br /><br />贝索斯创办亚马逊书店之前曾作过认真调查，发现书籍是最适合在网上卖的东西。因为书是标准化产品，很少退货，耐运输不易损坏，而且可在网上对书进行介绍、评价、也可登载部分章节，这是传统书店不具备的优势；另外，不存在一个占垄断地位的传统书店，降低了网络书店进入市场的门槛。现在亚马逊发展成了一个购物门户网站，他利用自己庞大的顾客源，邀请其他小零售商加盟。亚马逊成功证明了贝索斯当初的选择绝对准确。 <br /><br />5．低价万岁：价格永远是最有力的武器，亚马逊的成功，定价策略功不可没。buy.com公司也是卖力地运用减价策略，甚至出血来吸引顾客。该公司的商品 85类, 去年在九个月的时间也有我从6380万美元增加到近四亿美元，但亏损了8050万美元。该公司表示，随着其销售规模不断扩大，经营成本降低，还会有广告收入，加上高附加值产品增加，经营情况会好起来。另一家网上超市netmarket.com更绝，如果顾客发现其他网站出售的同类商品比这里便宜，它不仅将差价还给你，还会另外返回差价的35%，条件是你每年交69.95美元会员费。 <br />（请点一下本文广告，谢谢） <br />6.交互咨询做参谋：根据一项研究，90%以上网上顾客喜欢交互式服务。Landsend.com服装公司设立了实时、个性化的交互式“导购员”， Landsend.com可以通过网上聊天方式来帮助顾客找到他想要的商品。这个网上还有一种“大家一起购物”的系统，让不同地点的顾客在网上讨论一件衣服是否值得买等，网上销售一年之内暴涨 3倍，向近200个国家发货。 <br /><br />网上家具店furniture.com的交互功能更强，顾客可以在网上或通过电话向一位家具专家咨询，可以参考网站提供的房间设计模型，家具上所有织物的样品可以邮寄给顾客让他亲手摸一摸。如果你表明自己对某一件商品的品味，就会有其他顾客发电子邮寄来提供参考意见。对于服装、家具等质量非标准化的商品，没有眼看、手摸、身体试过，是很难下决心购买。有时顾客本身也缺乏基本知识，网站做参谋真是抓住了顾客内心的需要。 <br /><br />8．相关信息集大成：无穷多的信息是网络最大的优势，有的网站善于利用这个优势，用与自己所卖商品相关的气息吸引浏览客。Garden.com是一家园艺站点，它主办了一份网上园艺杂志，请了园艺专家回答问题，顾客还可以在网上设计花园。而在录象机和销售DVD的reel.com，电影爱好者们可以找到许多有关电影的新闻和最新影片几个。 <br /><br />9. 完善配送系统：大部分网上商店委托第三方快递公司配送，webvan.com则下大本钱建设自己的配送系统。一旦建成，最快在30分钟之内可以把货送到顾客手里，那么活泼乱跳的海鲜、容易腐烂的水果、刚出炉的匹萨饼都能实现网上享受了。 <br /><br />三、网上竞拍 <br /><br />雅虎、亚马逊、Ｄｅｌｌ、电子湾（EBAY）被公认为因特网上四大成功模式。 <br /><br />10．ebay的拍卖：每个人都可以拿出各种稀奇古怪的东西在网上寻求买主，想要的任何东西也许都会找到，价格由买主和卖主之间协商，ebay价格模式如此惊人的成功，引得现在几乎所有的购物网站都经营起拍卖来了。 <br /><br />11. 供应商拍卖: 有买就有卖，之所以说“拍卖”而不是招标，因为拍卖只属于因特网。 <br /><br />Freemarkets.com专门帮助传统企业寻找有无竞争力的半成品供应商，有需求方面出价，供应方接价。从政府采购到机械制造商，都可以在这里张贴代理采购的清单，等着供应商们来竞价。这类服务平均能为买方节省 10— 25％的采购成本。Ewanted.com网站为个人提供拍卖服务，你只要详细说明自己想要什么东西、心理价位、如何付款，卖主们看到就会主动联系，卖主多了，还会压价。 <br /><br />12. 顾客定价：princeline.com的方式和拍卖又有些不同，它是让消费者出高价，卖主愿者上钩。princeline.com收集了人们愿意承担的机票、旅馆房间、汽车和房产抵押的价格，“悬赏”等卖主，从经济学角度分析，这种模式能达到一种没有浪费的均衡，顾客定价模式引起了强烈震撼，尽管一开始经营情况不是最好，但是它在股市上却大获成功。 <br /><br />13. 以物易物：doublebill.com&bartertrust.com推出以物易物交易网站，交易者以虚拟的货币为单位定价,双方成交分别后付给网站手续费。支持者认为，因特网是提供货物和人劳务交易的绝佳平台，可以大大提高以货易货的可行性。 <br /><br />四、网上金融 <br /><br />14. 财经证券网站:投资生财人人关心，这是财经证券网站因此成为最受欢迎的一个网站的原因。像国内的证券之星、和讯中金网、易富网等提供股票即时行情、证券数据、重要财经新闻、证券分析软件等内容，属于财经资讯网站。这种网站在朝前发展一步可成为网上券商，网上券商也有两种模式：一种全部业务都是网上操作，第二种既有网上交易同时也直接接触顾客，它加入网上交易, 并和多家零售网点连接起来，网上证券商吸引人主要不是靠低廉的交易费用，而是优秀的证券研究工具，指导你如何进行股票投资。还有的财经政策类网站在个人理财方面表现得十分突出, MYCFO公司就为专门为有钱而不知如何管理的人作私人秘书, 告诉你怎么交税、怎么投资、怎么付帐。 <br /><br />15. 网络银行和保险公司：传统的银行及保险公司的业务都可以在网上进行。从网上你可以查找到自己的支票是否兑现、确认存款、帐户间的资金转移，了解信用卡、抵押贷款、教育贷款以及个人贷款限额等理财信息，并可以申请上述贷款。比如美国1995年开始了网络银行，网上提供抵押、保险、税收等，内容丰富，便于使用。到1997年７月，他的客户已超过80万人。再比如，ECOUVAGE公司则是一家网上保险公司，它使整个保险操作获得简化，客户可以在任何时候、花费比过去少，客户可以在任何时候保险项目和赔偿。 <br /><br />16．网络风险投资：把钱给网站并帮助他们公开发行股票，这是现在许多风险投资公司所热衷的事。他们往往帮助创办一系列的网络公司，只要其中有一部分网站能够上市，就能大赚一笔。还有的风险公司自己并不募集资金，不参与投资和分配，而是做投资者和网站的红娘，赚取佣金，将有潜力的网络公司和有实力的投资公司进行配对。 <br /><br />五、配套服务 <br /><br />17．物质配送：网络买卖实在方便，但离开了物流配送系统，购物网站将会一事无成。98年圣诞节，美国网上购物人气急升，大量的货物就由美国联合货运公司（UPS）、邮政快递和联邦快运（Fedexp）参加。UPS在全美建立了仓储和包装系统，可以按顾客约定的时间送货上门。配送单在网上流通，客户还可以随时在网上看到自己的货物到了什么地方。FEDEXP通过收购一软件公司，全面改造它的网络系统，客户只要发一个电子邮件, 剩下的就全部交给他了。 <br /><br />18. 技术支持：网络世界的每一个最细微的变化，其实要依赖计算机程序的发明和改进，因此有用的程序身价陡增。LINUX操作系统是个开放的共享软件，靠天南海北自动投入工作的自由程序设计师，已经对微软WINDOWS构成威胁。由于自由设计师常常使指对自己感兴趣的部分，一些繁琐而又极为重要的部分没人做。于是几家中介网站应运而生，为供需双方牵线搭桥。 <br /><br />网上购物手续繁琐，产生了新的商机。1998年，“购物篮”开始应用，顾客要卖的东西放到篮子里，最后统一结算。不同的网站会用不同的单子，每次都要顾客填写信用卡等各种数据，所以还是不方便。AZROO开发初通用"篮子"，在多个站点购物时一次结算填单，这样就把整个网络变成了一个大超市, 非常方便。 <br /><br />六、商务的电子化 <br /><br />电子商务可以是“电子的商务化”，也可以是“商务的电子化”。 <br /><br />19．在线采购：作为工业经济代表的通用汽车、福特汽车、通用电气、波音公司等，争相把它们的采购部门转移到网上。网络的开放性和全球性让他们可以密切跟踪交易的每个步骤，货比多家是“小菜一碟”，效率大大提高。据估计，网上交易为通用和福特汽车每年节省20％左右的成本，通用电气节约5至7亿美元。老牌公司的“ｅ化”不仅节了流，更有开源的妙处。这些“巨无霸”下面都有一大群零部件供应商，如福特汽车的供应商多达3万多家，每年销售总额3000亿美元左右。这些供应商可以把福特网站作为中心，交流信息、进行交易，其他汽车厂商也可加入来采购。如此一来，网站就可坐收交易手续费和广告费，据预计，福特、通用汽车的网站4年内年营收都将达50亿美元。 <br /><br />20．硬件在线销售：电脑硬件与网络的关联十分密切，与之打交道的客户又大多与网有关，硬件制造商上网销售顺理成章。最近思科系统公司（CISCO）取代微软成为市值之王，这不能不归功于它的网络销售战略。思科是世界最大的因特网设备制造商，也是最早实施网络销售战略的。电子商务带来极高的销售额和极低的销售成本，使思科成为IT产业历史上获利最丰的企业。 <br /><br />同样，戴尔电脑（DELL）的网上接受订购、按订单制造产品的模式，也使它成为个人电脑企业中成长最快的一家；英特尔的网络战略开展稍晚，但99年的网络销售收入105亿美元，已超过了总额的三分之一。 <br /><br />21．“黄页”上网：“托马斯名录”（thomasregister.com）是一家出版商家名录的公司，有点类似黄页电话簿，当然内容要丰富详尽得多。托马斯收有8000种目录和15600家公司名录，上网之后，它还为其中23000家专门建立了“电子门面”，内容有产品名单和产品详细信息等。网络还能实现一些极有用的新功能，比如某家公司对关键客户的秘密报价，只让掌握密码的人独享。托马斯每年向每个“门面”收取3000美元管理费，盈利丰厚。 <br /><br />七、第四媒体 <br /><br />因特网以飞速发展的势头，成为继报纸、广播、电视之后的第四大大众传媒。有些网站的经营思路，就是充分利用网络信息传播的优势。 <br /><br />22．独家信息资源：独家新闻是一张报纸发行量（或者广播电视收听收视率）的关键，同样道理，网络媒体有独家信息资源才能提高点击率。 Britannica.com把整部《大英百科全书》搬上网，还有来自76家著名杂志的相关文章、能链接到125000个相关网站。这样的例子可能是一个极端，但即使做不到如此丰富的信息量，也必须好好做到“独特”两字。 <br /><br />23．新闻背景：电视依然是现在影响最大的媒体，但电视常有“浅薄”之嫌，那么，在网上对新闻背景和有关知识作深度挖掘报道，应该是很吸引人的。如果你想对科学背景知识知道得多些，比如转基因牛肉能不能吃，天基导弹防御系统到底怎么样，到Whyfiles.news.wisc.edu看看不会失望。同样是科技内容，新星在线（pbs.org/wgbh/nova）用故事、插图、录像把“和平号”太空游、登月过程演绎得让你身临其境；每日科技（sciencedaily.com）每天搜集科研新闻。 <br /><br />25．电子杂志：为了增加访问量，电子杂志一般都是免费的，但也有些宁愿保持权威的清高形象，也不降低档次。声誉卓著的华尔街日报（wsj.com）就是网上为数很少的能够收到订阅费的站点，现在已有33万订户每年花59美元订阅这张报纸的电子版。这种做法为广告客户过滤出目标范围非常明确的受众，即对商业和金融新闻感兴趣的人，因而广告形势看涨。 <br /><br />26．网上娱乐：亚马逊网上书店开设的互联网电影数据库（imdb.com）存有21万多部电影，斯皮尔伯格等5位好莱坞名人联合微软的创始人之一保尔· 阿兰一起创办了一个Ｐｏｐ．ｃｏｍ网站，播放原创视频娱乐节目，华纳兄弟公司也推出了Edtertaindom.com网站。ＭＰ３兴起，带动网上音乐持续升温，一个以ＭＰ３．ｃｏｍ为名的网站顺时而出，提供成千上万的ＭＰ３歌曲供免费下载。类似的还有Real.com，这里除了大量的ＭＰ３音乐，还网罗了网上几乎所有的音频、视频内容的超级链接，已演变成一个娱乐门户网站。 <br /><br />八、网上“保姆” <br /><br />有些网站，不直接卖什么有形的商品，卖的是特定的信息和服务。 <br /><br />26．购物指南：BizRate.com收集了1700个网上商店的信息，根据以往顾客对它们的订购过程、选择和价格的满意程度评出5个星级。 Productopia.com还建了聊天室，你可以直接向网友们讨教。Mysimon.comｍ为你开列一串串分类目录：书店若干家，茶叶店若干家，你按它提供的网址随意选择好了。在那么多的网上商店找一样东西，嫌累？Deaktime.com会卖力地替你“逛街”。 <br /><br />Freeshop.com专门搜集网上商店的打折、免费赠送活动信息。信用卡公司经常向用户提供各种优惠，消费者往往搞不清楚，到Hiddenmoney.com看看就能了如指掌。 <br /><br />27．私人助理：当你的身份证号、银行卡号、家庭地址、电话号码等任何一项改变了，要通知许多人是不是很头疼？Zcentral.com就是为解决这种烦恼而诞生的，你只要花两分钟在上面改动一下，所有该知道的人都会及时接到通知。如果你对因特网的安全性有信心的话，也可以把信用卡密码放在上面，免得记不住。这个网站上还可存放文件、进行私人会议。Anyday.com则是一个日程安排网站，为用户管理日程表、地址簿和要做的事，到时提醒。 <br /><br />28.家政服务员：ehow.com帮助你进行家务管理，怎样设置书桌？感冒了怎么办？溜冰鞋坏了怎么修？这里提供了详尽的答案可采购物品清单。如果找不到现成答案，网站会想尽办法在几天内回答你。来到Superfamily.com网站，一家人哪怕远隔天涯亦如围坐在起居室里一般，在中国的父母与在美国子女可以互相传送照片、新闻和日常安排，还可以编一份家庭报纸。 <br /><br />29.旅行服务：网上的旅游服务站点很多，各有特色。Lonelyplanet.com能向旅行者提供有关旅行目的地的详细资料，不断更新全球旅行新闻，告诉你各种旅行技巧。Travelocity.com的母公司Ｓａｂｒｅ集团拥有世界上最大的预订系统，一次点击就可获知你出发到达主要大城市所需的费用，根据你的旅行需要自动搜索３条最省钱的路线，等等。不久前，该网站与ＰｒｅｖｉｅｗＴｒａｖｅｌ合并成为规模最大的旅行网站，数据库中存有42000 家酒店、70000种旅行计划。大多数航空公司都推出自己的航程积点奖励计划来促销，但乘客往往会忘记及时累积里程，订票网站Webflyer.com能自动帮你记录。 <br /><br />多年不见的老同学想聚会，但邀约的工作特别麻烦。交给Evite.com干就行了，你填一张单子，它就会发出电子邮件让邀请对象到该网站上来，大家就可以互相商讨。Seeuthere网站也负责组织各种约会，不过它主要处理大规模的聚会，还包括为邀请对象订票等服务。 <br /><br />九、上网“保姆” <br /><br />这些公司做的是为准备上网的公司提供服务。要知道大多数企业并不具备专业的网络知识和技能，而且大多数人懒得学习大量的新技术，很需要有个“保姆”来引路。 <br /><br />30.上网业务外包：对中小企业来说，用专门的部门和人员从事网络业务太昂贵了，精力也不够,但不上网又不行。只要交5000美元软硬件费用和每月35美元的管理费，Verio.com就帮中小企业开展、管理、开拓电子商务。98年圣诞美国的电子商务大潮突然爆发，中小企业纷纷寻求帮助，Verio公司 99年第二季度的收入达620万美元。大中型企业其实也存在着类似的问题，庞大的主机管起来很烦，Exodus.com由此发展了主机托管服务，收获颇丰。 <br /><br />31.免费的午餐：在Bigstep.com上开店，如果用信用卡交易必须通过该网站开设账户；在Freemerchant.com则要打它给你的广告。在Mindspring.com店玩玩也不错，最便宜的电子商务计划每月只需79.9美元，提供有限的后勤服务功能，最多可销售50种商品。这些网站上还会给予许多有益的指导，简直是一个培训实习基地。 <br /><br />32.电子商务咨询：许多人都知道安达信、麦肯锡等咨询公司，福里斯特公司（forrester.com）在网上世界的知名度不比前者低。这是一家专门评估电子商务网站、预测电子商务市场的咨询公司，连美国政府都要引用它的分析报告。类似福里斯特的公司不少，有专做网站排行、媒体测评、性能测评等的，都相当成功。Rowe.com建立了庞大的资料库，里面有24万篇报道、3500种市场报告和800万本与电子商务有关的折扣书。它以租赁的方式向客户提供资料，并为客户设计电子商务交易流程。 <br /><br />十、虚拟社区 <br /><br />电视把世界变成地球村，散居在地球各个角落的人，为了同一个爱好，相聚到虚拟的茶馆里。 <br /><br />33.爱好者的客厅：以汽车爱好者为例，一些网站如“汽车内幕”（Innerauto.com）、“汽车网”（Cars.com）、“摩托车艺术展” （guggenheim.org）搜集了大量的汽车知识和信息、汽车评论等，吸引感兴趣者来谈论汽车话题，也吸引汽车商家的关注。每项爱好者多的话题，都可以衍生出专业的虚拟社区。 <br /><br />34.网上沙龙：这里刚好相反，大家没什么特定的题目，东拉西扯想到什么说什么，仅为了满足自由发表言论的欲望。比如你们在deja.com上大侃李小龙的电影，卖这些影片的音像店就悄悄地开门邀客了，因为口碑传播比任何促销手段都有效。这种商业模式要成功，首先要保证爱说话、会说话的人多，所以 Epinions.com给“侃爷”付酬，有一个听众就付你１至３美分。当然“侃爷”不应是被某些商家买通的，否则网站会做坍牌子。 <br /><br />35.商业社区：商业社区与纯粹的电子商务网址的区别是，商务完全是为社区服务的，不能让其中的“居民”反感。商业社区首先要有尽量多的相关信息，发行电子杂志为订户传递信息，开放讨论组让大家参加。然后，网站就可以加入访问者感兴趣的商品，为一群需求清楚的目标消费群服务。例如 Babycenter.com提供从怀孕、生产、育婴的所有内容，吸引孕妇和初为人母的女性，同时销售婴儿用品、书籍、玩具、儿童服饰等。 <br /><br />36.儿童乐园：孩子是未来的因特网主人，然而现在网上有太多的儿童不宜之地，于是出现了专为儿童设计的网站。雅虎开设了Yahooligans.com 儿童门户，还有ajkids.com、Disney.com等，上面的内容既有给孩子们看的，也有供老师和家长参考的。冲浪猴（Surfmonkey.com）为儿童设计了一种浏览器，保证他们不会在网上误入歧途。 <br /><br />孩子们总有提不完的问题，为人父母者疲于应付，不妨让他们自己上网找答案，如“科学与发现”节目的儿童栏目Discoverykids.com，美国航空航天局的儿童版Kids.earth.nasa.gov，“好奇孩子”Hhmi.org/coolscience.com。这些站点大多是非商业性的，但并非没有商业开发价值，而且对于树立开办者的企业形象大有帮助。
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/196328#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 24 May 2008 11:33:10 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/196328</link>
        <guid>http://seasar.javaeye.com/blog/196328</guid>
      </item>
      <item>
        <title>oracle如何实现：每天统计前面几天销售额的总额</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/193266" style="color:red;">http://seasar.javaeye.com/blog/193266</a>&nbsp;
          发表时间: 2008年05月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          用分析函数　统计某商店的营业额。        <br />    date      sale<br />    1          20<br />    2          15<br />    3          14<br />    4          18<br />    5          30<br />   规则：按天统计：每天都统计前面几天的总额<br />   得到的结果：<br />   DATE  SALE      SUM<br />   ----- -------- ------<br />   1     20       20          --1天           <br />   2     15       35          --1天＋2天           <br />   3     14       49          --1天＋2天＋3天           <br />   4     18       67           .          <br />   5     30       97           .
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/193266#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 May 2008 14:18:35 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/193266</link>
        <guid>http://seasar.javaeye.com/blog/193266</guid>
      </item>
      <item>
        <title>Oracle中ROWNUM的使用技巧</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/193204" style="color:red;">http://seasar.javaeye.com/blog/193204</a>&nbsp;
          发表时间: 2008年05月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Oracle中ROWNUM的使用技巧<br />作者： fuyuncat<br /><br />来源： www.HelloDBA.com<br /><br />ROWNUM是一种伪列，它会根据返回记录生成一个序列化的数字。利用ROWNUM，我们可以生产一些原先难以实现的结果输出，但因为它是伪列的这个特殊性，我们在使用时也需要注意一些事项，不要掉入“陷阱”。下面就介绍一下它的使用技巧及注意事项。<br /><br />1         特殊结果输出<br />利用ROWNUM，我们可以做到一些特殊方式的输出。<br /><br />1.1     Top N结果输出<br />我们如果希望取输出结果的前面几条数据，通过ROWNUM可以轻松实现：<br /><br /> <br /><br />SQL> select * from t_test4<br />  2  where rownum &lt;= 5;<br /> <br />USERNAME                          USER_ID CREATED<br />------------------------------ ---------- ---------<br />WOW                                    71 26-APR-07<br />CS2                                    70 15-JAN-07<br />3                                      69 01-NOV-06<br />DMP                                    68 12-OCT-06<br />PROFILER                               67 05-SEP-06<br /> <br /><br />但是，如果你希望对一个排序结果取Top N数据的话，使用ROWNUM存在一些“陷阱”，我们后面部分会介绍这些“陷阱”并且说明如何避免。<br /><br />1.2     分页查询<br />利用ROWNUM对结果进行分页，下面返回结果中的第6到第10条记录：<br /><br />SQL> select * from<br />  2  (<br />  3  select a.*, rownum as rn from css_bl_view a<br />  4  where capture_phone_num = '(1) 925-4604800'<br />  5  ) b<br />  6  where b.rn between 6 and 10;<br /> <br />6 rows selected.<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2770 Card=2183 Bytes =7166789)<br />   1    0   VIEW (Cost=2770 Card=2183 Bytes=7166789)<br />   2    1     COUNT<br />   3    2       TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />      29346  consistent gets<br />      29190  physical reads<br />          0  redo size<br />       7328  bytes sent via SQL*Net to client<br />        234  bytes received via SQL*Net from client<br />          4  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          5  rows processed<br /> <br /><br />另外一种实现方式：<br /><br /> <br /><br />SQL> select * from css_bl_view a<br />  2  where capture_phone_num = '(1) 925-4604800'<br />  3  and rownum &lt;= 10<br />  4  minus<br />  5  select * from css_bl_view a<br />  6  where capture_phone_num = '(1) 925-4604800'<br />  7  and rownum &lt;= 5<br />  8  ;<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=5920 Card=10 Bytes=8970)<br />   1    0   MINUS<br />   2    1     SORT (UNIQUE) (Cost=2960 Card=10 Bytes=5980)<br />   3    2       COUNT (STOPKEY)<br />   4    3         TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)<br />   5    1     SORT (UNIQUE) (Cost=2960 Card=5 Bytes=2990)<br />   6    5       COUNT (STOPKEY)<br />   7    6         TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />         62  consistent gets<br />         50  physical reads<br />          0  redo size<br />       7232  bytes sent via SQL*Net to client<br />        234  bytes received via SQL*Net from client<br />          4  SQL*Net roundtrips to/from client<br />          2  sorts (memory)<br />          0  sorts (disk)<br />          5  rows processed<br /> <br /><br />第三种实现方式：<br /><br /> <br /><br />SQL> select * from<br />  2  (<br />  3  select a.*, rownum as rn from css_bl_view a<br />  4  where capture_phone_num = '(1) 925-4604800'<br />  5  and rownum &lt;= 10<br />  6  ) b<br />  7  where b.rn > 5;<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2770 Card=10 Bytes=32830)<br />   1    0   VIEW (Cost=2770 Card=10 Bytes=32830)<br />   2    1     COUNT (STOPKEY)<br />   3    2       TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />         35  consistent gets<br />         30  physical reads<br />          0  redo size<br />       7271  bytes sent via SQL*Net to client<br />        234  bytes received via SQL*Net from client<br />          4  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          5  rows processed<br /> <br /><br />这里特地将三种实现方式的查询计划及统计数据打印出来，大家可以比较一下3中方式的性能。<br /><br />1.3     利用ROWNUM做分组子排序<br />对于以下表T_TEST4的内容：<br /><br /> <br /><br />OWNER                                   NAME<br />------------------------------------------------------<br />STRMADMIN                               STREAMS_QUEUE<br />APARKMAN                                JOB_QUEUE<br />SYS                                     AQ$_AQ_SRVNTFN_TABLE_E<br />SYS                                     AQ$_KUPC$DATAPUMP_QUETAB_E<br />APARKMAN                                AQ$_JMS_TEXT_E<br />STRMADMIN                               AQ$_STREAMS_QUEUE_TABLE_E<br />SYS                                     AQ$_SCHEDULER$_EVENT_QTAB_E<br />…<br /> <br /><br />如果我们希望结果按照OWNER进行分组后，再对每组中成员进行编号，结果类似如下：<br /><br /> <br /><br />OWNER                                   NO NAME<br />------------------------------------------------------<br />APARKMAN                                1 JOB_QUEUE<br />                                        2 AQ$_JMS_TEXT_E<br />STRMADMIN                               1 STREAMS_QUEUE<br />                                        2 AQ$_STREAMS_QUEUE_TABLE_E<br />SYS                                     1 AQ$_AQ_SRVNTFN_TABLE_E<br />                                        2 AQ$_KUPC$DATAPUMP_QUETAB_E<br />                                        3 AQ$_SCHEDULER$_EVENT_QTAB_E<br />…<br /> <br /><br />在没有ROWNUM时要实现这样的功能会很复杂，但通过ROWNUM我们可以轻松实现：<br /><br /> <br /><br />SQL> SELECT DECODE(ROWNUM-min_sno,0,a.owner,NULL) owner,DECODE(ROWNUM-min_sno,0,1,rownum+1-min_sno) sno, a.name<br />  2  FROM (SELECT *<br />  3        FROM t_test8<br />  4        ORDER BY owner, name ) a,<br />  5       (SELECT owner, MIN(rownum) min_sno<br />  6        FROM( SELECT *<br />  7              FROM t_test8<br />  8              ORDER BY owner, name)<br />  9        GROUP BY owner) b<br /> 10  WHERE a.owner=b.owner;<br /> <br />OWNER                                 SNO NAME<br />------------------------------ ---------- ------------------------------<br />APARKMAN                                1 JOB_QUEUE<br />                                        2 AQ$_JMS_TEXT_E<br />STRMADMIN                               1 STREAMS_QUEUE<br />                                        2 AQ$_STREAMS_QUEUE_TABLE_E<br />SYS                                     1 AQ$_AQ_SRVNTFN_TABLE_E<br />                                        2 AQ$_KUPC$DATAPUMP_QUETAB_E<br />                                        3 AQ$_SCHEDULER$_EVENT_QTAB_E<br />                                        4 AQ$_SCHEDULER$_JOBQTAB_E<br />                                        5 AQ$_STREAMS_QUEUE_TABLE_E<br />                                        6 AQ$_SYS$SERVICE_METRICS_TAB_E<br />                                        7 AQ$_AQ_EVENT_TABLE_E<br />                                        8 AQ$_AQ$_MEM_MC_E<br />                                        9 AQ$_ALERT_QT_E<br />                                       10 ALERT_QUE<br />                                       11 AQ_EVENT_TABLE_Q<br />                                       12 SYS$SERVICE_METRICS<br />                                       13 STREAMS_QUEUE<br />                                       14 SRVQUEUE<br />                                       15 SCHEDULER$_JOBQ<br />                                       16 SCHEDULER$_EVENT_QUEUE<br />                                       17 AQ_SRVNTFN_TABLE_Q<br />SYSMAN                                  1 AQ$_MGMT_NOTIFY_QTABLE_E<br />                                        2 MGMT_NOTIFY_Q<br />SYSTEM                                  1 DEF$_AQERROR<br />                                        2 DEF$_AQCALL<br />                                        3 AQ$_DEF$_AQERROR_E<br />                                        4 AQ$_DEF$_AQCALL_E<br />WMSYS                                   1 AQ$_WM$EVENT_QUEUE_TABLE_E<br />                                        2 WM$EVENT_QUEUE<br /> <br />29 rows selected.<br />2         性能<br />我们很多程序员在确认某个表中是否有相应数据时，喜欢加上ROWNUM=1，其思路就是只要存在一条数据就说明有相应数据，查询就可以直接返回了，这样就能提高性能了。但是在10G之前，使用ROWNUM=1是不能达到预期的性能效果的，而是需要通过&lt;2或&lt;=1作为过滤条件才能达到预期效果，看以下查询计划：<br /><br /> <br /><br />SQL> select * from t_test1<br />  2  where object_id &lt;100<br />  3  and rownum = 1;<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=86)<br />   1    0   COUNT (STOPKEY)<br />   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=37 Card=89 Bytes=7654)<br />   3    2       INDEX (RANGE SCAN) OF 'T_TEST1_PK' (UNIQUE) (Cost=2 Card=89)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />         62  consistent gets<br />          0  physical reads<br />          0  redo size<br />        654  bytes sent via SQL*Net to client<br />        234  bytes received via SQL*Net from client<br />          4  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          1  rows processed<br /> <br />SQL> select * from t_test1<br />  2  where object_id &lt;100<br />  3  and rownum &lt;= 1;<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=86)<br />   1    0   COUNT (STOPKEY)<br />   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=37 Card=89 Bytes=7654)<br />   3    2       INDEX (RANGE SCAN) OF 'T_TEST1_PK' (UNIQUE) (Cost=2 Card=89)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />          3  consistent gets<br />          0  physical reads<br />          0  redo size<br />        654  bytes sent via SQL*Net to client<br />        234  bytes received via SQL*Net from client<br />          4  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          1  rows processed<br /> <br />SQL> /<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=86)<br />   1    0   COUNT (STOPKEY)<br />   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=37 Card=89 Bytes=7654)<br />   3    2       INDEX (RANGE SCAN) OF 'T_TEST1_PK' (UNIQUE) (Cost=2 Card=89)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />          3  consistent gets<br />          0  physical reads<br />          0  redo size<br />        654  bytes sent via SQL*Net to client<br />        234  bytes received via SQL*Net from client<br />          4  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          1  rows processed<br /> <br /><br />10G以后，这个问题就被修正了：<br /><br /> <br /><br />SQL> select * from t_test1<br />  2  where rownum = 1;<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />Plan hash value: 536364188<br /> <br />------------------------------------------------------------------------------<br />| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |<br />------------------------------------------------------------------------------<br />|   0 | SELECT STATEMENT   |         |     1 |    86 |     2   (0)| 00:00:01 |<br />|*  1 |  COUNT STOPKEY     |         |       |       |            |          |<br />|   2 |   TABLE ACCESS FULL| T_TEST1 |     1 |    86 |     2   (0)| 00:00:01 |<br />------------------------------------------------------------------------------<br /> <br />Predicate Information (identified by operation id):<br />---------------------------------------------------<br /> <br />   1 - filter(ROWNUM=1)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          1  recursive calls<br />          0  db block gets<br />          4  consistent gets<br />          1  physical reads<br />          0  redo size<br />       1201  bytes sent via SQL*Net to client<br />        385  bytes received via SQL*Net from client<br />          2  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          1  rows processed<br /> <br />SQL> select * from t_test1<br />  2  where rownum &lt;= 1;<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />Plan hash value: 536364188<br /> <br />------------------------------------------------------------------------------<br />| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |<br />------------------------------------------------------------------------------<br />|   0 | SELECT STATEMENT   |         |     1 |    86 |     2   (0)| 00:00:01 |<br />|*  1 |  COUNT STOPKEY     |         |       |       |            |          |<br />|   2 |   TABLE ACCESS FULL| T_TEST1 |     1 |    86 |     2   (0)| 00:00:01 |<br />------------------------------------------------------------------------------<br /> <br />Predicate Information (identified by operation id):<br />---------------------------------------------------<br /> <br />   1 - filter(ROWNUM&lt;=1)<br /> <br /> <br />Statistics<br />----------------------------------------------------------<br />          0  recursive calls<br />          0  db block gets<br />          4  consistent gets<br />          0  physical reads<br />          0  redo size<br />       1201  bytes sent via SQL*Net to client<br />        385  bytes received via SQL*Net from client<br />          2  SQL*Net roundtrips to/from client<br />          0  sorts (memory)<br />          0  sorts (disk)<br />          1  rows processed<br /> <br /><br />3         ROWNUM的使用“陷阱”<br />由于ROWNUM是一个伪列，只有有结果记录时，ROWNUM才有相应数据，因此对它的使用不能向普通列那样使用，否则就会陷入一些“陷阱”当中。<br /><br />3.1     对ROWNUM进行>、>=、=操作<br />不能对ROWNUM使用>（大于1的数值）、>=（大于或等于1的数值）、=（大于或等于1的数值），否则无结果<br /><br /> <br /><br />SQL> select count(*) from css_bl_view a where rownum>0;<br /> <br />  COUNT(*)<br />----------<br />361928<br /> <br /> <br />SQL> select count(*) from css_bl_view a<br />  2  where rownum > 1;<br /> <br />  COUNT(*)<br />----------<br />         0<br /> <br /><br />这是因为：<br /><br />1、ROWNUM是伪列，必须要要有返回结果后，每条返回记录就会对应产生一个ROWNUM数值；<br /><br />2、返回结果记录的ROWNUM是从1开始排序的，因此第一条始终是1;<br /><br /> <br /><br />这样，当查询到第一条记录时，该记录的ROWNUM为1，但条件要求ROWNUM>1，因此不符合，继续查询下一条；因为前面没有符合要求的记录，因此下一条记录过来后，其ROWNUM还是为1，如此循环，就不会产生结果。上述查询可以通过子查询来替代：<br /><br /> <br /><br />SQL> select count(*)<br />  2  from<br />  3  (select BL_REF_CDE, rownum rn from css_bl_view)<br />  4  where rn > 1;<br /> <br />  COUNT(*)<br />----------<br />    361927<br /> <br /><br />我们可以通过以下方式来实现对ROWNUM的>、=的查询：<br /><br />查询ROWNUM=5的数据：<br /><br /> <br /><br />SQL> select object_id,object_name<br />  2  from (select object_id,object_name, rownum as rn from t_test1)<br />  3  where rn = 5;<br /> <br /> OBJECT_ID OBJECT_NAME<br />---------- ------------------------------<br />        29 C_COBJ#<br /> <br /><br />查询ROWNUM > 25的数据：<br /><br /> <br /><br />SQL> select * from t_test4<br />  2  minus<br />  3  select * from t_test4<br />  4  where rownum &lt;= 25;<br /> <br />USERNAME                          USER_ID CREATED<br />------------------------------ ---------- ---------<br />DIP                                    19 21-NOV-05<br />OUTLN                                  11 21-NOV-05<br />PUBLIC                              99999 18-JUL-07<br />SYS                                     0 21-NOV-05<br />SYSMAN                                 32 21-NOV-05<br />SYSTEM                                  5 21-NOV-05<br /> <br />6 rows selected.<br />3.2     ROWNUM和Order BY<br />要注意的是：在使用ROWNUM时，只有当Order By的字段是主键时，查询结果才会先排序再计算ROWNUM，下面OBJECT_ID是表T_TEST1的主键字段：<br /><br /> <br /><br />SQL> select object_id,object_name from t_test1<br />  2  where rownum &lt;= 5<br />  3  order by object_id;<br /> <br /> OBJECT_ID OBJECT_NAME<br />---------- ------------------------------<br />         2 C_OBJ#<br />         3 I_OBJ#<br />         4 TAB$<br />         5 CLU$<br />         6 C_TS#<br /> <br /><br />但是，对非主键字段OBJECT_NAME进行排序时，结果就混乱了：<br /><br /> <br /><br />SQL> select object_id,object_name from t_test1<br />  2  where rownum &lt;= 5<br />  3  order by object_name;<br /> <br /> OBJECT_ID OBJECT_NAME<br />---------- ------------------------------<br />        28 CON$<br />        29 C_COBJ#<br />        20 ICOL$<br />        44 I_USER1<br />        15 UNDO$<br /> <br />SQL> select count(*) from t_test1<br />  2  where object_name &lt; 'CON$';<br /> <br />  COUNT(*)<br />----------<br />     21645<br /> <br /><br />出现这种混乱的原因是：Oracle先按物理存储位置（rowid）顺序取出满足rownum条件的记录，即物理位置上的前5条数据，然后在对这些数据按照Order By的字段进行排序，而不是我们所期望的先排序、再取特定记录数。<br /><br /> <br /><br />如果需要对非主键字段排序再去前n条数据，我们可以以以下方式实现：<br /><br /> <br /><br />SQL> select object_id,object_name<br />  2  from (select object_id,object_name from t_test1<br />  3        order by object_name)<br />  4  where rownum &lt;= 5;<br /> <br /> OBJECT_ID OBJECT_NAME<br />---------- ------------------------------<br />     35489 /1000e8d1_LinkedHashMapValueIt<br />     35490 /1000e8d1_LinkedHashMapValueIt<br />     21801 /1005bd30_LnkdConstant<br />     21802 /1005bd30_LnkdConstant<br />     17205 /10076b23_OraCustomDatumClosur<br /> <br /><br />3.3     排序分页<br />当对存在重复值的字段排序后再分页输出，我们很容易会陷入到另外一个“陷阱”。<br /><br /> <br /><br />请看以下例子，我们希望对T_TEST1的OWNER字段排序后，以每页输出10个结果的方式分页输出：<br /><br /> <br /><br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name from t_test1 order by owner) a<br />  4  where rownum &lt;= 10)<br />  5  where rn >= 1;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWADAPTER<br />AFWOWNER                       AFWADAPTERCONFIGURATION<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX1<br />AFWOWNER                       AFWADAPTERFQN_PK<br />AFWOWNER                       AFWADAPTERCONFIGURATION_PK<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX2<br />AFWOWNER                       AFWSERVERCODE_PK<br />AFWOWNER                       AFWSERVER<br />AFWOWNER                       AFWADAPTERLOOKUP_IDX1<br />AFWOWNER                       AFWADAPTERLOOKUP<br /> <br />10 rows selected.<br /> <br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name from t_test1 order by owner) a<br />  4  where rownum &lt;= 20)<br />  5  where rn >= 11;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWTOKENSTATUSCODE_PK<br />AFWOWNER                       AFWTOKENSTATUS<br />AFWOWNER                       AFWTOKENADMIN_IDX1<br />AFWOWNER                       AFWTOKENADMINCODE_PK<br />AFWOWNER                       AFWTOKENADMIN<br />AFWOWNER                       AFWTOKEN<br />AFWOWNER                       AFWSERVERCONFIGURATION_PK<br />AFWOWNER                       AFWSERVERCONFIGURATION<br />AFWOWNER                       AFWSERVER<br />AFWOWNER                       AFWADAPTERLOOKUP<br /> <br />10 rows selected.<br /> <br /><br />仔细比较结果，你会发现“AFWSERVER”、“AFWADAPTERLOOKUP”在两次分页结果中都出现了。但是OBJECT_NAME在每个OWNER中的值是唯一的，说明这个输出结果是错误的，我们又陷入了一个“陷阱”。这是怎么回事呢，请先看下上述语句的查询计划：<br /><br /> <br /><br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name from t_test1 order by owner) a<br />  4  where rownum &lt;= 20)<br />  5  where rn >= 11;<br /> <br />10 rows selected.<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=205 Card=20 Bytes=94<br />          0)<br /> <br />   1    0   VIEW (Cost=205 Card=20 Bytes=940)<br />   2    1     COUNT (STOPKEY)<br />   3    2       VIEW (Cost=205 Card=30670 Bytes=1042780)<br />   4    3         SORT (ORDER BY STOPKEY) (Cost=205 Card=30670 Bytes=858760)<br />   5    4           TABLE ACCESS (FULL) OF 'T_TEST1' (Cost=42 Card=30670 Bytes=858760)<br /> <br /><br />看下这个“陷阱”是怎么形成的。从查询计划上，我们可以注意到，对于子查询<br /><br />select a.*, rownum as rn from<br />     (select owner, object_name from t_test1 order by owner) a<br />where rownum &lt;= 20<br />优化器采用了“SORT (ORDER BY STOPKEY)”。<br /><br /> <br /><br />“SORT (ORDER BY STOPKEY)”不需要对所有数据进行排序，而是只要找出结果集中的按特定顺序的最前N条记录，一旦找出了这N条记录，就无需再对剩下的数据进行排序，而直接返回结果。这种算法我们可以视为是“快速排序”算法的变种。快速排序算法的基本思想是：先将数据分2组集合，保证第一集合中的每个数据都大于第二个集合中每个数据，然后再按这个原则对每个集合进行递归分组，直到集合的单位最小。在进行“SORT (ORDER BY STOPKEY)”时，首先找出N条数据（这些数据并没有做排序）放在第一组，保证第一组的数据都大于第二组的数据，然后只对第一组数据进行递归。<br /><br />可以看到，基于这样的算法基础上，如果N的数值不同，数据的分组也不同（如N=20时，第一次分组比例为12:8，然后继续递归；当N=10时，第一次分组比例为3:7 … …），这样，在数据的排序字段值都相等时，输出结果的顺序就会因为N值不同而不同。<br /><br /> <br /><br />知道原因后，我们可以通过以下几种方法来避免这个“陷阱”。<br /><br />1、让查询计划避免“SORT (ORDER BY STOPKEY)”，采用“SORT (ORDER BY)”，使数据排序不受ROWNUM的影响。但这样会使所有数据都做排序：<br /><br /> <br /><br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name, rowid from t_test1 order by owner) a)<br />  4  where rn &lt;= 10<br />  5  and rn >= 1;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWADAPTER<br />AFWOWNER                       AFWADAPTERCONFIGURATION<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX2<br />AFWOWNER                       AFWADAPTERCONFIGURATION_PK<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX1<br />AFWOWNER                       AFWADAPTERFQN_PK<br />AFWOWNER                       AFWADAPTERLOOKUP_IDX1<br />AFWOWNER                       AFWSERVERCODE_PK<br />AFWOWNER                       AFWSERVERCONFIGURATION_IDX1<br />AFWOWNER                       AFWTOKENTYPECODE_PK<br /> <br />10 rows selected.<br /> <br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name, rowid from t_test1 order by owner) a)<br />  4  where rn &lt;= 20<br />  5  and rn >= 11;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWTOKENTYPE<br />AFWOWNER                       AFWTOKENSTATUSCODE_PK<br />AFWOWNER                       AFWTOKENSTATUS<br />AFWOWNER                       AFWTOKENADMIN_IDX1<br />AFWOWNER                       AFWTOKENADMINCODE_PK<br />AFWOWNER                       AFWTOKENADMIN<br />AFWOWNER                       AFWTOKEN<br />AFWOWNER                       AFWSERVERCONFIGURATION_PK<br />AFWOWNER                       AFWTOKEN_PK<br />AFWOWNER                       AFWTOKEN_IDX6<br /> <br />10 rows selected.<br /> <br />SQL> set autot trace<br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name, rowid from t_test1 order by owner) a)<br />  4  where rn &lt;= 20<br />  5  and rn >= 11;<br /> <br />10 rows selected.<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=237 Card=30670 Bytes=1441490)<br />   1    0   VIEW (Cost=237 Card=30670 Bytes=1441490)<br />   2    1     COUNT<br />   3    2       VIEW (Cost=237 Card=30670 Bytes=1042780)<br />   4    3         SORT (ORDER BY) (Cost=237 Card=30670 Bytes=1073450)<br />   5    4           TABLE ACCESS (FULL) OF 'T_TEST1' (Cost=42 Card=30670 Bytes=1073450)<br /> <br /><br />2、在排序时，加上一个或多个字段（如主键字段、ROWID），使排序结果具有唯一性：<br /><br /> <br /><br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name, rowid from t_test1 order by owner, object_id) a<br />  4  where rownum &lt;= 10)<br />  5  where rn >= 1;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWADAPTER<br />AFWOWNER                       AFWADAPTERFQN_PK<br />AFWOWNER                       AFWADAPTERCONFIGURATION<br />AFWOWNER                       AFWADAPTERCONFIGURATION_PK<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX1<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX2<br />AFWOWNER                       AFWADAPTERLOOKUP<br />AFWOWNER                       AFWADAPTERLOOKUP_IDX1<br />AFWOWNER                       AFWSERVER<br />AFWOWNER                       AFWSERVERCODE_PK<br /> <br />10 rows selected.<br /> <br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name, rowid from t_test1 order by owner, object_id) a<br />  4  where rownum &lt;= 20)<br />  5  where rn >= 11;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWSERVERCONFIGURATION<br />AFWOWNER                       AFWSERVERCONFIGURATION_PK<br />AFWOWNER                       AFWSERVERCONFIGURATION_IDX1<br />AFWOWNER                       AFWTOKEN<br />AFWOWNER                       AFWTOKEN_PK<br />AFWOWNER                       AFWTOKEN_IDX1<br />AFWOWNER                       AFWTOKEN_IDX2<br />AFWOWNER                       AFWTOKEN_IDX3<br />AFWOWNER                       AFWTOKEN_IDX4<br />AFWOWNER                       AFWTOKEN_IDX5<br /> <br />10 rows selected.<br /> <br />SQL> set autot trace<br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select owner, object_name, rowid from t_test1 order by owner, object_id) a<br />  4  where rownum &lt;= 20)<br />  5  where rn >= 11;<br /> <br />10 rows selected.<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=253 Card=20 Bytes=940)<br />   1    0   VIEW (Cost=253 Card=20 Bytes=940)<br />   2    1     COUNT (STOPKEY)<br />   3    2       VIEW (Cost=253 Card=30670 Bytes=1042780)<br />   4    3         SORT (ORDER BY STOPKEY) (Cost=253 Card=30670 Bytes=1196130)<br />   5    4           TABLE ACCESS (FULL) OF 'T_TEST1' (Cost=42 Card=306<br />          70 Bytes=1196130)<br /> <br /><br />3、对排序字段建立索引，并强制使用索引。这样就能利用索引已经建立好的排序结果：<br /><br />SQL> create index t_test1_idx1 on t_test1(owner);<br /> <br />Index created.<br /> <br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select /*+index(t T_TEST1_IDX1)*/owner, object_name from t_test1 t order by owner) a<br />  4  where rownum &lt;= 10)<br />  5  where rn >= 1<br />  6  ;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWADAPTER<br />AFWOWNER                       AFWADAPTERCONFIGURATION<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX1<br />AFWOWNER                       AFWADAPTERCONFIGURATION_IDX2<br />AFWOWNER                       AFWADAPTERCONFIGURATION_PK<br />AFWOWNER                       AFWADAPTERFQN_PK<br />AFWOWNER                       AFWADAPTERLOOKUP<br />AFWOWNER                       AFWADAPTERLOOKUP_IDX1<br />AFWOWNER                       AFWSERVER<br />AFWOWNER                       AFWSERVERCODE_PK<br /> <br />10 rows selected.<br /> <br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select /*+index(t T_TEST1_IDX1)*/owner, object_name from t_test1 t order by owner) a<br />  4  where rownum &lt;= 20)<br />  5  where rn >= 11;<br /> <br />OWNER                          OBJECT_NAME<br />------------------------------ ------------------------------<br />AFWOWNER                       AFWSERVERCONFIGURATION<br />AFWOWNER                       AFWSERVERCONFIGURATION_IDX1<br />AFWOWNER                       AFWSERVERCONFIGURATION_PK<br />AFWOWNER                       AFWTOKEN<br />AFWOWNER                       AFWTOKENADMIN<br />AFWOWNER                       AFWTOKENADMINCODE_PK<br />AFWOWNER                       AFWTOKENADMIN_IDX1<br />AFWOWNER                       AFWTOKENSTATUS<br />AFWOWNER                       AFWTOKENSTATUSCODE_PK<br />AFWOWNER                       AFWTOKENTYPE<br /> <br />10 rows selected.<br /> <br />SQL> set autot trace<br />SQL> select owner, object_name from<br />  2  (select a.*, rownum as rn from<br />  3  (select /*+index(t T_TEST1_IDX1)*/owner, object_name from t_test1 t order by owner) a<br />  4  where rownum &lt;= 20)<br />  5  where rn >= 11;<br /> <br />10 rows selected.<br /> <br /> <br />Execution Plan<br />----------------------------------------------------------<br />   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=414 Card=20 Bytes=940)<br />   1    0   VIEW (Cost=414 Card=20 Bytes=940)<br />   2    1     COUNT (STOPKEY)<br />   3    2       VIEW (Cost=414 Card=30670 Bytes=1042780)<br />   4    3         TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=414Card=30670 Bytes=858760)<br />   5    4           INDEX (FULL SCAN) OF 'T_TEST1_IDX1' (NON-UNIQUE) (<br />          Cost=26 Card=30670)<br /> <br /> <br /><br />以上就是ROWNUM的使用技巧及其注意事项，希望编程成员正确使用ROWNUM，也希望DBA遇到相关问题能迅速定位。
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/193204#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 May 2008 10:52:55 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/193204</link>
        <guid>http://seasar.javaeye.com/blog/193204</guid>
      </item>
      <item>
        <title>Oracle ROWNUM</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/193168" style="color:red;">http://seasar.javaeye.com/blog/193168</a>&nbsp;
          发表时间: 2008年05月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          ROWNUM<br />For each row returned by a query, the ROWNUM pseudocolumn returns a number indicating the order in which Oracle selects the row from a table or set of joined rows. The first row selected has a ROWNUM of 1, the second has 2, and so on.<br /><br />You can use ROWNUM to limit the number of rows returned by a query, as in this example:<br /><br />SELECT * FROM employees WHERE ROWNUM &lt; 10;<br /><br /><br />If an ORDER BY clause follows ROWNUM in the same query, then the rows will be reordered by the ORDER BY clause. The results can vary depending on the way the rows are accessed. For example, if the ORDER BY clause causes Oracle to use an index to access the data, then Oracle may retrieve the rows in a different order than without the index. Therefore, the following statement will not have the same effect as the preceding example:<br /><br />SELECT * FROM employees WHERE ROWNUM &lt; 11 ORDER BY last_name;<br /><br /><br />If you embed the ORDER BY clause in a subquery and place the ROWNUM condition in the top-level query, then you can force the ROWNUM condition to be applied after the ordering of the rows. For example, the following query returns the 10 smallest employee numbers. This is sometimes referred to as a "top-N query":<br /><br />SELECT * FROM<br />   (SELECT * FROM employees ORDER BY employee_id)<br />   WHERE ROWNUM &lt; 11;<br /><br /><br />In the preceding example, the ROWNUM values are those of the top-level SELECT statement, so they are generated after the rows have already been ordered by employee_id in the subquery.<br /><br />See Also: <br />Oracle9i Application Developer's Guide - Fundamentals for more information about top-N queries<br /> <br /><br />Conditions testing for ROWNUM values greater than a positive integer are always false. For example, this query returns no rows:<br /><br />SELECT * FROM employees<br />    WHERE ROWNUM > 1;<br /><br /><br />The first row fetched is assigned a ROWNUM of 1 and makes the condition false. The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 and makes the condition false. All rows subsequently fail to satisfy the condition, so no rows are returned.<br /><br />You can also use ROWNUM to assign unique values to each row of a table, as in this example:<br /><br />UPDATE my_table<br />    SET column1 = ROWNUM;<br /><br /><br />--------------------------------------------------------------------------------<br />Note: <br />Using ROWNUM in a query can affect view optimization. For more information, see Oracle9i Database Concepts.<br /><br />--------------------------------------------------------------------------------
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/193168#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 May 2008 09:35:41 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/193168</link>
        <guid>http://seasar.javaeye.com/blog/193168</guid>
      </item>
      <item>
        <title>Welcome to the Seasar Project!</title>
        <author>seasar</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://seasar.javaeye.com">seasar</a>&nbsp;
          链接：<a href="http://seasar.javaeye.com/blog/190563" style="color:red;">http://seasar.javaeye.com/blog/190563</a>&nbsp;
          发表时间: 2008年05月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Welcome to the Seasar Project!<br /><br />Today, Dependency-Injection is the most popular technology of Java. However, did it make our development work really easy? You must be still irritated with writing configuration files. Seasar2, the most popular open source framework in Japan, frees you from such annoyance and brings you comfortable DI Life. You will never look back at the DI as we know today.<br /><br />We believe strongly that:<br /><br />    * Configuration files must Die<br />    * Dependency Injection made easy
          <br/>
          <span style="color:red;">
            <a href="http://seasar.javaeye.com/blog/190563#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 07 May 2008 13:30:20 +0800</pubDate>
        <link>http://seasar.javaeye.com/blog/190563</link>
        <guid>http://seasar.javaeye.com/blog/190563</guid>
      </item>
  </channel>
</rss>