<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>grantbb</title>
    <description></description>
    <link>http://grantbb.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>DDOS总结</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/215583" style="color:red;">http://grantbb.javaeye.com/blog/215583</a>&nbsp;
          发表时间: 2008年07月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>百度上的知道解释的很清楚<br />
<a href="http://baike.baidu.com/view/5522.htm" target="_blank">http://baike.baidu.com/view/5522.htm</a><br />
<br />
可以尝试tomcat上配置两个connector<br />
<br />
采用NIO或者APR的方式配置（效率提升不多，线程数少，cpu上升不多）<br />
<a href="http://www.javaworld.com.tw/jute/post/view?bid=9&amp;id=139958&amp;sty=3&amp;age=0" target="_blank">http://www.javaworld.com.tw/jute/post/view?bid=9&amp;id=139958&amp;sty=3&amp;age=0</a><br />
<br />
全部为动态会降低性能 ，没有java可靠，安全性稳定性<br />
<br />
robbin：解决DDOS，放专门的硬件路由器<br />
<br />
架构的考虑，尽可能使用代理和缓存<br />
<br />
-----------<br />
QoS就是在路由上做啊 一台机器上用eth0做路由 eth1绑定服务 所有进来的包都要经过eth0 然后再转发到eth1.<br />
<br />
QoS限制进入eth1的带宽 超过限定 就随机丢包 eth1上还可以用netfilter再防一下<br />
<br />
分布式拒绝服务攻击(DDoS)原理及防范<br />
<a href="http://www.ibm.com/developerworks/cn/security/se-ddos/index.html" target="_blank">http://www.ibm.com/developerworks/cn/security/se-ddos/index.html</a></p>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/215583#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>Wed, 16 Jul 2008 22:51:30 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/215583</link>
        <guid>http://grantbb.javaeye.com/blog/215583</guid>
      </item>
      <item>
        <title>lucene中的filter器群组及其缓存大盘点</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/212414" style="color:red;">http://grantbb.javaeye.com/blog/212414</a>&nbsp;
          发表时间: 2008年07月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>lucene中的filter其实并不起眼,大家对其对性能的影响也不是很关注,但实际上filter是除了单纯搜索以外,其他搜索附加功能的必选组件,
其性能很大程度上会直接影响搜索的性能,之前我一直认为filter的性能比query高,但事实说明并不完全如此(这里所说的负荷是指io消耗并不是
cpu),实际上在lucene中充满着各种io流,也就是说很多东西都无法从根本上保存,这也给缓存带来了很大难度(这个问题看似简单,但是在超复杂的
组合查询下,缓存可能会几乎无用,原因就是key怎么把握)<br />
<br />
首先来看看filter的接口定义:<br />
public abstract class Filter implements java.io.Serializable {<br />
&nbsp; public abstract BitSet bits(IndexReader reader) throws IOException;<br />
}<br />
<br />
简单明了从reader中知道哪些记录是可以读出来的用true false放在bitsets中,然后再用这去和总集合做and操作得到剩余记录数,然后再通过query查询.原理知道了,下面来考虑下它的缓存:<br />
&nbsp;缓存filter本身,由于他是序列化对象,那么已经具备了缓存的条件,但是这是一个错误,因为你缓存了这个类,而当你把参数reader拿出来依然会和机器产生io,因此这是极其不恰当的方法,应该缓存它的结果.<br />
在lucene中有这么几个和filter有关的类:<br />
CachingWrapperFilter<br />
CachingSpanFilter<br />
RemoteCachingWrapperFilter<br />
FilterManager<br />
<br />
其实我想质疑前两个,为什么呢,请看他的源码:<br />
&nbsp; protected transient Map cache;<br />
<br />
他放置缓存的map居然是transient的,这意味着即使你把它实例在static中这个变量依然会每次要new的,这样的缓存有意义吗?我看不出他怎么缓存的<br />
&nbsp; /**<br />
&nbsp;&nbsp; * A transient Filter cache.&nbsp; To cache Filters even when using <a href="mailto:%7B@link">{@link</a>
 org.apache.lucene.search.RemoteSearchable} use<br />
&nbsp;&nbsp; * <a href="mailto:%7B@link">{@link</a>
 org.apache.lucene.search.RemoteCachingWrapperFilter} instead.<br />
&nbsp;&nbsp; */<br />
上面这句注释总算明了了,呵呵.<br />
那么其实RemoteCachingWrapperFilter才是真正的cache类,他的实现借助于filterManager,这个类是我们平时能理解的那种cache结构<br />
&nbsp; public BitSet bits(IndexReader reader) throws IOException {<br />
&nbsp;&nbsp;&nbsp; Filter cachedFilter = FilterManager.getInstance().getFilter(filter);<br />
&nbsp;&nbsp;&nbsp; return cachedFilter.bits(reader);<br />
&nbsp; }<br />
<br />
但这个还不够,第一他的性能我心里没谱,遇到上万的访问怎么办?所以还是要用第三方的缓存,我使用的是memcached,这个东西不介绍了,只有一个问题,就是必须要求对象是可序列化的,这个不难理解,要想网络传输只能治么搞.<br />
我的缓存策略:把最细胞的filter用memached缓存他的结果集,而他的组合fliter用自带的filtermanager管理就好了.filter怎么合在一起上次写过一个,看这里: <a href="http://www.edwardpro.com/post/572/" target="_blank">http://www.edwardpro.com/post/572/</a>
<br />
<br />
而
我这样的道理也是基于filtermanager的key是reader的hashcode,因此他是对应不同的索引的.那么肯定有朋友问怎么刷新呢?太
简单了啊,你的key只要有reader或者search的hashcode就可以了,你一旦更新的源hashcode就变化了.(如果你的search
和reader的hash不是固定的那么你肯定承受不了100以上的并行访问,io会高得惊人.)<br />
<br />
另外一个技巧,是关于
rangefilter的,这个东西不错,但是有一点难,在哪里呢?因为他的查询似乎效率不高,因此一定要缓存!
但是key呢?比如我常用的key是timestamp,但是实际中就会发现如果用毫秒的timestamp那么key几乎无用,因为很少相同的,经过改
进,我把时间可以用月做单位,查询也是如此,如果你的要求高我觉得做到天就ok了,如果你数据再多用到小时肯定也够了吧,这样filter的缓存会带来极
大的性能提升.<br />
<br />
那么实际效果呢,在原来使用时候2台集群机(nginx作为前端代理,后部用resin作为应用服务器)io平均1.xx
现在加了缓存之后常年保持在0.2左右!性能得到了几乎5~6倍的提升.而一般查询一个十万当量的+ 5个关键字 + 3个filter
时间大约是&lt;10ms 非命中时大约是 70~80ms 这个速度如果得到同样结果的数据库至少要放大1000倍的时间.<br />
<br />
由于我
memcached没有做集群是独立的(事实也应该如此,因为你两台机器的reader的hashcode肯定是不一样的,放一起也是这样的结果,这样也
没有不好,当一台机器出现问题或者需要更新代码可以用时间差来保证负荷平稳过渡,不像以前一台机器每次重启都是有点怕怕的,只能找空闲时间才敢这么做.<br />
<br />
最后要讲的query,其实前面我说了半天没有提到query,query的缓存呢? 其实在lucene中有这么个类:<br />
QueryFilter<br />
这个类简单说就是把query变成filter,那干什么呢?很简单啊,这样任何查询都会变成filter的,所以所有的缓存都是filter!那么从缓存中取出来的filterquery怎么用?<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;MatchAllDocsQuery matchAll = new MatchAllDocsQuery();<br />
&nbsp;&nbsp;&nbsp;&nbsp;result = isearch.search(matchAll, filter, sort);<br />
filter
是用我的合成filter组合的,这样消耗就更低了,当然不建议无限制增加系统负荷,因为那样就几乎无法重启了,呵呵.好了基本说到这里,其实最后我想说
我的核心思想: 任何query都是filter,lucene就是filter查询,事实是如此的,呵呵.<br />
<br />
大家有什么其他方案也可以讨论和交流一下,呵呵. 
		</p>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/212414#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>Mon, 07 Jul 2008 17:56:21 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/212414</link>
        <guid>http://grantbb.javaeye.com/blog/212414</guid>
      </item>
      <item>
        <title>[转]Lucene倒排索引原理</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/212365" style="color:red;">http://grantbb.javaeye.com/blog/212365</a>&nbsp;
          发表时间: 2008年07月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>Lucene是一个高性能的java全文检索工具包，它使用的是倒排文件索引结构。该结构及相应的生成算法如下：<br />
　　<br />
　　0）设有两篇文章1和2<br />
　　文章1的内容为：Tom lives in Guangzhou,I live in Guangzhou too.<br />
　　文章2的内容为：He once lived in Shanghai.<br />
　　<br />
　　1)由于lucene是基于关键词索引和查询的，首先我们要取得这两篇文章的关键词，通常我们需要如下处理措施<br />
　　a.我们现在有的是文章内容，即一个字符串，我们先要找出字符串中的所有单词，即分词。英文单词由于用空格分隔，比较好处理。中文单词间是连在一起的需要特殊的分词处理。<br />
　　b.文章中的&rdquo;in&rdquo;, &ldquo;once&rdquo; &ldquo;too&rdquo;等词没有什么实际意义，中文中的&ldquo;的&rdquo;&ldquo;是&rdquo;等字通常也无具体含义，这些不代表概念的词可以过滤掉<br />
　　c.用户通常希望查&ldquo;He&rdquo;时能把含&ldquo;he&rdquo;，&ldquo;HE&rdquo;的文章也找出来，所以所有单词需要统一大小写。<br />
　　d.用户通常希望查&ldquo;live&rdquo;时能把含&ldquo;lives&rdquo;，&ldquo;lived&rdquo;的文章也找出来，所以需要把&ldquo;lives&rdquo;，&ldquo;lived&rdquo;还原成&ldquo;live&rdquo;<br />
　　e.文章中的标点符号通常不表示某种概念，也可以过滤掉<br />
　　在lucene中以上措施由Analyzer类完成<br />
　　<br />
　　经过上面处理后<br />
　　 文章1的所有关键词为：[tom] [live] [guangzhou] [i] [live] [guangzhou]<br />
　　 文章2的所有关键词为：[he] [live] [shanghai]<br />
　　<br />
　　2) 有了关键词后，我们就可以建立倒排索引了。上面的对应关系是：&ldquo;文章号&rdquo;对&ldquo;文章中所有关键词&rdquo;。倒排索引把这个关系倒过来，变成：&ldquo;关键词&rdquo;对&ldquo;拥有该关键词的所有文章号&rdquo;。文章1，2经过倒排后变成<br />
　　关键词 文章号<br />
　　guangzhou 1<br />
　　he 2<br />
　　i 1<br />
　　live 1,2<br />
　　shanghai 2<br />
　　tom 1<br />
　　<br />
　　通常仅知道关键词在哪些文章中出现还不够，我们还需要知道关键词在文章中出现次数和出现的位置，通常有两种位置：a)字符位置，即记录该词是文章中第
几个字符（优点是关键词亮显时定位快）；b)关键词位置，即记录该词是文章中第几个关键词（优点是节约索引空间、词组（phase）查询
快），lucene 中记录的就是这种位置。<br />
　　<br />
　　加上&ldquo;出现频率&rdquo;和&ldquo;出现位置&rdquo;信息后，我们的索引结构变为：<br />
　　关键词 文章号[出现频率] 出现位置<br />
　　guangzhou 1[2] 3，6<br />
　　he 2[1] 1<br />
　　i 1[1] 4<br />
　　live 1[2],2[1] 2，5，2<br />
　　shanghai 2[1] 3<br />
　　tom 1[1] 1<br />
　　<br />
　　以live
这行为例我们说明一下该结构：live在文章1中出现了2次，文章2中出现了一次，它的出现位置为&ldquo;2,5,2&rdquo;这表示什么呢？我们需要结合文章号和出现
频率来分析，文章1中出现了2次，那么&ldquo;2,5&rdquo;就表示live在文章1中出现的两个位置，文章2中出现了一次，剩下的&ldquo;2&rdquo;就表示live是文章2中第
2个关键字。<br />
　　<br />
　　以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的（lucene没有使用B树结构），因此lucene可以用二元搜索算法快速定位关键词。<br />
　　<br />
　　实现时 lucene将上面三列分别作为词典文件（Term Dictionary）、频率文件(frequencies)、位置文件
(positions)保存。其中词典文件不仅保存有每个关键词，还保留了指向频率文件和位置文件的指针，通过指针可以找到该关键字的频率信息和位置信
息。<br />
　　<br />
　　 Lucene中使用了field的概念，用于表达信息所在位置（如标题中，文章中，url中），在建索引中，该field信息也记录在词典文件中，每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。<br />
　　<br />
　　为了减小索引文件的大小，Lucene对索引还使用了压缩技术。首先，对词典文件中的关键词进行了压缩，关键词压缩为&lt;前缀长度，后
缀&gt;，例如：当前词为&ldquo;阿拉伯语&rdquo;，上一个词为&ldquo;阿拉伯&rdquo;，那么&ldquo;阿拉伯语&rdquo;压缩为&lt;3，语&gt;。其次大量用到的是对数字的压缩，数字只
保存与上一个值的差值（这样可以减小数字的长度，进而减少保存该数字需要的字节数）。例如当前文章号是16389（不压缩要用3个字节保存），上一文章号
是16382，压缩后保存7（只用一个字节）。<br />
　　<br />
　　 下面我们可以通过对该索引的查询来解释一下为什么要建立索引。<br />
　　假设要查询单词 &ldquo;live&rdquo;，lucene先对词典二元查找、找到该词，通过指向频率文件的指针读出所有文章号，然后返回结果。词典通常非常小，因而，整个过程的时间是毫秒级的。<br />
　　而用普通的顺序匹配算法，不建索引，而是对所有文章的内容进行字符串匹配，这个过程将会相当缓慢，当文章数目很大时，时间往往是无法忍受的。</p>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/212365#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>Mon, 07 Jul 2008 15:51:16 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/212365</link>
        <guid>http://grantbb.javaeye.com/blog/212365</guid>
      </item>
      <item>
        <title>项目管理2</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/212114" style="color:red;">http://grantbb.javaeye.com/blog/212114</a>&nbsp;
          发表时间: 2008年07月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>项目经理就是要 做事很职业，做人很Nice </p>
<p>PM对外可以调整计划，但是不能够停止项目 </p>
<p>项目与产品的区别 </p>
<ul>
<li>项目：正确得做事 </li>
<li>产品：做正确的事 </li>
<li>项目 
<ul>
<li>要满足干系人的各种需求 </li>
<li>有项目的基线 </li>
</ul>
</li>
<li>产品 
<ul>
<li>要满足最终用户的需求 </li>
<li>要有市场方面的运作 </li>
<li>产品可以废弃，更需要连续化 </li>
</ul>
</li>
</ul>
<p>开天窗 </p>
<ul>
<li>把大家都不知道的事情，公开出来 </li>
</ul>
<p>运作 </p>
<ul>
<li>对于大家都知道的事情进行运作 </li>
</ul>
<p>项目是以目标来驱动的 </p>
<p>成功了的项目更加不好收尾，需要好好总结 </p>
<ul>
<li>成员的总结，发展方向 </li>
<li>项目的总结、经验、改进 </li>
<li>业务或者产品的总结 </li>
<li>管理的问题总结 </li>
</ul>
<p>什么是成功的项目？ </p>
<ul>
<li>在预计的时间范围内完成的 </li>
<li>在预计的预算内完成 </li>
<li>达到了预期的质量 </li>
<li>符合技术、质量等的要求 </li>
<li>客户验收通过 </li>
</ul>
<p>项目管理三角形 </p>
<ul>
<li>质量 = 面积 </li>
</ul>
<p>给客户培训就是培养感情 </p>
<p>要管理干系人，要多多沟通，去影响他们 </p>
<p>项目管理办公室 PMO </p>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/212114#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>Sun, 06 Jul 2008 21:29:19 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/212114</link>
        <guid>http://grantbb.javaeye.com/blog/212114</guid>
      </item>
      <item>
        <title>MySQL常用SQL列表</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/208185" style="color:red;">http://grantbb.javaeye.com/blog/208185</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Selecting a database:<br /><br />mysql> USE database;<br /><br />Listing databases:<br /><br />mysql> SHOW DATABASES;<br /><br />Listing tables in a db:<br /><br />mysql> SHOW TABLES;<br /><br />Describing the format of a table:<br /><br />mysql> DESCRIBE table;<br /><br />Creating a database:<br /><br />mysql> CREATE DATABASE db_name;<br /><br />Creating a table:<br /><br />mysql> CREATE TABLE table_name (field1_name TYPE(SIZE), field2_name TYPE(SIZE));<br />Ex: mysql> CREATE TABLE pet (name VARCHAR(20), sex CHAR(1), birth DATE);<br /><br />Load tab-delimited data into a table:<br /><br />mysql> LOAD DATA LOCAL INFILE "infile.txt" INTO TABLE table_name;<br />(Use \n for NULL)<br /><br />Inserting one row at a time:<br /><br />mysql> INSERT INTO table_name VALUES ('MyName', 'MyOwner', '2002-08-31');<br />(Use NULL for NULL)<br /><br />Retrieving information (general):<br /><br />mysql> SELECT from_columns FROM table WHERE conditions;<br />All values: SELECT * FROM table;<br />Some values: SELECT * FROM table WHERE rec_name = "value";<br />Multiple critera: SELECT * FROM TABLE WHERE rec1 = "value1" AND rec2 = "value2";<br /><br />Reloading a new data set into existing table:<br /><br />mysql> SET AUTOCOMMIT=1; # used for quick recreation of table<br />mysql> DELETE FROM pet;<br />mysql> LOAD DATA LOCAL INFILE "infile.txt" INTO TABLE table;<br /><br />Fixing all records with a certain value:<br /><br />mysql> UPDATE table SET column_name = "new_value" WHERE record_name = "value";<br /><br />Selecting specific columns:<br /><br />mysql> SELECT column_name FROM table;<br /><br />Retrieving unique output records:<br /><br />mysql> SELECT DISTINCT column_name FROM table;<br /><br />Sorting:<br /><br />mysql> SELECT col1, col2 FROM table ORDER BY col2;<br />Backwards: SELECT col1, col2 FROM table ORDER BY col2 DESC;<br /><br />Date calculations:<br /><br />mysql> SELECT CURRENT_DATE, (YEAR(CURRENT_DATE)-YEAR(date_col)) AS time_diff [FROM table];<br />MONTH(some_date) extracts the month value and DAYOFMONTH() extracts day.<br /><br />Pattern Matching:<br /><br />mysql> SELECT * FROM table WHERE rec LIKE "blah%";<br />(% is wildcard - arbitrary # of chars)<br />Find 5-char values: SELECT * FROM table WHERE rec like "_____";<br />(_ is any single character)<br /><br />Extended Regular Expression Matching:<br /><br />mysql> SELECT * FROM table WHERE rec RLIKE "^b$";<br />(. for char, [...] for char class, * for 0 or more instances<br />^ for beginning, {n} for repeat n times, and $ for end)<br />(RLIKE or REGEXP)<br />To force case-sensitivity, use "REGEXP BINARY"<br /><br />Counting Rows:<br /><br />mysql> SELECT COUNT(*) FROM table;<br /><br />Grouping with Counting:<br /><br />mysql> SELECT owner, COUNT(*) FROM table GROUP BY owner;<br />(GROUP BY groups together all records for each 'owner')<br /><br />Selecting from multiple tables:<br /><br />(Example)<br />mysql> SELECT pet.name, comment FROM pet, event WHERE pet.name = event.name;<br />(You can join a table to itself to compare by using 'AS')<br /><br />Currently selected database:<br /><br />mysql> SELECT DATABASE();<br /><br />Maximum value:<br /><br />mysql> SELECT MAX(col_name) AS label FROM table;<br /><br />Auto-incrementing rows:<br /><br />mysql> CREATE TABLE table (number INT NOT NULL AUTO_INCREMENT, name CHAR(10) NOT NULL);<br />mysql> INSERT INTO table (name) VALUES ("tom"),("dick"),("harry");<br /><br />Adding a column to an already-created table:<br /><br />mysql> ALTER TABLE tbl ADD COLUMN [column_create syntax] AFTER col_name;<br /><br />Removing a column:<br /><br />mysql> ALTER TABLE tbl DROP COLUMN col;<br />(Full ALTER TABLE syntax available at mysql.com.)<br /><br />Batch mode (feeding in a script):<br /><br /># mysql -u user -p &lt; batch_file<br />(Use -t for nice table layout and -vvv for command echoing.)<br />Alternatively: mysql> source batch_file;<br /><br />Backing up a database with mysqldump:<br /><br /># mysqldump --opt -u username -p database > database_backup.sql<br />(Use 'mysqldump --opt --all-databases > all_backup.sql' to backup everything.)<br />(More info at MySQL's docs.)
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/208185#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, 26 Jun 2008 12:20:02 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/208185</link>
        <guid>http://grantbb.javaeye.com/blog/208185</guid>
      </item>
      <item>
        <title>Lucene2.3.2发布了</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/190998" style="color:red;">http://grantbb.javaeye.com/blog/190998</a>&nbsp;
          发表时间: 2008年05月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最新的Lucene2.3.2发布了，主要修改了一些创建和修改索引时候的Bug。<br /><br />======================= Release 2.3.2 2008-05-05 =======================<br /><br />Bug fixes<br /><br /> 1. LUCENE-1191: On hitting OutOfMemoryError in any index-modifying<br />    methods in IndexWriter, do not commit any further changes to the<br />    index to prevent risk of possible corruption.  (Mike McCandless)<br /><br /> 2. LUCENE-1197: Fixed issue whereby IndexWriter would flush by RAM<br />    too early when TermVectors were in use.  (Mike McCandless)<br /><br /> 3. LUCENE-1198: Don't corrupt index if an exception happens inside<br />    DocumentsWriter.init (Mike McCandless)<br /><br /> 4. LUCENE-1199: Added defensive check for null indexReader before<br />    calling close in IndexModifier.close() (Mike McCandless)<br /><br /> 5. LUCENE-1200: Fix rare deadlock case in addIndexes* when<br />    ConcurrentMergeScheduler is in use (Mike McCandless)<br /><br /> 6. LUCENE-1208: Fix deadlock case on hitting an exception while<br />    processing a document that had triggered a flush (Mike McCandless)<br /><br /> 7. LUCENE-1210: Fix deadlock case on hitting an exception while<br />    starting a merge when using ConcurrentMergeScheduler (Mike McCandless)<br /><br /> 8. LUCENE-1222: Fix IndexWriter.doAfterFlush to always be called on<br />    flush (Mark Ferguson via Mike McCandless)<br />	<br /> 9. LUCENE-1226: Fixed IndexWriter.addIndexes(IndexReader[]) to commit<br />    successfully created compound files. (Michael Busch)<br /><br />10. LUCENE-1150: Re-expose StandardTokenizer's constants publicly;<br />    this was accidentally lost with LUCENE-966.  (Nicolas LalevÃ©e via<br />    Mike McCandless)<br /><br />11. LUCENE-1262: Fixed bug in BufferedIndexReader.refill whereby on<br />    hitting an exception in readInternal, the buffer is incorrectly<br />    filled with stale bytes such that subsequent calls to readByte()<br />    return incorrect results.  (Trejkaz via Mike McCandless)<br /><br />12. LUCENE-1270: Fixed intermittant case where IndexWriter.close()<br />    would hang after IndexWriter.addIndexesNoOptimize had been<br />    called.  (Stu Hood via Mike McCandless)<br />	<br />Build<br /><br /> 1. LUCENE-1230: Include *pom.xml* in source release files. (Michael Busch)
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/190998#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, 08 May 2008 11:54:28 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/190998</link>
        <guid>http://grantbb.javaeye.com/blog/190998</guid>
      </item>
      <item>
        <title>【转】Lucene使用与优化</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/183875" style="color:red;">http://grantbb.javaeye.com/blog/183875</a>&nbsp;
          发表时间: 2008年04月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我认为这篇文章作为入门，对Lucene的总结比较好：<br /><br />1 lucene简介<br />1.1 什么是lucene<br />Lucene是一个全文搜索框架，而不是应用产品。因此它并不像www.baidu.com 或者google Desktop那么拿来就能用，它只是提供了一种工具让你能实现这些产品。<br /><br />1.2 lucene能做什么<br />要回答这个问题，先要了解lucene的本质。实际上lucene的功能很单一，说到底，就是你给它若干个字符串，然后它为你提供一个全文搜索服务，告诉你你要搜索的关键词出现在哪里。知道了这个本质，你就可以发挥想象做任何符合这个条件的事情了。你可以把站内新闻都索引了，做个资料库；你可以把一个数据库表的若干个字段索引起来，那就不用再担心因为“%like%”而锁表了；你也可以写个自己的搜索引擎……<br /><br />1.3 你该不该选择lucene<br />下面给出一些测试数据，如果你觉得可以接受，那么可以选择。<br />测试一：250万记录，300M左右文本，生成索引380M左右，800线程下平均处理时间300ms。<br />测试二：37000记录，索引数据库中的两个varchar字段，索引文件2.6M，800线程下平均处理时间1.5ms。<br /><br />2 lucene的工作方式<br />lucene提供的服务实际包含两部分：一入一出。所谓入是写入，即将你提供的源（本质是字符串）写入索引或者将其从索引中删除；所谓出是读出，即向用户提供全文搜索服务，让用户可以通过关键词定位源。<br /><br />2.1写入流程<br />源字符串首先经过analyzer处理，包括：分词，分成一个个单词；去除stopword（可选）。<br />将源中需要的信息加入Document的各个Field中，并把需要索引的Field索引起来，把需要存储的Field存储起来。<br />将索引写入存储器，存储器可以是内存或磁盘。<br /><br />2.2读出流程<br />用户提供搜索关键词，经过analyzer处理。<br />对处理后的关键词搜索索引找出对应的Document。<br />用户根据需要从找到的Document中提取需要的Field。<br /><br />3 一些需要知道的概念<br />lucene用到一些概念，了解它们的含义，有利于下面的讲解。<br /><br />3.1 analyzer<br />Analyzer 是分析器，它的作用是把一个字符串按某种规则划分成一个个词语，并去除其中的无效词语，这里说的无效词语是指英文中的“of”、 “the”，中文中的“的”、“地”等词语，这些词语在文章中大量出现，但是本身不包含什么关键信息，去掉有利于缩小索引文件、提高效率、提高命中率。<br />分词的规则千变万化，但目的只有一个：按语义划分。这点在英文中比较容易实现，因为英文本身就是以单词为单位的，已经用空格分开；而中文则必须以某种方法将连成一片的句子划分成一个个词语。具体划分方法下面再详细介绍，这里只需了解分析器的概念即可。<br /><br />3.2 document<br />用户提供的源是一条条记录，它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后，就是以一个Document的形式存储在索引文件中的。用户进行搜索，也是以Document列表的形式返回。<br /><br />3.3 field<br />一个Document可以包含多个信息域，例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域，这些信息域就是通过Field在Document中存储的。<br />Field有两个属性可选：存储和索引。通过存储属性你可以控制是否对这个Field进行存储；通过索引属性你可以控制是否对该Field进行索引。这看起来似乎有些废话，事实上对这两个属性的正确组合很重要，下面举例说明：<br />还是以刚才的文章为例子，我们需要对标题和正文进行全文搜索，所以我们要把索引属性设置为真，同时我们希望能直接从搜索结果中提取文章标题，所以我们把标题域的存储属性设置为真，但是由于正文域太大了，我们为了缩小索引文件大小，将正文域的存储属性设置为假，当需要时再直接读取文件；我们只是希望能从搜索解果中提取最后修改时间，不需要对它进行搜索，所以我们把最后修改时间域的存储属性设置为真，索引属性设置为假。上面的三个域涵盖了两个属性的三种组合，还有一种全为假的没有用到，事实上Field不允许你那么设置，因为既不存储又不索引的域是没有意义的。<br /><br />3.4 term<br />term是搜索的最小单位，它表示文档的一个词语，term由两部分组成：它表示的词语和这个词语所出现的field。<br /><br />3.5 tocken<br />tocken是term的一次出现，它包含trem文本和相应的起止偏移，以及一个类型字符串。一句话中可以出现多次相同的词语，它们都用同一个term表示，但是用不同的tocken，每个tocken标记该词语出现的地方。<br /><br />3.6 segment<br />添加索引时并不是每个document都马上添加到同一个索引文件，它们首先被写入到不同的小文件，然后再合并成一个大索引文件，这里每个小文件都是一个segment。<br />4 lucene的结构<br />lucene包括core和sandbox两部分，其中core是lucene稳定的核心部分，sandbox包含了一些附加功能，例如highlighter、各种分析器。<br />Lucene core有七个包：analysis，document，index，queryParser，search，store，util。<br />4.1 analysis<br />Analysis包含一些内建的分析器，例如按空白字符分词的WhitespaceAnalyzer，添加了stopwrod过滤的StopAnalyzer，最常用的StandardAnalyzer。<br />4.2 document<br />Document包含文档的数据结构，例如Document类定义了存储文档的数据结构，Field类定义了Document的一个域。<br />4.3 index<br />Index 包含了索引的读写类，例如对索引文件的segment进行写、合并、优化的IndexWriter类和对索引进行读取和删除操作的 IndexReader类，这里要注意的是不要被IndexReader这个名字误导，以为它是索引文件的读取类，实际上删除索引也是由它完成， IndexWriter只关心如何将索引写入一个个segment，并将它们合并优化；IndexReader则关注索引文件中各个文档的组织形式。<br />4.4 queryParser<br />QueryParser 包含了解析查询语句的类，lucene的查询语句和sql语句有点类似，有各种保留字，按照一定的语法可以组成各种查询。 Lucene有很多种Query类，它们都继承自Query，执行各种特殊的查询，QueryParser的作用就是解析查询语句，按顺序调用各种 Query类查找出结果。<br />4.5 search<br />Search包含了从索引中搜索结果的各种类，例如刚才说的各种Query类，包括TermQuery、BooleanQuery等就在这个包里。<br />4.6 store<br />Store包含了索引的存储类，例如Directory定义了索引文件的存储结构，FSDirectory为存储在文件中的索引，RAMDirectory为存储在内存中的索引，MmapDirectory为使用内存映射的索引。<br />4.7 util<br />Util包含一些公共工具类，例如时间和字符串之间的转换工具。<br />5 如何建索引<br />5.1 最简单的能完成索引的代码片断<br /><br />IndexWriter writer = new IndexWriter(“/data/index/”, new StandardAnalyzer(), true);<br />Document doc = new Document();<br />doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));<br />doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED));<br />writer.addDocument(doc);<br />writer.optimize();<br />writer.close();<br /><br />下面我们分析一下这段代码。<br />首先我们创建了一个writer，并指定存放索引的目录为“/data/index”，使用的分析器为StandardAnalyzer，第三个参数说明如果已经有索引文件在索引目录下，我们将覆盖它们。<br />然后我们新建一个document。<br />我们向document添加一个field，名字是“title”，内容是“lucene introduction”，对它进行存储并索引。<br />再添加一个名字是“content”的field，内容是“lucene works well”，也是存储并索引。<br />然后我们将这个文档添加到索引中，如果有多个文档，可以重复上面的操作，创建document并添加。<br />添加完所有document，我们对索引进行优化，优化主要是将多个segment合并到一个，有利于提高索引速度。<br />随后将writer关闭，这点很重要。<br /><br />对，创建索引就这么简单！<br />当然你可能修改上面的代码获得更具个性化的服务。<br /><br />5.2 将索引直接写在内存<br />你需要首先创建一个RAMDirectory，并将其传给writer，代码如下：<br /><br />Directory dir = new RAMDirectory();<br />IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(), true);<br />Document doc = new Document();<br />doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));<br />doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED));<br />writer.addDocument(doc);<br />writer.optimize();<br />writer.close();<br /><br />5.3 索引文本文件<br />如果你想把纯文本文件索引起来，而不想自己将它们读入字符串创建field，你可以用下面的代码创建field：<br /><br />Field field = new Field("content", new FileReader(file));<br /><br />这里的file就是该文本文件。该构造函数实际上是读去文件内容，并对其进行索引，但不存储。<br /><br />6 如何维护索引<br />索引的维护操作都是由IndexReader类提供。<br /><br />6.1 如何删除索引<br />lucene提供了两种从索引中删除document的方法，一种是<br /><br />void deleteDocument(int docNum)<br /><br />这种方法是根据document在索引中的编号来删除，每个document加进索引后都会有个唯一编号，所以根据编号删除是一种精确删除，但是这个编号是索引的内部结构，一般我们不会知道某个文件的编号到底是几，所以用处不大。另一种是<br /><br />void deleteDocuments(Term term)<br /><br />这种方法实际上是首先根据参数term执行一个搜索操作，然后把搜索到的结果批量删除了。我们可以通过这个方法提供一个严格的查询条件，达到删除指定document的目的。<br />下面给出一个例子：<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexReader reader = IndexReader.open(dir);<br />Term term = new Term(field, key);<br />reader.deleteDocuments(term);<br />reader.close();<br /><br />6.2 如何更新索引<br />lucene并没有提供专门的索引更新方法，我们需要先将相应的document删除，然后再将新的document加入索引。例如：<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexReader reader = IndexReader.open(dir);<br />Term term = new Term(“title”, “lucene introduction”);<br />reader.deleteDocuments(term);<br />reader.close();<br /><br />IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(), true);<br />Document doc = new Document();<br />doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));<br />doc.add(new Field("content", "lucene is funny", Field.Store.YES, Field.Index.TOKENIZED));<br />writer.addDocument(doc);<br />writer.optimize();<br />writer.close();<br />7 如何搜索<br />lucene 的搜索相当强大，它提供了很多辅助查询类，每个类都继承自Query类，各自完成一种特殊的查询，你可以像搭积木一样将它们任意组合使用，完成一些复杂操作；另外lucene还提供了Sort类对结果进行排序，提供了Filter类对查询条件进行限制。你或许会不自觉地拿它跟SQL语句进行比较： “lucene能执行and、or、order by、where、like ‘%xx%’操作吗？”回答是：“当然没问题！”<br /><br />7.1 各种各样的Query<br />下面我们看看lucene到底允许我们进行哪些查询操作：<br /><br />7.1.1 TermQuery<br />首先介绍最基本的查询，如果你想执行一个这样的查询：“在content域中包含‘lucene’的document”，那么你可以用TermQuery：<br /><br />Term t = new Term("content", " lucene";<br />Query query = new TermQuery(t);<br /><br />7.1.2 BooleanQuery<br />如果你想这么查询：“在content域中包含java或perl的document”，那么你可以建立两个TermQuery并把它们用BooleanQuery连接起来：<br /><br />TermQuery termQuery1 = new TermQuery(new Term("content", "java");<br />TermQuery termQuery 2 = new TermQuery(new Term("content", "perl");<br />BooleanQuery booleanQuery = new BooleanQuery();<br />booleanQuery.add(termQuery 1, BooleanClause.Occur.SHOULD);<br />booleanQuery.add(termQuery 2, BooleanClause.Occur.SHOULD);<br /><br />7.1.3 WildcardQuery<br />如果你想对某单词进行通配符查询，你可以用WildcardQuery，通配符包括’?’匹配一个任意字符和’*’匹配零个或多个任意字符，例如你搜索’use*’，你可能找到’useful’或者’useless’：<br /><br />Query query = new WildcardQuery(new Term("content", "use*");<br /><br />7.1.4 PhraseQuery<br />你可能对中日关系比较感兴趣，想查找‘中’和‘日’挨得比较近（5个字的距离内）的文章，超过这个距离的不予考虑，你可以：<br /><br />PhraseQuery query = new PhraseQuery();<br />query.setSlop(5);<br />query.add(new Term("content ", “中”));<br />query.add(new Term(“content”, “日”));<br /><br />那么它可能搜到“中日合作……”、“中方和日方……”，但是搜不到“中国某高层领导说日本欠扁”。<br /><br />7.1.5 PrefixQuery<br />如果你想搜以‘中’开头的词语，你可以用PrefixQuery：<br /><br />PrefixQuery query = new PrefixQuery(new Term("content ", "中");<br /><br />7.1.6 FuzzyQuery<br />FuzzyQuery用来搜索相似的term，使用Levenshtein算法。假设你想搜索跟‘wuzza’相似的词语，你可以：<br /><br />Query query = new FuzzyQuery(new Term("content", "wuzza");<br /><br />你可能得到‘fuzzy’和‘wuzzy’。<br /><br />7.1.7 RangeQuery<br />另一个常用的Query是RangeQuery，你也许想搜索时间域从20060101到20060130之间的document，你可以用RangeQuery：<br /><br />RangeQuery query = new RangeQuery(new Term(“time”, “20060101”), new Term(“time”, “20060130”), true);<br /><br />最后的true表示用闭合区间。<br /><br />7.2 QueryParser<br />看了这么多Query，你可能会问：“不会让我自己组合各种Query吧，太麻烦了！”当然不会，lucene提供了一种类似于SQL语句的查询语句，我们姑且叫它lucene语句，通过它，你可以把各种查询一句话搞定，lucene会自动把它们查分成小块交给相应Query执行。下面我们对应每种 Query演示一下：<br />TermQuery可以用“field:key”方式，例如“content:lucene”。<br />BooleanQuery中‘与’用‘+’，‘或’用‘ ’，例如“content:java contenterl”。<br />WildcardQuery仍然用‘?’和‘*’，例如“content:use*”。<br />PhraseQuery用‘~’，例如“content:"中日"~5”。<br />PrefixQuery用‘*’，例如“中*”。<br />FuzzyQuery用‘~’，例如“content: wuzza ~”。<br />RangeQuery用‘[]’或‘{}’，前者表示闭区间，后者表示开区间，例如“time:[20060101 TO 20060130]”，注意TO区分大小写。<br />你可以任意组合query string，完成复杂操作，例如“标题或正文包括lucene，并且时间在20060101到20060130之间的文章”可以表示为：“+ (title:lucene content:lucene) +time:[20060101 TO 20060130]”。代码如下：<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexSearcher is = new IndexSearcher(dir);<br />QueryParser parser = new QueryParser("content", new StandardAnalyzer());<br />Query query = parser.parse("+(title:lucene content:lucene) +time:[20060101 TO 20060130]";<br />Hits hits = is.search(query);<br />for (int i = 0; i &lt; hits.length(); i++)<br />{<br />Document doc = hits.doc(i);<br />System.out.println(doc.get("title");<br />}<br />is.close();<br /><br />首先我们创建一个在指定文件目录上的IndexSearcher。<br />然后创建一个使用StandardAnalyzer作为分析器的QueryParser，它默认搜索的域是content。<br />接着我们用QueryParser来parse查询字串，生成一个Query。<br />然后利用这个Query去查找结果，结果以Hits的形式返回。<br />这个Hits对象包含一个列表，我们挨个把它的内容显示出来。<br /><br />7.3 Filter<br />filter 的作用就是限制只查询索引的某个子集，它的作用有点像SQL语句里的where，但又有区别，它不是正规查询的一部分，只是对数据源进行预处理，然后交给查询语句。注意它执行的是预处理，而不是对查询结果进行过滤，所以使用filter的代价是很大的，它可能会使一次查询耗时提高一百倍。<br />最常用的filter是RangeFilter和QueryFilter。RangeFilter是设定只搜索指定范围内的索引；QueryFilter是在上次查询的结果中搜索。<br />Filter的使用非常简单，你只需创建一个filter实例，然后把它传给searcher。继续上面的例子，查询“时间在20060101到20060130之间的文章”除了将限制写在query string中，你还可以写在RangeFilter中：<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexSearcher is = new IndexSearcher(dir);<br />QueryParser parser = new QueryParser("content", new StandardAnalyzer());<br />Query query = parser.parse("title:lucene content:lucene";<br />RangeFilter filter = new RangeFilter("time", "20060101", "20060230", true, true);<br />Hits hits = is.search(query, filter);<br />for (int i i &lt; hits.length(); i++)<br />{<br />Document doc = hits.doc(i);<br />System.out.println(doc.get("title");<br />}<br />is.close();<br /><br />7.4 Sort<br />有时你想要一个排好序的结果集，就像SQL语句的“order by”，lucene能做到：通过Sort。<br />Sort sort Sort(“time”); //相当于SQL的“order by time”<br />Sort sort = new Sort(“time”, true); // 相当于SQL的“order by time desc”<br />下面是一个完整的例子：<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexSearcher is = new IndexSearcher(dir);<br />QueryParser parser = new QueryParser("content", new StandardAnalyzer());<br />Query query = parser.parse("title:lucene content:lucene";<br />RangeFilter filter = new RangeFilter("time", "20060101", "20060230", true, true);<br />Sort sort = new Sort(“time”);<br />Hits hits = is.search(query, filter, sort);<br />for (int i = 0; i &lt; hits.length(); i++)<br />{<br />Document doc = hits.doc(i);<br />System.out.println(doc.get("title");<br />}<br />is.close();<br /><br />8 分析器<br />在前面的概念介绍中我们已经知道了分析器的作用，就是把句子按照语义切分成一个个词语。英文切分已经有了很成熟的分析器： StandardAnalyzer，很多情况下StandardAnalyzer是个不错的选择。甚至你会发现StandardAnalyzer也能对中文进行分词。<br />但是我们的焦点是中文分词，StandardAnalyzer能支持中文分词吗？实践证明是可以的，但是效果并不好，搜索“如果”会把“牛奶不如果汁好喝”也搜索出来，而且索引文件很大。那么我们手头上还有什么分析器可以使用呢？core里面没有，我们可以在sandbox里面找到两个： ChineseAnalyzer和CJKAnalyzer。但是它们同样都有分词不准的问题。相比之下用StandardAnalyzer和 ChineseAnalyzer建立索引时间差不多，索引文件大小也差不多，CJKAnalyzer表现会差些，索引文件大且耗时比较长。<br />要解决问题，首先分析一下这三个分析器的分词方式。StandardAnalyzer和ChineseAnalyzer都是把句子按单个字切分，也就是说 “牛奶不如果汁好喝”会被它们切分成“牛 奶 不 如 果 汁 好 喝”；而CJKAnalyzer则会切分成“牛奶 奶不 不如 如果 果汁汁好好喝”。这也就解释了为什么搜索“果汁”都能匹配这个句子。<br />以上分词的缺点至少有两个：匹配不准确和索引文件大。我们的目标是将上面的句子分解成“牛奶 不如果汁好喝”。这里的关键就是语义识别，我们如何识别“牛奶”是一个词而“奶不”不是词语？我们很自然会想到基于词库的分词法，也就是我们先得到一个词库，里面列举了大部分词语，我们把句子按某种方式切分，当得到的词语与词库中的项匹配时，我们就认为这种切分是正确的。这样切词的过程就转变成匹配的过程，而匹配的方式最简单的有正向最大匹配和逆向最大匹配两种，说白了就是一个从句子开头向后进行匹配，一个从句子末尾向前进行匹配。基于词库的分词词库非常重要，词库的容量直接影响搜索结果，在相同词库的前提下，据说逆向最大匹配优于正向最大匹配。<br />当然还有别的分词方法，这本身就是一个学科，我这里也没有深入研究。回到具体应用，我们的目标是能找到成熟的、现成的分词工具，避免重新发明车轮。经过网上搜索，用的比较多的是中科院的ICTCLAS和一个不开放源码但是免费的JE-Analysis。ICTCLAS有个问题是它是一个动态链接库， java调用需要本地方法调用，不方便也有安全隐患，而且口碑也确实不大好。JE-Analysis效果还不错，当然也会有分词不准的地方，相比比较方便放心。= new = 0;<br />9 性能优化<br />一直到这里，我们还是在讨论怎么样使lucene跑起来，完成指定任务。利用前面说的也确实能完成大部分功能。但是测试表明lucene的性能并不是很好，在大数据量大并发的条件下甚至会有半分钟返回的情况。另外大数据量的数据初始化建立索引也是一个十分耗时的过程。那么如何提高lucene的性能呢？下面从优化创建索引性能和优化搜索性能两方面介绍。<br /><br />9.1 优化创建索引性能<br />这方面的优化途径比较有限，IndexWriter提供了一些接口可以控制建立索引的操作，另外我们可以先将索引写入RAMDirectory，再批量写入FSDirectory，不管怎样，目的都是尽量少的文件IO，因为创建索引的最大瓶颈在于磁盘IO。另外选择一个较好的分析器也能提高一些性能。<br /><br />9.1.1 通过设置IndexWriter的参数优化索引建立<br />setMaxBufferedDocs(int maxBufferedDocs)<br />控制写入一个新的segment前内存中保存的document的数目，设置较大的数目可以加快建索引速度，默认为10。<br />setMaxMergeDocs(int maxMergeDocs)<br />控制一个segment中可以保存的最大document数目，值较小有利于追加索引的速度，默认Integer.MAX_VALUE，无需修改。<br />setMergeFactor(int mergeFactor)<br />控制多个segment合并的频率，值较大时建立索引速度较快，默认是10，可以在建立索引时设置为100。<br /><br />9.1.2 通过RAMDirectory缓写提高性能<br />我们可以先把索引写入RAMDirectory，达到一定数量时再批量写进FSDirectory，减少磁盘IO次数。<br /><br />FSDirectory fsDir = FSDirectory.getDirectory("/data/index", true);<br />RAMDirectory ramDir = new RAMDirectory();<br />IndexWriter fsWriter = new IndexWriter(fsDir, new StandardAnalyzer(), true);<br />IndexWriter ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);<br />while (there are documents to index)<br />{<br />... create Document ...<br />ramWriter.addDocument(doc);<br />if (condition for flushing memory to disk has been met)<br />{<br />fsWriter.addIndexes(new Directory[] { ramDir });<br />ramWriter.close();<br />ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);<br />}<br />}<br /><br />9.1.3 选择较好的分析器<br />这个优化主要是对磁盘空间的优化，可以将索引文件减小将近一半，相同测试数据下由600M减少到380M。但是对时间并没有什么帮助，甚至会需要更长时间，因为较好的分析器需要匹配词库，会消耗更多cpu，测试数据用StandardAnalyzer耗时133分钟；用MMAnalyzer耗时150分钟。<br /><br />9.2 优化搜索性能<br />虽然建立索引的操作非常耗时，但是那毕竟只在最初创建时才需要，平时只是少量的维护操作，更何况这些可以放到一个后台进程处理，并不影响用户搜索。我们创建索引的目的就是给用户搜索，所以搜索的性能才是我们最关心的。下面就来探讨一下如何提高搜索性能。<br /><br />9.2.1 将索引放入内存<br />这是一个最直观的想法，因为内存比磁盘快很多。Lucene提供了RAMDirectory可以在内存中容纳索引：<br /><br />Directory fsDir = FSDirectory.getDirectory(“/data/index/”, false);<br />Directory ramDir = new RAMDirectory(fsDir);<br />Searcher searcher = new IndexSearcher(ramDir);<br /><br />但是实践证明RAMDirectory和FSDirectory速度差不多，当数据量很小时两者都非常快，当数据量较大时（索引文件400M）RAMDirectory甚至比FSDirectory还要慢一点，这确实让人出乎意料。<br />而且lucene的搜索非常耗内存，即使将400M的索引文件载入内存，在运行一段时间后都会out of memory，所以个人认为载入内存的作用并不大。<br /><br />9.2.2 优化时间范围限制<br />既然载入内存并不能提高效率，一定有其它瓶颈，经过测试发现最大的瓶颈居然是时间范围限制，那么我们可以怎样使时间范围限制的代价最小呢？<br />当需要搜索指定时间范围内的结果时，可以：<br />1、用RangeQuery，设置范围，但是RangeQuery的实现实际上是将时间范围内的时间点展开，组成一个个BooleanClause加入到 BooleanQuery中查询，因此时间范围不可能设置太大，经测试，范围超过一个月就会抛BooleanQuery.TooManyClauses，可以通过设置 BooleanQuery.setMaxClauseCount(int maxClauseCount)扩大，但是扩大也是有限的，并且随着maxClauseCount扩大，占用内存也扩大<br />2、用 RangeFilter代替RangeQuery，经测试速度不会比RangeQuery慢，但是仍然有性能瓶颈，查询的90%以上时间耗费在 RangeFilter，研究其源码发现RangeFilter实际上是首先遍历所有索引，生成一个BitSet，标记每个document，在时间范围内的标记为true，不在的标记为false，然后将结果传递给Searcher查找，这是十分耗时的。<br />3、进一步提高性能，这个又有两个思路：<br />a、缓存Filter结果。既然RangeFilter的执行是在搜索之前，那么它的输入都是一定的，就是IndexReader，而 IndexReader是由Directory决定的，所以可以认为RangeFilter的结果是由范围的上下限决定的，也就是由具体的 RangeFilter对象决定，所以我们只要以RangeFilter对象为键，将filter结果BitSet缓存起来即可。lucene API已经提供了一个CachingWrapperFilter类封装了Filter及其结果，所以具体实施起来我们可以cache CachingWrapperFilter对象，需要注意的是，不要被CachingWrapperFilter的名字及其说明误导， CachingWrapperFilter看起来是有缓存功能，但的缓存是针对同一个filter的，也就是在你用同一个filter过滤不同 IndexReader时，它可以帮你缓存不同IndexReader的结果，而我们的需求恰恰相反，我们是用不同filter过滤同一个 IndexReader，所以只能把它作为一个封装类。<br />b、降低时间精度。研究Filter的工作原理可以看出，它每次工作都是遍历整个索引的，所以时间粒度越大，对比越快，搜索时间越短，在不影响功能的情况下，时间精度越低越好，有时甚至牺牲一点精度也值得，当然最好的情况是根本不作时间限制。<br />下面针对上面的两个思路演示一下优化结果（都采用800线程随机关键词随即时间范围）：<br />第一组，时间精度为秒：<br />方式 直接用RangeFilter 使用cache 不用filter<br />平均每个线程耗时 10s 1s 300ms<br /><br />第二组，时间精度为天<br />方式 直接用RangeFilter 使用cache 不用filter<br />平均每个线程耗时 900ms 360ms 300ms<br /><br />由以上数据可以得出结论：<br />1、 尽量降低时间精度，将精度由秒换成天带来的性能提高甚至比使用cache还好，最好不使用filter。<br />2、 在不能降低时间精度的情况下，使用cache能带了10倍左右的性能提高。<br /><br />9.2.3 使用更好的分析器<br />这个跟创建索引优化道理差不多，索引文件小了搜索自然会加快。当然这个提高也是有限的。较好的分析器相对于最差的分析器对性能的提升在20%以下。<br /><br />10 一些经验<br /><br />10.1关键词区分大小写<br />or AND TO等关键词是区分大小写的，lucene只认大写的，小写的当做普通单词。<br /><br />10.2 读写互斥性<br />同一时刻只能有一个对索引的写操作，在写的同时可以进行搜索<br /><br />10.3 文件锁<br />在写索引的过程中强行退出将在tmp目录留下一个lock文件，使以后的写操作无法进行，可以将其手工删除<br /><br />10.4 时间格式<br />lucene只支持一种时间格式yyMMddHHmmss，所以你传一个yy-MM-dd HH:mm:ss的时间给lucene它是不会当作时间来处理的<br /><br />10.5 设置boost<br />有些时候在搜索时某个字段的权重需要大一些，例如你可能认为标题中出现关键词的文章比正文中出现关键词的文章更有价值，你可以把标题的boost设置的更大，那么搜索结果会优先显示标题中出现关键词的文章（没有使用排序的前题下）。使用方法：<br />Field. setBoost(float boost);默认值是1.0，也就是说要增加权重的需要设置得比1大。 <br /><br /><br />Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2235951
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/183875#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, 17 Apr 2008 18:57:39 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/183875</link>
        <guid>http://grantbb.javaeye.com/blog/183875</guid>
      </item>
      <item>
        <title>Lucene的评分(score)机制的简单解释</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/181802" style="color:red;">http://grantbb.javaeye.com/blog/181802</a>&nbsp;
          发表时间: 2008年04月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          通过Searcher.explain(Query query, int doc)方法可以查看某个文档的得分的具体构成。<br /><br />在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。<br /><br />tf：是查询的词在文档中出现的次数的平方根<br />idf：表示反转文档频率，观察了一下所有的文档都一样，所以那就没什么用处，不会起什么决定作用。<br />boost：激励因子，可以通过setBoost方法设置，需要说明的通过field和doc都可以设置，所设置的值会同时起作用<br />lengthNorm：是由搜索的field的长度决定了，越长文档的分值越低。<br /><br />所以我们编程能够控制score的就是设置boost值。<br /><br />还有个问题，为什么一次查询后最大的分值总是1.0呢？<br />因为Lucene会把计算后，最大分值超过1.0的分值作为分母，其他的文档的分值都除以这个最大值，计算出最终的得分。<br /><br />下面用代码和运行结果来进行说明：<br /><pre name="code" class="java">public class ScoreSortTest {
	public final static String INDEX_STORE_PATH = "index";
	public static void main(String[] args) throws Exception {
		IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true);
		writer.setUseCompoundFile(false);
		
		Document doc1 = new Document();
		Document doc2 = new Document();
		Document doc3 = new Document();
		
		Field f1 = new Field("bookname","bc bc", Field.Store.YES, Field.Index.TOKENIZED);
		Field f2 = new Field("bookname","ab bc", Field.Store.YES, Field.Index.TOKENIZED);
		Field f3 = new Field("bookname","ab bc cd", Field.Store.YES, Field.Index.TOKENIZED);
		
		doc1.add(f1);
		doc2.add(f2);
		doc3.add(f3);
		
		writer.addDocument(doc1);
		writer.addDocument(doc2);
		writer.addDocument(doc3);
		
		writer.close();
		
		IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH);
		TermQuery q = new TermQuery(new Term("bookname", "bc"));
		q.setBoost(2f);
		Hits hits = searcher.search(q);
		for(int i=0; i&lt;hits.length();i++){
			Document doc = hits.doc(i);
			System.out.print(doc.get("bookname") + "\t\t");
			System.out.println(hits.score(i));
			System.out.println(searcher.explain(q, hits.id(i)));//
		}
	}
}</pre><br /><strong>运行结果：</strong><br /><div class="quote_title">引用</div><div class="quote_div">bc bc		0.629606<br />0.629606 = (MATCH) fieldWeight(bookname:bc in 0), product of:<br />  1.4142135 = tf(termFreq(bookname:bc)=2)<br />  0.71231794 = idf(docFreq=3, numDocs=3)<br />  0.625 = fieldNorm(field=bookname, doc=0)<br /><br />ab bc		0.4451987<br />0.4451987 = (MATCH) fieldWeight(bookname:bc in 1), product of:<br />  1.0 = tf(termFreq(bookname:bc)=1)<br />  0.71231794 = idf(docFreq=3, numDocs=3)<br />  0.625 = fieldNorm(field=bookname, doc=1)<br /><br />ab bc cd		0.35615897<br />0.35615897 = (MATCH) fieldWeight(bookname:bc in 2), product of:<br />  1.0 = tf(termFreq(bookname:bc)=1)<br />  0.71231794 = idf(docFreq=3, numDocs=3)<br />  0.5 = fieldNorm(field=bookname, doc=2)<br /></div><br />从结果中我们可以看到：<br />bc bc文档中bc出现了2次，tf为2的平方根，所以是1.4142135。而其他的两个文档出现了一次，所以是1.0<br />所有的三个文档的idf值都是一样的，是0.71231794<br />默认情况下，boost的值都是1.0，所以lengthNorm就是当前的fieldNorm的值。前两个文档的长度一致，为0.625，而排在最后的文档，因为长度要长一些，所以分值要低，为0.5<br /><br />现在对f2这个字段增加激励因子：f2.setBoost(2.0f);<br />运行结果变为：<br /><div class="quote_title">引用</div><div class="quote_div">ab bc		0.8903974<br />0.8903974 = (MATCH) fieldWeight(bookname:bc in 1), product of:<br />  1.0 = tf(termFreq(bookname:bc)=1)<br />  0.71231794 = idf(docFreq=3, numDocs=3)<br />  1.25 = fieldNorm(field=bookname, doc=1)</div><br />发现fieldNorm值有0.625变成了1.25，所以就是乘以了2.0<br /><br />接下来再对第二个文档增加激励因子：doc2.setBoost(2.0f);<br />运行结果变为：<br /><div class="quote_title">引用</div><div class="quote_div">ab bc		1.0<br />1.7807949 = (MATCH) fieldWeight(bookname:bc in 1), product of:<br />  1.0 = tf(termFreq(bookname:bc)=1)<br />  0.71231794 = idf(docFreq=3, numDocs=3)<br />  2.5 = fieldNorm(field=bookname, doc=1)</div><br />发现fieldNorm又乘以了2，所以说对于Document和Field的setBoost都会乘到一起。<br /><br />因为该文档的最终的score超过了1.0变成1.7807949，所以其他的两个文档的最终得分都要除以该值，<br />分别变成：<br /><div class="quote_title">引用</div><div class="quote_div">bc bc		0.35355335<br />ab bc cd		0.19999999</div><br /><br /><br />相信通过上面的解释，大家就可以形象得理解Lucene的打分机制，同时也知道如何来改变文档的得分。
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/181802#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>Fri, 11 Apr 2008 15:46:40 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/181802</link>
        <guid>http://grantbb.javaeye.com/blog/181802</guid>
      </item>
      <item>
        <title>Lucene搜索优化技巧 - 搜索篇</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/174600" style="color:red;">http://grantbb.javaeye.com/blog/174600</a>&nbsp;
          发表时间: 2008年03月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          搜索<br />    1、对于按创建时间的排序可以使用doc.id的方式<br />        new SortField(null, SortField.DOC, reverse)排序方式尽量使用INT类型的字段<br />        也就是按照写入索引的顺序排序<br />    2、对于时间字符串的排序可以转换成整数进行排序<br />    3、去掉不必要的parse 	<br />        使用TermQuery替换<br />    4、TermQuery和Term可以只保留一个实例<br />        createTerm(text)<br />    5、减少Doc到model的转换<br />        索引出来String到Date的转换多余而且费时<br />        直接使用Doc对象包装成JSONObject <br />    6、MultiFieldQueryParser改成自己用boolean查询重构<br />    7、减少请求参数的包装类<br />    8、搜索排序方法可以作为常量<br />        将sort参数变成int型，使用swich进行判断<br />    10、使用HitCollector类来适应不同情况下，Hits的大小<br />        新、旧接口<br />        相关搜索接口<br />    11、使用尽可能快的磁盘IO<br />    12、日志，先写文件，每天批量入库<br />    13、增量索引使用reopen<br />        新的reopen()方法只会加载那些变更过的索引片断，而不是重新加载完整的索引。<br />    14、setMergeFactor 在做实时索引的时候，可以设置的小一点<br />        这样就会及时索引进去
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/174600#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, 21 Mar 2008 18:50:23 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/174600</link>
        <guid>http://grantbb.javaeye.com/blog/174600</guid>
      </item>
      <item>
        <title>Lucene搜索优化技巧 - 索引篇</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/174597" style="color:red;">http://grantbb.javaeye.com/blog/174597</a>&nbsp;
          发表时间: 2008年03月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          索引<br />    1、t.termText()替换为new String(t.termBuffer(),0,t.termLength())<br />    2、StringReader 和TokenStream对象都需要close<br />    3、索引时Document只用一个、Field只用几个<br />        一个Document对象对应多个Field实例<br />        Field有新的setValue方法，动态改变属性<br />        不能只有一个Field实例<br />            例如：idField, bodyField<br />        必须等Document都到索引中之后，才可以重新设置值<br />    4、索引中Field的命名只使用2个字符表示 <br />    5、有些索引字段可以考虑使用0，1替代字符串，排序采用整数来排<br />    6、减少索引的存储字段，一般只存ID<br />    7、索引的时候只用一个IndexWriter对象<br />    8、3.1版本有个新的方法writer.ramSizeInBytes()<br />        根据RAM的使用情况，来决定是不需要刷新到磁盘。<br />        之前：setMaxBufferedDocs<br />    9、批量索引的时候，尽可能多使用一些内存，采用非复合的文件方式，完成后集中优化合并索引文件<br />        fsWriter.addIndexesNoOptimize<br />        fsWriter.setUseCompoundFile(false);<br />        需要注意不要超过系统的允许打开文件数<br />    10、重复使用单一的Token实例，在analyzer中。<br />    11、Turn off auto-commit if there are stored fields and term vectors <br />        设置autoCommit=false，直到writer close之后才会生效<br />        默认是true<br />    12、如果总是同时在多个分词的字段中查询，可以考虑将多个Field合并到一个Field中<br />    13、增加mergeFactor，但是不要太大<br />        反复调试获取经验值<br />    14、关闭一些实际上没用的功能（不要存储一些不必要的字段，尽量不要打开term vectors） <br />    15、使用更快的analyzer <br />    16、加快获得document数据的速度<br />        比如：从数据库、文件获取数据的速度<br />    17、索引的时候可以考虑使用多线程<br />        使用多线程addDocuments<br />        需要测试，然后确定线程数<br />    18、可以分开索引，然后合并<br />        并行索引机制
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/174597#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, 21 Mar 2008 18:47:53 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/174597</link>
        <guid>http://grantbb.javaeye.com/blog/174597</guid>
      </item>
      <item>
        <title>SVN Attempted to lock an already-locked dir</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/168885" style="color:red;">http://grantbb.javaeye.com/blog/168885</a>&nbsp;
          发表时间: 2008年03月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在eclipse里提交和更新文件是抱错。<br /><br />Attempted to lock an already-locked dir<br />svn: Working copy 'F:\workspace\WebFrame\WebRoot\attach\prodrelation' locked<br /><br />执行“清除”操作后，问题解决了。<br /><br />很多操作，例如中断提交，都会进入这种工作拷贝的锁定状态。
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/168885#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, 06 Mar 2008 21:58:11 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/168885</link>
        <guid>http://grantbb.javaeye.com/blog/168885</guid>
      </item>
      <item>
        <title>Lucene2.3.1发布了</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/165506" style="color:red;">http://grantbb.javaeye.com/blog/165506</a>&nbsp;
          发表时间: 2008年02月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          主要是修改了一些2.3.0版本的Bug，特别是当autoCommit=false的情况下以及多线程添加Document，有些字段打开了term-vector有些没有打都会对索引数据造成破坏<br /><br />autoCommit 选项是从2.2.0版本就添加了，默认是true，我对这个参数还不是很理解，都是用的默认值true。所以没有碰到问题。<br /><br />2.3.1版本没有包含任何新的功能，索引文件的格式也没有变化，完全兼容2.3.0版本。<br /><br />官方鼓励所有使用2.3.0版本的应用尽快升级到2.3.1版本。<br /><br /><br />Bug fixes<br />    <br /> 1. LUCENE-1168: Fixed corruption cases when autoCommit=false and<br />    documents have mixed term vectors (Suresh Guvvala via Mike<br />    McCandless).<br /><br /> 2. LUCENE-1171: Fixed some cases where OOM errors could cause<br />    deadlock in IndexWriter (Mike McCandless).<br /><br /> 3. LUCENE-1173: Fixed corruption case when autoCommit=false and bulk<br />    merging of stored fields is used (Yonik via Mike McCandless).<br /><br /> 4. LUCENE-1163: Fixed bug in CharArraySet.contains(char[] buffer, int<br />    offset, int len) that was ignoring offset and thus giving the<br />    wrong answer.  (Thomas Peuss via Mike McCandless)<br />	<br /> 5. LUCENE-1177: Fix rare case where IndexWriter.optimize might do too<br />    many merges at the end.  (Mike McCandless)<br />	<br /> 6. LUCENE-1176: Fix corruption case when documents with no term<br />    vector fields are added before documents with term vector fields.<br />    (Mike McCandless)<br />	<br /> 7. LUCENE-1179: Fixed assert statement that was incorrectly<br />    preventing Fields with empty-string field name from working.<br />    (Sergey Kabashnyuk via Mike McCandless)
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/165506#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>Wed, 27 Feb 2008 16:27:58 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/165506</link>
        <guid>http://grantbb.javaeye.com/blog/165506</guid>
      </item>
      <item>
        <title>AXIS开发的小问题</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/165406" style="color:red;">http://grantbb.javaeye.com/blog/165406</a>&nbsp;
          发表时间: 2008年02月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          AXIS<br />    问题<br />          少了一个activation.jar<br />          因为类的注释少了一个符号，导致无法编译.jws<br />    服务开发步骤<br />          开发服务代码<br />          编写部署描述<br />    客户端开发<br />          转到AXIS目录下的WEB-INF子目录。确保Tomcat服务已经处于启动状态，键入命令 ：<br />          Java -Djava.ext.dirs=lib org.apache.axis.wsdl.WSDL2Java http://localhost:8080/axis/Calculator.jws?wsdl<br />          上面这种模式类会比较多，但是调用会比较清楚<br />    WTP<br />          model类需要有默认的构造函数，否则会提示出错<br />          接口中有ArrayList的调用的情况  改成Object[]
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/165406#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>Wed, 27 Feb 2008 12:07:00 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/165406</link>
        <guid>http://grantbb.javaeye.com/blog/165406</guid>
      </item>
      <item>
        <title>Lucene2.2的新变化</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/158416" style="color:red;">http://grantbb.javaeye.com/blog/158416</a>&nbsp;
          发表时间: 2008年01月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          发现2.1里面的新变化很多都用到了，而且帮助很大。所以决定把2.2的新内容消化一下<br />1、在InderWriter的构造参数中增加了一个可选的boolean的参数autoCommit。默认是true，当设置成false的时候，索引的变化知道writer被close掉之后，才会提交变化。<br />还有一个可选的删除策略的参数，应该是用来控制删除索引后是否生效。<br /><br />2、很多public的方法都会抛出：AlreadyClosedException<br /><br />3、TokenStream里面增加了reset()方法，允许提供自定义的实现。<br /><br />未完待续，还有很多需要进一步消化。
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/158416#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>Tue, 22 Jan 2008 20:23:06 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/158416</link>
        <guid>http://grantbb.javaeye.com/blog/158416</guid>
      </item>
      <item>
        <title>Lucene2.1的新变化</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/158412" style="color:red;">http://grantbb.javaeye.com/blog/158412</a>&nbsp;
          发表时间: 2008年01月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1.9  到  2.0  的改动不是很多，主要是废弃了一些  API  ，  2.0  起了一个过渡的作用。<br /><br />2.1 是在 2.0 基础上做了很多的改进，提升了性能，修复了一些 Bug 等。<br /><br /> <br /><br />Lucene2.1 在索引的格式上做了一些改进，所以旧版本的 Lucene 是无法访问 2.1 版的索引文件。但是 2.1 版本的可以读写旧版本的索引文件。保持向下的兼容性。这点需要我们在使用时注意。<br /><br /> <br /><br />下面简单的列出一些新的特性：<br /><br />1.       's' 和 't' 从默认的 stopwords 中移掉了。但是依然还有 'a' 也可以会有同样的问题，所以分词需要针对自己的应用进行自定义。<br /><br />2.       更新了 StandardAnalyzer 中的针对 CJK 的 Unicode 代码范围。用处不大，因为我们中文需要自己开发分词。<br /><br />3.       允许在 QueryParser 的最前面使用通配符 (*, ?) ，之前是不允许的。这个比较有意义，可以实现一些模糊搜索。<br /><br />4.       QueryParser 默认使用 ConstantScoreRangeQuery 执行范围查询。增加了 useOldRangeQuery 属性允许在需要的情况下使用旧的 RangeQuery<br /><br />5.       对于 WildcardQuery ，如果一个 term 不包含任何的 ? 或者 * ，之前会抛出异常，现在会执行一个 TermQuery 。<br /><br />6.       去掉了 deprecated 的 doc.fields() 方法和 Enumeration<br /><br />7.       write lock 现在默认的位置是索引的目录，简单命名为 write.lock<br /><br />8.       新的 FieldSelector API ，相关的 IndexReader 和实现都发生了变化。新的 Fieldable 接口被用作字段的延迟加载上。<br /><br />9.       使用 MultiFieldQueryParser 的时候可以为不同的 field 指定不同的 boosts<br /><strong><br />10.   新的方法 IndexWriter.addIndexesNoOptimize() 在新添加一个新的 segments 的时候，只进行合并，不进行优化。</strong><br /><br />11.   QueryParser 允许在引号和短语中使用反斜线<br /><br /><strong>12.   增加了方法 RAMDirectory.sizeInBytes(), IndexWriter.ramSizeInBytes() 和 IndexWriter.flushRamSegments() ，允许应用程序控制索引时缓存文档对内存的使用，这些蛮有用的，可以用于监控索引的过程。</strong><br /><strong><br />13.   QueryParser 解析 *:* 为匹配所有的内容</strong><br /><br />14.   可以通过命令行在已经存在的索引文件中修改和删除 field<br /><br /><strong>15.   IndexWriter 增加了方法来高效得更新 documents 。增加 IndexWriter.flush() 方法将内存的内容刷新到文件系统。</strong><br />                                  大兵 2007-3-22
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/158412#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, 22 Jan 2008 20:08:33 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/158412</link>
        <guid>http://grantbb.javaeye.com/blog/158412</guid>
      </item>
      <item>
        <title>Tomcat5到Tomcat6的升级步骤</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/156180" style="color:red;">http://grantbb.javaeye.com/blog/156180</a>&nbsp;
          发表时间: 2008年01月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          整个升级的过程还是非常简单的。<br />只是NIO方面的配置有些不同。<br /><br />1、对应修改/bin/catalina.sh<br />   增加 JAVA_OPTS 的配置<br />2、修改/conf/server.xml中的Connector的配置<br />8080端口修改为：<br /><pre name="code" class="java">&lt;Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" connectionTimeout="30000" 
         acceptorThreadCount="2" redirectPort="8443" socket.directBuffer="false"/></pre><br /> <br />如果需要配置8009端口：保持跟tomcat5一样的配置<br /> <br />有些应用需要在默认的Host中配置Context，保持同样的配置，例如：<br /><pre name="code" class="java">&lt;Context docBase="/home/toodou/cas" path="/cas" reloadable="true"/></pre><br /> <br />有些应用如果还需要配置其他的虚拟主机，对应配置一下即可。
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/156180#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>Tue, 15 Jan 2008 18:04:32 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/156180</link>
        <guid>http://grantbb.javaeye.com/blog/156180</guid>
      </item>
      <item>
        <title>Tomcat5.0与6.0的性能比较</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/155126" style="color:red;">http://grantbb.javaeye.com/blog/155126</a>&nbsp;
          发表时间: 2008年01月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          并发量  LOAD    MEM     IO	   吞吐量 平均响应时间 偏离<br />TOMCAT5	20	3-4	10.6	52-60	874	1335	257<br />TOMCAT6	20	2.4	14.6	21	906	1305	205<br />NIO	20	2.4	12.3	21	855	1304	330<br /><br />TOMCAT5	40	4-5	19.2	66	908	2570	507<br />TOMCAT6	40	2.25	12.3	41	875	2622	618<br />NIO	40	2.5	16.7	42	895	2567	592<br />							<br />							<br />结论：							<br />	在同样的负载下，tomcat6比tomcat5的load要低很多，同时处理链接的能力确实增强了。						<br />	现在看起来NIO也没有体现出太多优势，可能是参数设置上还需要进一步研究。<br /><br />接下来准备放到产品环境跑一下看看了。
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/155126#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, 11 Jan 2008 16:42:53 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/155126</link>
        <guid>http://grantbb.javaeye.com/blog/155126</guid>
      </item>
      <item>
        <title>MySQL的类型</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/148163" style="color:red;">http://grantbb.javaeye.com/blog/148163</a>&nbsp;
          发表时间: 2007年12月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一、数字类型<br /><br />　　所谓的“数字类”，就是指 DECIMAL 和 NUMERIC，它们是同一种类型。它严格的说不是一种数字类型，因为他们实际上是将数字以字符串形式保存的;他的值的每一位 (包括小数点) 占一个字节的存储空间，因此这种类型耗费空间比较大。但是它的一个突出的优点是小数的位数固定，在运算中不会“失真”，所以比较适合用于“价格”、“金额”这样对精度要求不高但准确度要求非常高的字段。<br /><br />　　小数类，即浮点数类型，根据精度的不同，有 FLOAT 和 DOUBLE 两种。它们的优势是精确度，FLOAT 可以表示绝对值非常小、小到约 1.17E-38 (0.000...0117，小数点后面有 37 个零) 的小数，而 DOUBLE 更是可以表示绝对值小到约 2.22E-308 (0.000...0222，小数点后面有 307 个零) 的小数。FLOAT 类型和 DOUBLE 类型占用存储空间分别是 4 字节和 8 字节。如果需要用到小数的字段，精度要求不高的，当然用 FLOAT 了。可是说句实在话，我们“民用”的数据，哪有要求精度那么高的呢?这两种类型至今我没有用过――我还没有遇到适合于使用它们的事例。<br /><br />　　用的最多的，最值得精打细算的，是整数类型。从只占一个字节存储空间的 TINYINT 到占 8 个字节的 BIGINT，挑选一个“够用”并且占用存储空间最小的类型是设计数据库时应该考虑的。TINYINT、SMALLINT、MEDIUMINT、INT 和 BIGINT 占用存储空间分别为 1 字节、2 字节、3 字节、4 字节和 8 字节，就无符号的整数而言，这些类型能表示的最大整数分别为 255、65535、16777215、4294967295 和 18446744073709551615。如果用来保存用户的年龄 (举例来说，数据库中保存年龄是不可取的)，用 TINYINT 就够了;九城的《纵横》里，各项技能值，用 SMALLINT 也够了;如果要用作一个肯定不会超过 16000000 行的表的 AUTO_INCREMENT 的 IDENTIFY 字段，当然用 MEDIUMINT 不用 INT，试想，每行节约一个字节，16000000 行可以节约 10 兆多呢。<br /><br />　　二、日期时间类型<br /><br />　　日期和时间类型比较简单，无非是 DATE、TIME、DATETIME、TIMESTAMP 和 YEAR 等几个类型。只对日期敏感，而对时间没有要求的字段，就用 DATE 而不用 DATETIME 是不用说的了;单独使用时间的情况也时有发生――使用 TIME;但最多用到的还是用 DATETIME。在日期时间类型上没有什么文章可做，这里就不再详述。<br /><br />　　三、字符 (串) 类型<br /><br />　　不要以为字符类型就是 CHAR，CHAR 和 VARCHAR 的区别在于 CHAR 是固定长度，只要你定义一个字段是 CHAR(10)，那么不论你存储的数据是否达到了 10 个字节，它都要占去 10 个字节的空间;而 VARCHAR 则是可变长度的，如果一个字段可能的值是不固定长度的，我们只知道它不可能超过 10 个字符，把它定义为 VARCHAR(10) 是最合算的，VARCHAR 类型的占用空间是它的值的实际长度 +1。为什么要 +1 呢?这一个字节用于保存实际使用了多大的长度。从这个 +1 中也应该看到，如果一个字段，它的可能值最长是 10 个字符，而多数情况下也就是用到了 10 个字符时，用 VARCHAR 就不合算了：因为在多数情况下，实际占用空间是 11 个字节，比用 CHAR(10) 还多占用一个字节。<br /><br />　　举个例子，就是一个存储股票名称和代码的表，股票名称绝大部分是四个字的，即 8 个字节;股票代码，上海的是六位数字，深圳的是四位数字。这些都是固定长度的，股票名称当然要用 CHAR(8);股票代码虽然是不固定长度，但如果使用 VARCHAR(6)，一个深圳的股票代码实际占用空间是 5 个字节，而一个上海的股票代码要占用 7 个字节!考虑到上海的股票数目比深圳的多，那么用 VARCHAR(6) 就不如 CHAR(6) 合算了。<br /><br />　　虽然一个 CHAR 或 VARCHAR 的最大长度可以到 255，我认为大于 20 的 CHAR 是几乎用不到的――很少有大于 20 个字节长度的固定长度的东东吧?不是固定长度的就用 VARCHAR。大于 100 的 VARCHAR 也是几乎用不到的――比这更大的用 TEXT 就好了。TINYTEXT，最大长度为 255，占用空间也是实际长度 +1;TEXT，最大长度 65535，占用空间是实际长度 +2;MEDIUMTEXT，最大长度 16777215，占用空间是实际长度 +3;LONGTEXT，最大长度 4294967295，占用空间是实际长度 +4。为什么 +1、+2、+3、+4?你要是还不知道就该打 PP 了。这些可以用在论坛啊、新闻啊，什么的，用来保存文章的正文。根据实际情况的不同，选择从小到大的不同类型。<br /><br />　　四、枚举和集合类型<br /><br />　　枚举 (ENUM) 类型，最多可以定义 65535 种不同的字符串从中做出选择，只能并且必须选择其中一种，占用存储空间是一个或两个字节，由枚举值的数目决定;集合 (SET) 类型，最多可以有 64 个成员，可以选择其中的零个到不限定的多个，占用存储空间是一个到八个字节，由集合可能的成员数目决定。<br /><br />　　举个例子来说，在 SQLServer 中，你可以节约到用一个 BIT 类型来表示性别 (男/女)，但 MySQL 没有 BIT，用 TINTINT 吗?不，可以用 ENUM(男孩’,’女孩’)，只有两种选择，所以只需一个字节――跟 TINYINT 一样大，但却可以直接用字符串 ’男孩’ 和 ’女孩’ 来存取。
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/148163#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, 13 Dec 2007 19:00:22 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/148163</link>
        <guid>http://grantbb.javaeye.com/blog/148163</guid>
      </item>
      <item>
        <title>Java解ZIP压缩文件</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/147821" style="color:red;">http://grantbb.javaeye.com/blog/147821</a>&nbsp;
          发表时间: 2007年12月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">try {
// Open the ZIP file
String inFilename = "infile.zip";
ZipInputStream in = new ZipInputStream(new FileInputStream(inFilename));

// Get the first entry
ZipEntry entry = in.getNextEntry();

// Open the output file
String outFilename = "o";
OutputStream out = new FileOutputStream(outFilename);

// Transfer bytes from the ZIP file to the output file
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}

// Close the streams
out.close();
in.close();
} catch (IOException e) {
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/147821#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, 12 Dec 2007 15:25:10 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/147821</link>
        <guid>http://grantbb.javaeye.com/blog/147821</guid>
      </item>
      <item>
        <title>Java创建ZIP压缩文件</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/147819" style="color:red;">http://grantbb.javaeye.com/blog/147819</a>&nbsp;
          发表时间: 2007年12月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          追求简单实用的方法<br /><br /><pre name="code" class="java">// These are the files to include in the ZIP file
String[] filenames = new String[]{"filename1", "filename2"};

// Create a buffer for reading the files
byte[] buf = new byte[1024];

try {
// Create the ZIP file
String outFilename = "outfile.zip";
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));

// Compress the files
for (int i=0; i&lt;filenames.length; i++) {
FileInputStream in = new FileInputStream(filenames[i]);

// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(filenames[i]));

// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}

// Complete the entry
out.closeEntry();
in.close();
}

// Complete the ZIP file
out.close();
} catch (IOException e) {
}
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/147819#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>Wed, 12 Dec 2007 15:23:43 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/147819</link>
        <guid>http://grantbb.javaeye.com/blog/147819</guid>
      </item>
      <item>
        <title>用Spring邮件抽象层发送邮件</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/147762" style="color:red;">http://grantbb.javaeye.com/blog/147762</a>&nbsp;
          发表时间: 2007年12月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          18.1. Introduction<br />介绍<br />Spring provides a higher level of abstraction for sending electronic mail which shields the user from the specifics of underlying mailing system and is responsible for a low level resource handling on behalf of the client.<br /><br />Spring 支持一个更高层的抽象用来发送电子邮件，它隐藏底层邮件系统的细节并且代表客户端对低级别的控制 。<br /><br />18.2. Spring mail abstraction structure<br />Spring邮件抽象结构<br />The main package of Spring mail abstraction layer is org.springframework.mail package. It contains central interface for sending emails called MailSender and the value object which encapsulates properties of a simple mail such as from, to, cc, subject, text called SimpleMailMessage. This package also contains a hierarchy of checked exceptions which provide a higher level of abstraction over the lower level mail system exceptions with the root exception being MailException.Please refer to JavaDocs for more information on mail exception hierarchy.<br /><br />Sring邮件抽象层的主要包是：org.springframework.mail 包。它包含叫MailSender为发送邮件的核心接口和包含简单邮件属性例如from,to,cc,subject,text叫 SimpleMailMessage的值对象. 这个包也包含一个检查异常的层次，它支持一个更高级别的抽象超过低级别的邮件系统异常伴随根异常存在MailException. 请参考JavaDocs为更多的信息杂邮件异常层次。<br /><br />Spring also provides a sub-interface of MailSender for specialized JavaMail features such as MIME messages, namely org.springframework.mail.javamail.JavaMailSender It also provides a callback interface for preparation of JavaMail MIME messages, namely org.springframework.mail.javamail.MimeMessagePreparator<br /><br />Spring也支持一个MailSender的专用于JavaMail特征例如MIME消息子接口，命名为 org.springframework.javamail.JavaMailerSener。它也支持一个为JavaMail MIME信息的准备回调接口，命名为 org.springframework.mail.JavaMail.MimeMessagePreparator.<br /><br />MailSender:<br /><br />public interface MailSender {<br /><br />    /**<br />     * Send the given simple mail message.<br />     * @param simpleMessage message to send<br />     * @throws MailException in case of message, authentication, or send errors<br />     * 发送给定的简单邮件信息<br />     * @参数 simpleMessage  发送的信息<br />     * @throws MailException 假设信息，证明或发送错误<br />     */<br />    <br />    public void send(SimpleMailMessage simpleMessage) throws MailException;<br /><br />    /**<br />     * Send the given array of simple mail messages in batch.<br />     * @param simpleMessages messages to send<br />     * @throws MailException in case of message, authentication, or send errors<br />     */<br />    public void send(SimpleMailMessage[] simpleMessages) throws MailException;<br /><br />}<br /><br />JavaMailSender:<br /><br />public interface JavaMailSender extends MailSender {<br /><br />    /**<br />     * Create a new JavaMail MimeMessage for the underlying JavaMail Session<br />     * of this sender. Needs to be called to create MimeMessage instances<br />     * that can be prepared by the client and passed to send(MimeMessage).<br />     * @return the new MimeMessage instance<br />     * @see #send(MimeMessage)<br />     * @see #send(MimeMessage[])<br />     * 创建一个新的JavaMail MimeMessage 为潜在的JavaMail的发送者的会话.<br />     * 需要被调用来创建MimeMessage实例，它可以被客户准备并且被传递发送(MimeMessage).<br />     * @return 这个新的MimeMessage 实例<br />     * @see #send(Message)<br />     * @sess #send(MimeMessage[])<br />     */<br />    public MimeMessage createMimeMessage();<br /><br />    /**<br />     * Send the given JavaMail MIME message.<br />     * The message needs to have been created with createMimeMessage.<br />     * @param mimeMessage message to send<br />     * @throws MailException in case of message, authentication, or send errors<br />     * @see #createMimeMessage<br />     */<br />    public void send(MimeMessage mimeMessage) throws MailException;<br /><br />    /**<br />     * Send the given array of JavaMail MIME messages in batch.<br />     * The messages need to have been created with createMimeMessage.<br />     * @param mimeMessages messages to send<br />     * @throws MailException in case of message, authentication, or send errors<br />     * @see #createMimeMessage<br />     */<br />    public void send(MimeMessage[] mimeMessages) throws MailException;<br /><br />    /**<br />     * Send the JavaMail MIME message prepared by the given MimeMessagePreparator.<br />     * Alternative way to prepare MimeMessage instances, instead of createMimeMessage<br />     * and send(MimeMessage) calls. Takes care of proper exception conversion.<br />     * @param mimeMessagePreparator the preparator to use<br />     * @throws MailException in case of message, authentication, or send errors<br />     */<br />    public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException;<br /><br />    /**<br />     * Send the JavaMail MIME messages prepared by the given MimeMessagePreparators.<br />     * Alternative way to prepare MimeMessage instances, instead of createMimeMessage<br />     * and send(MimeMessage[]) calls. Takes care of proper exception conversion.<br />     * @param mimeMessagePreparators the preparator to use<br />     * @throws MailException in case of message, authentication, or send errors<br />     */<br />    public void send(MimeMessagePreparator[] mimeMessagePreparators) throws MailException;<br /><br />}<br />MimeMessagePreparator:<br /><br />public interface MimeMessagePreparator {<br /><br />    /**<br />     * Prepare the given new MimeMessage instance.<br />     * @param mimeMessage the message to prepare<br />     * @throws MessagingException passing any exceptions thrown by MimeMessage<br />     * methods through for automatic conversion to the MailException hierarchy<br />     */<br />    void prepare(MimeMessage mimeMessage) throws MessagingException;<br /><br />}<br /><br />18.3. Using Spring mail abstraction<br />使用Spring邮件抽象<br />Let’s assume there is a business interface called OrderManager<br />让我们假定这里有一个商业接口叫OrderManager<br /><br />public interface OrderManager {<br /><br />    void placeOrder(Order order);<br />   <br />}<br /><br />and there is a use case that says that an email message with order number would need to be generated and sent to a customer placing that order. So for this purpose we want to use MailSender and SimpleMailMessage<br />并且这里有一个有用案例，可以说一个伴随订单编号的邮件信息将需要被产生并且发送给一个客户处理这个订单。所以为这个目的我们想要使用MailSender和SimpleMailSender.<br /><br /><br />Please note that as usual, we work with interfaces in the business code and let Spring IoC container take care of wiring of all the collaborators for us.<br /><br />请注意照常，我们工作使用在商业代码中的接口并且让Spring Ioc 容器关心为我们的所有合作者。<br /><br />Here is the implementation of OrderManager<br />这里是OrderManager的实现:<br /><br />import org.springframework.mail.MailException;<br />import org.springframework.mail.MailSender;<br />import org.springframework.mail.SimpleMailMessage;<br /><br />public class OrderManagerImpl implements OrderManager {<br /><br />    private MailSender mailSender;<br />    private SimpleMailMessage message;<br /><br />    public void setMailSender(MailSender mailSender) {<br />        this.mailSender = mailSender;<br />    }<br /><br />    public void setMessage(SimpleMailMessage message) {<br />        this.message = message;<br />    }<br /><br />    public void placeOrder(Order order) {<br /><br />        //... * Do the business calculations....<br />        //... * Call the collaborators to persist the order<br /><br />        //Create a thread safe "sandbox" of the message<br />        SimpleMailMessage msg = new SimpleMailMessage(this.message);<br />        msg.setTo(order.getCustomer().getEmailAddress());<br />        msg.setText(<br />            "Dear "<br />                + order.getCustomer().getFirstName()<br />                + order.getCustomer().getLastName()<br />                + ", thank you for placing order. Your order number is "<br />                + order.getOrderNumber());<br />        try{<br />            mailSender.send(msg);<br />        }<br />        catch(MailException ex) {<br />            //log it and go on<br />            System.err.println(ex.getMessage());           <br />        }<br />    }<br />}<br />Here is what the bean definitions for the code above would look like:<br />这里是这个为这个以上代码bean定义类似：<br /><br />&lt;bean id="mailSender"<br />      class="org.springframework.mail.javamail.JavaMailSenderImpl"><br />    &lt;property name="host">&lt;value>mail.mycompany.com&lt;/value>&lt;/property><br />&lt;/bean><br /><br />&lt;bean id="mailMessage"<br />      class="org.springframework.mail.SimpleMailMessage"><br />    &lt;property name="from">&lt;value>customerservice@mycompany.com&lt;/value>&lt;/property><br />    &lt;property name="subject">&lt;value>Your order&lt;/value>&lt;/property><br />&lt;/bean><br /><br />&lt;bean id="orderManager"<br />      class="com.mycompany.businessapp.support.OrderManagerImpl"><br />    &lt;property name="mailSender">&lt;ref bean="mailSender"/>&lt;/property><br />    &lt;property name="message">&lt;ref bean="mailMessage"/>&lt;/property><br />&lt;/bean><br />Here is the implementation of OrderManager using MimeMessagePreparator callback interface. Please note that the mailSender property is of type JavaMailSender in this case in order to be able to use JavaMail MimeMessage:<br /><br />import javax.mail.Message;<br />import javax.mail.MessagingException;<br />import javax.mail.internet.InternetAddress;<br />import javax.mail.internet.MimeMessage;<br /><br />import javax.mail.internet.MimeMessage;<br />import org.springframework.mail.MailException;<br />import org.springframework.mail.javamail.JavaMailSender;<br />import org.springframework.mail.javamail.MimeMessagePreparator;<br /><br />public class OrderManagerImpl implements OrderManager {<br />    private JavaMailSender mailSender;<br />   <br />    public void setMailSender(JavaMailSender mailSender) {<br />        this.mailSender = mailSender;<br />    }<br /><br />    public void placeOrder(final Order order) {<br /><br />        //... * Do the business calculations....<br />        //... * Call the collaborators to persist the order<br />       <br />       <br />        MimeMessagePreparator preparator = new MimeMessagePreparator() {<br />            public void prepare(MimeMessage mimeMessage) throws MessagingException {<br />                mimeMessage.setRecipient(Message.RecipientType.TO,<br />                        new InternetAddress(order.getCustomer().getEmailAddress()));<br />                mimeMessage.setFrom(new InternetAddress("mail@mycompany.com"));<br />                mimeMessage.setText(<br />                    "Dear "<br />                        + order.getCustomer().getFirstName()<br />                        + order.getCustomer().getLastName()<br />                        + ", thank you for placing order. Your order number is "<br />                        + order.getOrderNumber());<br />            }<br />        };<br />        try{<br />            mailSender.send(preparator);<br />        }<br />        catch(MailException ex) {<br />            //log it and go on<br />            System.err.println(ex.getMessage());           <br />        }<br />    }<br />}<br />If you want to use JavaMail MimeMessage to the full power, the MimeMessagePreparator is available at your fingertips.<br />如果你想使用JavaMail  MimeMessage来使得足够强大，MimeMessagePreparator 是可以利用的。<br /><br />Please note that the mail code is a crosscutting（横切的） concern（关注）  and is a perfect candidate（候选） for refactoring into a custom Spring AOP advice, which then could easily be applied to OrderManager target. Please see the AOP chapter.<br /><br /><br />18.3.1. Pluggable MailSender implementations<br />Spring comes with two MailSender implementations out of the box - the JavaMail implementation and the implementation on top of Jason Hunter’s MailMessage class that’s included in http://servlets.com/cos (com.oreilly.servlet). Please refer to JavaDocs for more information.<br /><br />18.4. Using the JavaMail MimeMessageHelper<br />One of the components that comes in pretty handy when dealing with JavaMail messages is the org.springframework.mail.javamail.MimeMessageHelper. It prevents you from having to use the nasty APIs the the javax.mail.internet classes. A couple of possible scenarios:<br /><br />18.4.1. Creating a simple MimeMessage and sending it<br />Using the MimeMessageHelper it’s pretty easy to setup and send a MimeMessage:<br /><br />// of course you would setup the mail sender using<br />// DI in any real-world cases<br />JavaMailSenderImpl sender = new JavaMailSenderImpl();<br />sender.setHost("mail.host.com");<br /><br />MimeMessage message = sender.createMimeMesage();<br />MimeMessageHelper helper = new MimeMessageHelper(message);<br />helper.setTo("test@host.com");<br />helper.setText("Thank you for ordering!");<br /><br />sender.send(message);<br /><br />18.4.2. Sending attachments and inline resources<br />Email allow for attachments, but also for inline resources in multipart messages. Inline resources could for example be images or stylesheet you want to use in your message, but don’t want displayed as attachment. The following shows you how to use the MimeMessageHelper to send an email along with an inline image.<br /><br />JavaMailSenderImpl sender = new JavaMailSenderImpl();<br />sender.setHost("mail.host.com");<br /><br />MimeMessage message = sender.createMimeMesage();<br /><br />// use the true flag to indicate you need a multipart message<br />MimeMessageHelper helper = new MimeMessageHelper(message, true);<br />helper.setTo("test@host.com");<br /><br />// use the true flag to indicate the text included is HTML<br />helper.setText(<br />  "&lt;html>&lt;body>&lt;img src=’cid:identifier1234’>&lt;/body>&lt;/html>"<br />  true);<br /><br />// let’s include the infamous windows Sample file (this time copied to c:/)<br />FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg"));<br />helper.addInline("identifier1234", res);<br /><br />// if you would need to include the file as an attachment, use<br />// addAttachment() methods on the MimeMessageHelper<br /><br />sender.send(message);<br />   <br />Inline resources are added to the mime message using the Content-ID specified as you’ve seen just now (identifier1234 in this case). The order in which you’re adding the text and the resource are VERY important. First add the text and after that the resources. If you’re doing it the other way around, it won’t work!
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/147762#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>Wed, 12 Dec 2007 12:12:14 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/147762</link>
        <guid>http://grantbb.javaeye.com/blog/147762</guid>
      </item>
      <item>
        <title>尝试GlassFish V2</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/140466" style="color:red;">http://grantbb.javaeye.com/blog/140466</a>&nbsp;
          发表时间: 2007年11月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p style="margin: 0in; font-family: SimSun; font-size: 10pt;">The GlassFish community has delivered the world's fastest open source application server</p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><a href="http://www.spec.org/jAppServer2004/results/res2007q3/jAppServer2004-20070619-00069.txt">SPECjAppServer 2004</a> results for GlassFish v2 running on Sun Fire T2000</p>
<br />
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">GlassFish号称最快的应用服务器，这点还是非常吸引人的，不知道时不时在所有的机器和操作系统上都是最快的？</p>
<br />
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">&nbsp;</p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">看了几篇文章，已经可以简单的使用了。安装是通过jar文件进行的，然后通过ant进行安装。</p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">之后，我又在Eclipse中添加了GlassFish服务器的插件，然后就可以在Eclipse中使用和开发了。</p>
<br />
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">接下来主要就是抽个时间在服务器上进行一下服务器的性能测试。</p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">&nbsp;</p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">参考：<br />
</p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;">  </p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3"><a href="http://blog.csdn.net/huangjianchang/archive/2006/10/11/1329950.aspx">与大家分享&mdash;&mdash;JavaEE5与Glassfish应用服务器</a></font></p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3">&nbsp;</font></p>
<p style="margin: 0in; font-weight: bold; font-family: SimSun; font-size: 20pt;"><font size="3">GlassFish--开源的Java EE应用服务器</font></p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3"><a href="http://www.china-pub.com/computers/common/info.asp?id=36937">http://www.china-pub.com/computers/common/info.asp?id=36937</a></font></p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3">&nbsp;</font></p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3"><a href="http://blog.csdn.net/easyskys/archive/2007/08/24/1758082.aspx"><span lang="zh-CN">Glassfish介绍</span></a><span lang="en-US">&nbsp;</span></font></p>
<p lang="en-US" style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3">&nbsp;</font></p>
<p style="margin: 0in; font-weight: bold; font-family: SimSun; font-size: 20pt;"><font size="3">什么是GlassFish v2真正Cool的地方</font></p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3"><a href="http://www.yeeyan.com/articles/view/2930/2053">http://www.yeeyan.com/articles/view/2930/2053</a></font></p>
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><font size="3">&nbsp;</font></p>
<br />
<p style="margin: 0in; font-family: SimSun; font-size: 10pt;"><br />
</p>
          <br/>
          <span style="color:red;">
            <a href="http://grantbb.javaeye.com/blog/140466#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>Wed, 14 Nov 2007 12:40:40 +0800</pubDate>
        <link>http://grantbb.javaeye.com/blog/140466</link>
        <guid>http://grantbb.javaeye.com/blog/140466</guid>
      </item>
      <item>
        <title>Sun2007科技日归来</title>
        <author>grantbb</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://grantbb.javaeye.com">grantbb</a>&nbsp;
          链接：<a href="http://grantbb.javaeye.com/blog/134954" style="color:red;">http://grantbb.javaeye.com/blog/134954</a>&nbsp;
          发表时间: 2007年10月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          感觉今年讲的内容是2006年的延续和深入，2006是很多的新概念诞生，包括JavaEE5、GlashFish、JPA、JavaSE5.0、注解，而今年才是真正的推广，之后大家开始陆续使用，一个新的技术推广确实是需要个3、5年的。对我来说比较有用的就是并发变成和JPA了。明天的topic不是很感兴趣，公司还有事情，所以明天就不去了，希望能够把大会的主要内容全部放到网上。就像美国的JavaOne一样。<br />
<br />
罗列一下听到的词汇和要点：<br />
<p><a href="http://gceclub.sun.com.cn/java_one_online/2007_ct.htm" target="_blank">http://gceclub.sun.com.cn/java_one_online/2007_ct.htm</a>  </p>
<p>concurrentAPI  </p>
<ul>
    <li>老的API不宜用，容易出错  </li>
    <li>Callable vs Runnable  </li>
    <li>Atomic  </li>
    <li>ReadWriteLock  </li>
    <li>document 注解 </li>
</ul>
<p>JPA  </p>
<ul>
    <li>JavaSE可用  </li>
    <li>实体  </li>
    <li>操作  </li>
    <li>关系  </li>
    <li>继承  </li>
    <li>检索语言  </li>
    <li>java&lt;-&gt;db_table &nbsp;  </li>
    <li>适用于字段多，表多的项目？ </li>
</ul>
<p>GlassFish  </p>
<ul>
    <li>启动快，几百毫秒  </li>
    <li>支持群集  </li>
    <li>复制策略  </li>
    <li>支持中文  </li>
    <li>Grizily
    <ul>
        <li>non-blocking  </li>
        <li>commet </li>
    </ul>
    </li>
</ul>
<p>JavaDB <br />
</p>
<p>JavaFX  </p>
<ul>
    <li>缺少工具  </li>
    <li>缺少应用场景  </li>
    <li>java 2d  </li>
    <li>jsp226  </li>
    <li>SVG </li>
</ul>
<p>Jmaki  </p>
<ul>
    <li>mashup  </li>
    <li>ajax component </li>
</ul>
<p>Netbean Profiler  </p>
<ul>
    <li>线程  </li>
    <li>内存  </li>
    <li>generation
    <ul>
        <li>gb收集的次数
        <ul>
            <li>old  </li>
            <li>young </li>
        </ul>
 