<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>myreligion</title>
    <description></description>
    <link>http://myreligion.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>The Mysql tool I’ve been waiting for years. zt</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/175933" style="color:red;">http://myreligion.javaeye.com/blog/175933</a>&nbsp;
          发表时间: 2008年03月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          I've just been pointed to the nice tool which I was waiting for years to see. It is fincore - little perl script which allows you to see what pages of file are cached in OS memory. This is really cool.<br /><br /><br />When it comes to MySQL it is very useful with MyISAM tables which has their data file cached by OS cache only so you do not have any good information from MySQL side on what data is cached. You can also use it with Innodb to see how much memory are you wasting with double buffering by not using of O_DIRECT.<br /><br />Besides general clues such as 50% of my file is cached you should watch for dynamics - for example check it during backup process and compare it due to normal load - this can give you a clue if slow down happens because of extra IO pressure or just because pages were washed out. You can also check how pages are cached. For example every second page cached may be helpful for point queries but does not save a lot of IO for doing table scans. <br /><br />One thing I'm still missing is looking it from another side - so I have say 10GB of OS cache used on the server but how can I tell what is using it ? This look from another side would help me dramatically to find out what is causing cache pressure and what needs to be worked on. Scanning all files on filesystem and checking which are cached obviously does not work.<br /><br />The fincore looks more like proof of concept tool - it is a bit simplistic, however being written in Perl it is easily hackable - if you want to make it to print percentage of file cached or "graph" showing how cached pages are distributed among file is very easy.<br /><br />The great thing about this tool it is very fast and it does not disturbs OS file cache by using mincore function to get pages which are currently in cache. <br /><br />This function is actually the real meat here - the tool is simplistic but it shows how to use the function so you can write real stuff. For example using this tool MySQL can easily add amount of cached data per table for MyISAM and Archive tables to INFORMATION_SCHEMA (or other system tables) which would be really cool Of course than one would need to implement cache content tracking for storage engines which cache everything in their own cache memory - Innodb, Falcon, Maria. <br /><br />Having information about how large portion of table is cached would allow optimizer to take much smarter decisions in many cases.<br /><br />Lets now see some examples:<br /><br /><div class="quote_title">引用</div><div class="quote_div">PLAIN TEXTSQL: <br />[root@DB01 mysql]# du -h ib_log*<br />257M    ib_logfile0<br />257M    ib_logfile1<br />[root@DB01 mysql]# perl /tmp/fincore --justsummarize ib_logfile0 ib_logfile1<br />page size: 4096 bytes<br />24141 pages, 94.3 Mbytes IN core FOR 2 files; 12070.50 pages, 47.2 Mbytes per file.<br />[root@DB01 mysql]# perl /tmp/fincore --justsummarize ib_logfile0<br />page size: 4096 bytes<br />1 page, 4.0 kbytes IN core FOR 1 file; 1.00 page, 4.0 kbytes per file.<br />[root@DB01 mysql]# perl /tmp/fincore --justsummarize ib_logfile1<br />page size: 4096 bytes<br />24169 pages, 94.4 Mbytes IN core FOR 1 file; 24169.00 pages, 94.4 Mbytes per file. </div><br /><br />So we can see one of Innodb log files is practically uncached while other has about 1/3rd cached - this makes sense, perhaps second log file is being written now and there is a "tail" of pages which just were not removed from the cache yet. As Innodb does not read logfile unless in recovery these are waste and Innodb could use fadvice to give instruction to kernel not to cache these as long as it can't perform direct IO to log files on Linux because it is not aligned.<br /><br /><div class="quote_title">引用</div><div class="quote_div">PLAIN TEXTSQL: <br />[root@DB01 mysql]# du -h ibdata*<br />246G    ibdata1<br />[root@DB01 mysql]# perl /tmp/fincore --justsummarize ibdata1<br />page size: 4096 bytes<br />0 pages, 0.0  bytes IN core FOR 1 file; 0.00 pages, 0.0  bytes per file. </div><br /><br />Out of 250GB innodb data file none of pages are in cache - this is because this instance is using O_DIRECT flag to bypass data buffering and we can well see it works.<br /><br />Lets now see stats for MyISAM tables:<br /><br /><div class="quote_title">引用</div><div class="quote_div">PLAIN TEXTSQL: <br />[root@DB01 logs]# du -h performance_log_080318.MYD<br />1.1G    performance_log_080318.MYD<br />[root@DB01 logs]# perl /tmp/fincore --justsummarize performance_log_080318.MYD<br />page size: 4096 bytes<br />497 pages, 1.9 Mbytes IN core FOR 1 file; 497.00 pages, 1.9 Mbytes per file.<br /> <br />[root@DB01 logs]# du -h performance_log_080319.MYD<br />229M    performance_log_080319.MYD<br />[root@DB01 logs]# perl /tmp/fincore --justsummarize performance_log_080319.MYD<br />page size: 4096 bytes<br />28415 pages, 111.0 Mbytes IN core FOR 1 file; 28415.00 pages, 111.0 Mbytes per file.<br />[root@DB01 logs]# </div><br /><br />The performance log for yesterday is almost out of cache. It is about 0:50 by server clock this is why we still can see some pages remaining. Today log file is 50% in cache. Knowing access pattern to the file you can draw some conclusions about how much IO pressure we have on this server.<br /><br />P.S If you would hack this tool or know any similar tools please let me know.
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/175933#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, 25 Mar 2008 17:47:34 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/175933</link>
        <guid>http://myreligion.javaeye.com/blog/175933</guid>
      </item>
      <item>
        <title>搞个力场防御系统来解决台湾吧</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/174888" style="color:red;">http://myreligion.javaeye.com/blog/174888</a>&nbsp;
          发表时间: 2008年03月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          看着中国的破武器实在让人着急，现在台湾那么危机，要是美国真杀过来，除了核武器，中国还真不见得真打的过人家。就算和台湾打，沿海也必不可少的会遭受巨大破坏和损失，都是白花花的银子和无差别的人类劳动，看着真让人心态啊。<br /><br />  在科幻电影里面，经常可以看到飞船都有防御罩，在stargate里面甚至这玩艺都能保护一个星球，也就是传说中的力场防御系统--采用力场屏蔽，阻断与拦截所有攻击：），比美国的TMD强多了，不怕饱和攻击。什么攻击都不怕！如果中国能造出来，在沿海部署一个，笼罩全国，那就无敌了。不过这个东西现在还没有人修出来，也就没有成熟的技术与经验；既然都是瞎猜，偶给点自己的设想，看看合不合适：）<br /> <br />  要修这个东西，偶觉得有2个办法。<br /><br />第一：超强电磁场<br /><br />  一般有威胁性的武器，都是一些精确制导武器，尤其对于美国，大部分武器都是精确制导的，所以武器内部肯定都是一堆堆的电路板。其实我们搞定了这些电路板，也就完成了有效拦截；当这些电路板被破坏，或者被部分破坏，武器基本上也就失效了（最少失去了预期的作战效果）。<br />  基于这个思路，我们只要在一定范围内，例如全国，或者沿海岸线产生一个强大的电磁层，类似于 电离层，当然比电离层厚度小很多，不过磁场强度大很多。在敌方武器（如导弹，飞机，XXX）通过时，其实就是在做切割磁力线的运动，武器上的电路板就按照中学的知识产生电流，如果磁场强度很大，武器内部的电路板上将会产生很大的电流；当然武器运动速度越快产生的电流也就越大，对于美国吹嘘的XX倍音速的东西再好不过了。我们知道，这些电路板都是敏感元器件，有一定的电流肯定全部都烧掉了，电路板一烧掉，武器系统也就报废了。也就可以拦截武器了：） 很先进吧~~~<br /><br />第二：反物质防护<br /><br />  这个应该会更加先进。不过要求是在飞行器上装备，也就是太空飞船上，赫赫。我们通过某种办法产生一些反物质，然后用磁场将其环绕于飞行器周围（当然要求将反物质存在的轨道先弄成真空，不能有正物质）。对于陆地区域防护应该也可以就是技术复杂点，保证反物质不碰到普通物质即可。这样，当有武器进攻时，不管是导弹，子弹，还是激光，粒子炮啥啥啥的，在到达飞行器之前必然要经过反物质，而通过时物质就会产生湮灭，武器会有部分被湮灭掉（估计很少很少），其他部分被湮灭产生的巨大能量蒸发掉，或者弹开（猜测的，应该会类似于坦克的主动防御的爆炸装甲），恩，无论什么武器进攻就可以抵挡，赫赫，标准的科幻技术实现效果，那就彻底无敌啦：）<br /><br />哎呀，等待着国家赶快实现啊，好把台湾和一些帝国主义帮凶都灭了！
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/174888#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>Sat, 22 Mar 2008 20:44:40 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/174888</link>
        <guid>http://myreligion.javaeye.com/blog/174888</guid>
      </item>
      <item>
        <title>对podcast的分析与定位--web2.5</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/170479" style="color:red;">http://myreligion.javaeye.com/blog/170479</a>&nbsp;
          发表时间: 2008年03月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;&nbsp;</p><p>&nbsp; cctv podcast虽然起步较早，不过现在无论在流媒体技术，展现，以及概念上都已经显得比较落后。央视podcast的主要内容来自编辑部门的电视节目，以及部分网友上传的电影和歌曲，原创作品不多；其他网站也大同小异，鉴于podcast制作比写blog复杂很多，大面积复制传播形成主流方式，像博客一样所有都自己动手弄自己的是一种不可能达到的状态。 </p><p>&nbsp;</p><p>&nbsp; 所以，从某种意义上说，podcast并不是一种以个人为中心的类型，和blog没有可比性。podcast的发展概念应该超越blog，在blog和 wiki之间。blog的理念是自己为中心，自己写自己的文章，展示自己的文章，图片等等。wiki的理念在于共创，通过集体的力量完成某一件事情，而这个事情完成以后并不归属于自己，所以可以推断wiki是一种更加高层次网民素质的体现，因为wiki体现的是一种奉献精神，而高于blog的个人中心精神。</p><p>&nbsp;</p><p>&nbsp; podcast，由于内容主要来源与复制传播，而并非原创；所以按照发布者进行组织是一种不妥当的选择，比较合适的组织方式应该是按照创作者。按照视频原始创作者进行组织，发布者通过贡献自己手中的视频来完成对某一主题，某一人视频的汇集，从而为普通的视频观看着提供某一方面更多更加准确全面的视频资料，提供观看者的体验程度。所以podcast的视频组织方式在理想状态下，应该按照wikipedia的方式进行处理；不过和wiki不同，podcast 发布者自身也可以创建视频，所以wiki标准的固定词条在此处不适用，podcast同时拥有者wiki概念上需要大家一起贡献来汇总的公共视频，也有个人自己录制的原创内容，个人的概念不可以被忽略。</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp; 按照上面的分析，如果对互联网划带，应该是：web1.0 -&gt; 以blog为代表的个人中心内容 web2.0 --&gt; podcast应该体现出的个人与贡献内容的混合 web2.5 -&gt; 以社会为中心，个人齐心贡献的内容模式，如wiki web3.0.&nbsp;&nbsp;&nbsp;&nbsp; </p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp; 明确了概念，podcast隶属于web2.5系统，所以相对于目前主流的个人为中心表现形式，它应该更多表现出其应有的共有奉献型资源的特性。podcast的组织结构应该满足：</p><ol><li>按照作品的原创者进行组织。（按导演）</li><li>按照作品的演出者进行组织。（按表演者）</li><li>按照发布者进行组织。（按照作品上传发布者）</li><li>按照视频归属事件进行组织。（按反应的事件）</li></ol><p>&nbsp; 视频贡献者：根据某些调查，互联网内容的贡献者一般年龄层次较高，心态较高。而对于视频，由于其特殊性，一般贡献者比较熟悉计算机，网络等新鲜技术，心理年龄一般应在25---40之间，其中对于奉献型组织的支持者一般应该在30以上。对于发布者发布的流程，应该更加体现简洁性与流程性，提高对这一特定群体的满意程度。</p><p>&nbsp;</p><p>&nbsp; 视频消费者：视频消费者应该可以当作一帮懒惰的人来考虑，他们期待着更少的操作，更少的页面转换，更大的视频窗口，更高的质量以及更好的视频流畅程度；对于他们来说可以理解为希望打开网站以后自己想要的东西都有了，一个个的为他们播放，他们自己则几乎什么都不需要做。为了满足他们的需要，在内容组织方式上提出了更高的要求，这个我们在上面已经提出了，同时视频还要有较强的推荐功能，通过分析当前用户的历史习惯或者他们选择的偏好，进行相关视频的推荐。而播放器也需要有更多的操作选项，提供更好的体验。</p><p>&nbsp;&nbsp; 播放器需求：</p><ol><li>可以支持IE6, IE7和firefox</li><li>拥有普通的屏幕功能和全屏功能</li><li>媒体播放开始，暂停，停止功能，音量调节功能等。</li><li>播放列表功能</li><li>可以在媒体播放的片头，片尾，甚至片中任意位置插入其他视频。（放广告，紧急通知新闻啥的）</li><li>提供两个文本层，一个固定文本层，一个活动文本层，播放器可以与服务器交互，让服务器控制着文本层文字内容的播放。（留作放广告，字幕，介绍，媒体的最新评论，最热门评论什么的）</li><li>播放器可以方便的增加链接，如为当前播放媒体的评分功能，显示当前媒体评分等。 </li></ol><br /><br /><p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/170479#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 Mar 2008 11:47:01 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/170479</link>
        <guid>http://myreligion.javaeye.com/blog/170479</guid>
      </item>
      <item>
        <title>用android开发个 照相秒表 如何？</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/151216" style="color:red;">http://myreligion.javaeye.com/blog/151216</a>&nbsp;
          发表时间: 2007年12月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;<br />
&nbsp;给想参加google android比赛的同学提个醒：技术总是服务于需求的，如果真的去参加比赛，项目创新肯定是要重于技术细节的。全世界那么多高手，指望在技术能力进入获奖区是非常困难的，建议大家更加专注于项目计划上。<br />
<br />
&nbsp;偶给提个项目，呵呵，就是改造现有手机系统上常有的功能&ldquo;秒表&rdquo;。秒表功能起源已经非常早了，不过可能就是因为起源太早，后续就人管了，包括摄像机普及的时候也没人管了:( 。如果能够将手机牌照功能融合到秒表中，肯定会是一个很不错的功能，尤其是在例如运动会比赛，体育课计算成绩上。<br />
<br />
&nbsp;大概的流程如下： 启动秒表，界面进入拍照模式，并在照片上面倒计时，当测量的人通过终点线时，按下秒表，程序记下时间并自动拍一张照片，继续下一个计时。等到所有人通过以后，得到的结果就不仅仅是一组多少秒的数据，而是一组图片+时间；这样一方面可以避免人太多时，计时者压根记不清谁的时间对谁（好比体育课上），一方面还可以根据照片情况调整按秒的时间误差。个人还是很实用的，也很有趣，而且利用现有的拍照功能，手机厂商的附加硬件成本也不高，手机还有特点。<br />
<br />
&nbsp;这个东西如果真的弄出来并大量发行，估计奥运会上就会有很多观众拿着手机在那儿当裁判玩。<br />
<br />
&nbsp; 如何？<br />
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/151216#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, 27 Dec 2007 13:47:40 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/151216</link>
        <guid>http://myreligion.javaeye.com/blog/151216</guid>
      </item>
      <item>
        <title>MySQL Select and Sort Status Variables</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/149178" style="color:red;">http://myreligion.javaeye.com/blog/149178</a>&nbsp;
          发表时间: 2007年12月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h2>MySQL Select and Sort Status Variables</h2>
MySQL Select and Sort Status Variables<br />
MySQL SHOW STATUS; and <a href="http://hackmysql.com/mysqlreport">mysqlreport</a> using the -sas command line    option show nine status variables which are counters for various types of SELECT statements MySQL has executed    and rows MySQL has sorted:<br />
<ol>
    <li>Select_scan</li>
    <li>Select_range</li>
    <li>Select_full_join</li>
    <li>Select_range_check</li>
    <li>Select_full_range_join</li>
    <li>Sort_scan</li>
    <li>Sort_range</li>
    <li>Sort_merge_passes</li>
    <li>Sort_rows</li>
</ol>
In particular, Select_scan and Select_range apply to either single table queries or the first table    in the join plan for a multiple table query. Select_full_join, Select_range_check, and Select_full_range_join    apply to the second and subsequent tables in the join plan for a multiple table query. The Sort variables    apply to any queries that sort rows. The distinction between where the variables apply is explained first,    which will help clarify the subsequent explanation of each variable.<br />
<br />
Beginning with mysqlreport v1.3 the variables are listed in the same order as above. This document will make    references to mysqlreport, although the same data can be obtained from the SHOW STATUS; command and some basic math.    <br />
<br />
<h2>The Distinction Between Where the Variables Apply</h2>
An over-simplified but sufficient way to classify all queries are those that select only one table and those    that select multiple tables. Regarding the nine Select and Sort variables, single and multiple table queries    have one thing in common: The first table. In a single table query the first table is the only table.    In a multiple table query the first table listed, the top-most row, in the output from EXPLAIN is the first    table. Select_scan and Select_range only apply to the first table.<br />
<br />
For multiple table queries Select_full_join, Select_range_check, and Select_full_range_join only apply to    the second and subsequent tables (second and subsequent rows) listed in the output from EXPLAIN.<br />
<br />
Sort_scan, Sort_range, Sort_merge_passes, and Sort_rows apply to any query that uses ORDER BY or    GROUP BY, regardless of how many tables.<br />
<br />
For example:
<pre>   mysql&gt; EXPLAIN SELECT * FROM tbl2, tbl1 WHERE tbl1.col1 = tbl2.col2 ORDER BY tbl1.col2;<br />   +-------------+-------+------+---------------+------+---------+------+------+------------------------+<br />   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                  |<br />   +-------------+-------+------+---------------+------+---------+------+------+------------------------+<br />   | SIMPLE      | tbl2  | ALL  | NULL          | NULL | NULL    | NULL |   18 | ..temporary;.. filesort|<br />   | SIMPLE      | tbl1  | ALL  | NULL          | NULL | NULL    | NULL |   27 | Using where            |<br />   +-------------+-------+------+---------------+------+---------+------+------+------------------------|<br />   </pre>
In the above join plan, tbl2 is the first table and tbl1 is the second table. This query will also effect some    of the Sort variables because it uses ORDER BY. Although both tables cause a table scan, tbl2 will apply to    Select_scan but tbl1 will apply to Select_full_join. In short, the nine Select and Sort status variables apply    where:<br />
<ol>
    <li>First table or only table: Select_scan and Select_range</li>
    <li>Second and subsequent tables: Select_full_join, Select_range_check, and Select_full_range_join</li>
    <li>Any query that uses ORDER BY or GROUP BY: Sort_scan, Sort_range, Sort_merge_passes, and Sort_rows</li>
</ol>
<br />
<h2>Select_scan</h2>
Select_scan refers to a table that is completely read in sequence from the hard drive. For such tables EXPLAIN    lists &quot;ALL&quot; in the &quot;type&quot; column. As we all know table scans are not desirable because they're slow (because    hard drives are slow). However, table scans are prevalent. It's not uncommon to see a server where 50% of all    SELECT queries are Select_scan. The fundamental reason why a SELECT results in a table scan is because no index    on the table can satisfied the conditions of the query (i.e., everything after WHERE), or there are no indexes    so all queries will result in a table scan. From a performance perspective it's safe to say you always want to    decrease this value. However, in some case it might increase after optimization because the server is then able    to do more. Ultimately, it will have to decrease again when qps (queries per second) gets higher.    <br />
<br />
<h2>Select_range</h2>
Select_range refers to a table that was read from the hard drive only in the necessary places to satisfy a    limited range of conditions. For such tables EXPLAIN lists type: range. An index tells MySQL where the    necessary places to read are, which saves time that would otherwise be wasted on disk seeks. Therefore,    Select_range is a lot faster than Select_scan. The queries <span class="mrk">SELECT * FROM tbl1 WHERE col1    BETWEEN 5 AND 13;</span> and <span class="mrk">SELECT * FROM tbl1 WHERE col1 &gt; 5 AND col1 &lt; 13;</span>    specify a range that MySQL could use if col1 is indexed, otherwise MySQL would have to table scan. The MySQL    manual has a section on <a href="http://dev.mysql.com/doc/refman/5.0/en/range-optimization.html">range optimization</a>    that briefly outlines the conditions in which MySQL can use a range.<br />
<br />
<h2>Select_full_join</h2>
Select_full_join is the same as Select_scan with the difference that Select_full_join applies to the second    and subsequent tables in the join plan for a multiple table query. For such tables EXPLAIN lists type: ALL.    Select_full_join results if there are no indexes on the table, or no indexes can be used to join the table.    A query like <span class="mrk">SELECT * FROM tbl1, tbl2 WHERE tbl1.col1 = tbl2.col1;</span> without any indexes    results in a Select_scan and a Select_full_join; Select_scan for the first table, Select_full_join for the second.    Select_full_join is no more desirable than Select_scan. Together the two are even worse. When EXPLAIN lists type:    ALL for each table in a join &quot;this output indicates that MySQL is generating a Cartesian product of all the    tables; that is, every combination of rows&quot; (MySQL manual). In simpler terms: Two tables of 10 rows each joined    together does not result in 20 rows, it results in 100 rows (10 multiplied by 10).    In real-world applications tables usually have at least a few thousand rows, so the cross product (a.k.a.    Cartesian product) of even two small tables can quickly become enormous. The worst I've ever seen was a three    table join that caused a cross product of 112 billion rows (actually the query never finished before it    caused the server to halt). Consequently, the per second rate and percentage of SELECT values for    Select_full_join as shown by mysqlreport should be a lot less than 1. (The counter value can be high as long as    the rate and percentage are less than 1.) Although it's beyond the scope of this document to discuss indexing    tables for joins, a quick solution to the query would be an index on tbl1.col1. The query still causes a    Select_scan for the first table in the join plan, but avoids the Select_full_join for thee second table,    and the number of rows produced decreases significantly.    <br />
<br />
<h2>Select_range_check</h2>
Select_range_check is a little better than Select_full_join and uses the same range principles as Select_range.    The difference is Select_range_check is not sure whether it can use a range to join the table so it keeps    checking in case it finds that it can. This &quot;uncertainty&quot; is an effect of the join: With Select_range there's    only one table so MySQL can be certain ahead of time. With multiple tables, the preceding tables may alter    the range conditions therefore MySQL cannot be certain ahead of time. For such tables EXPLAIN still lists    type: ALL because a type: range is not certain. For such tables MySQL also lists &quot;Range checked for each    record (index map: #)&quot; in the &quot;Extra&quot; column. Like Select_range at least one of the tables requires and index    for this optimization to be possible, otherwise the table will probably cause a Select_full_join. For the    query <span class="mrk">SELECT * FROM tbl1, tbl2 WHERE tbl1.col1 &gt; tbl2.col1;</span> if tbl2.col1 is indexed    then MySQL can Select_range_check:
<pre>   mysql&gt; EXPLAIN SELECT * FROM tbl1, tbl2 WHERE tbl1.col1 &gt; tbl2.col1;<br />   +-------------+-------+------+---------------+------+---------+------+------+----------------------+<br />   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                |<br />   +-------------+-------+------+---------------+------+---------+------+------+----------------------+<br />   | SIMPLE      | tbl1  | ALL  | NULL          | NULL | NULL    | NULL |   27 |                      |<br />   | SIMPLE      | tbl2  | ALL  | col1          | NULL | NULL    | NULL |   18 | Range checked for..  |<br />   +-------------+-------+------+---------------+------+---------+------+------+----------------------+<br />   <em>Range checked for each record (index map: 0x1)</em></pre>
With this simple query, MySQL will check the tbl2.col1 index about 27 times, once for each row in tbl1. For each    value tbl1.col1 MySQL will read only the rows in tbl2 where tbl2.col1 &lt; tbl1.col1. (With MySQL 5.x, an index    merge may be checked instead of a range.) If MySQL does use a range to join the table it will not increment    Select_range; it still only increments Select_range_check.<br />
<br />
<h2>Select_full_range_join</h2>
Select_full_range_join is the same as Select_range_check except that MySQL is certain it can join the table    using a range. For such tables EXPLAIN lists type: range. Like Select_range, Select_full_range_join requires    an index and is much faster than Select_full_join and potentially faster than Select_range_check. The same    range optimization principles for Select_range apply to the table being joined. A simple example:
<pre>   mysql&gt; EXPLAIN SELECT * FROM tbl1, tbl2 WHERE tbl1.col1 = 10 AND tbl2.col1 &gt; 13;<br />   +-------------+-------+-------+---------------+------+---------+-------+------+-------------+<br />   | select_type | table | type  | possible_keys | key  | key_len | ref   | rows | Extra       |<br />   +-------------+-------+-------+---------------+------+---------+-------+------+-------------+<br />   | SIMPLE      | tbl1  | ref   | col1          | col1 | 5       | const |    1 | Using where |<br />   | SIMPLE      | tbl2  | range | col1          | col1 | 5       | NULL  |    1 | Using where |<br />   +-------------+-------+-------+---------------+------+---------+-------+------+-------------+<br /><br />   </pre>
Since the range condition doesn't change, MySQL can certainly use the tbl2.col1 index to read only the necessary    records for tbl2, then join these results to tbl1.<br />
<br />
<h2>Sort_scan and Sort_range</h2>
Queries that sort rows, either by using ORDER BY or GROUP BY (except GROUP BY with ORDER BY NULL), undergo    three primary steps:
<ol>
    <li>Find rows based on WHERE conditions</li>
    <li>Sort rows</li>
    <li>Read rows in sorted order</li>
</ol>
Since data is stored in random order, these three steps make logical sense because the query is not    going to find the matching rows in the order they need to be returned. Unless step two can be bypassed (which    is possible) a Sort_scan and Sort_range will be incurred in step three. If step one results in    Select_scan, step three will result in Sort_scan. If step one Select_range, then step three Sort_range.    Essentially, there is no functional difference between Sort_scan and Sort_range: In either case only the    necessary rows are read in sorted order. Therefore the performance implications of Sort_scan and Sort_range    are no different: The effect on performance in either case is usually unnoticeable.<br />
<br />
<h2>Sort_merge_passes</h2>
Sort_merge_passes involves step two of the query-sort process. MySQL first tries to sort all the rows in    memory, the allotment of which is control by the sort_buffer_size    <a href="http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html">system variable</a>. If sort_buffer_size    is not large enough for all the rows, MySQL creates a temporary file to store the sorted rows, however the    temporary file will need to be sorted too after all rows have been found in step one. The re-sorting of the    temporary file counts toward Sort_merge_passes. MySQL actually creates a second temporary file into which    it puts the sorted contents of the first file. Therefore, it's common to see almost exactly twice as many    created temporary files as Sort_merge_passes. Technically, this is a slow process, however it's impact on    performance is usually unnoticeable. Increasing sort_buffer_size can decrease the number of Sort_merge_passes    and also the number of temporary files created.<br />
<br />
<h2>Sort_rows</h2>
Sort_rows is simply a total count of the number of rows sorted in step two. Since step two can be bypassed    in some cases, Sort_rows is not entirely inclusive. Also since Sort_scan and Sort_range in step two are    essentially no different, the Sort_rows value is not very indicative of anything. Consequently, it was    removed from mysqlreport in version 1.3. Sufficient to say most servers sort hundreds of millions of rows.
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/149178#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, 18 Dec 2007 16:49:06 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/149178</link>
        <guid>http://myreligion.javaeye.com/blog/149178</guid>
      </item>
      <item>
        <title>介绍一种实用的有效的hibernate查询缓存设计，欢迎讨论</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/148687" style="color:red;">http://myreligion.javaeye.com/blog/148687</a>&nbsp;
          发表时间: 2007年12月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal" align="left" style="text-align: left;"><span lang="EN-US" style="font-family: 宋体;"><o:p> </o:p></span></p>
<ol start="1" type="1">
    <li class="MsoNormal" style="text-align: left;"><strong style=""><span lang="EN-US" style="font-family: 宋体;">hibernate</span></strong><strong style=""><span style="font-family: 宋体;">自带缓存的情况介绍<span lang="EN-US"><o:p></o:p></span></span></strong></li>
</ol>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 15pt;"><span lang="EN-US" style="font-family: 宋体;">hibernate</span><span style="font-family: 宋体;">提供了两种缓存，一个是基于对象主<span lang="EN-US">ID</span>的一级缓存和一个为缓存查询结果而设计的二级缓存（姑且叫作查询缓存），一级缓存是默认开启的， 而且似乎也是很难关闭的；查询缓存默认是关闭的，而在我的印象中则一直觉得这个东西是<span lang="EN-US">&ldquo;</span>没有价值的<span lang="EN-US">&rdquo;</span>，至今没有看到典型的使用案例和使用模式。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span lang="EN-US" style="font-family: 宋体;">hibernate</span><span style="font-family: 宋体;">提供的查询缓存，默认会去<span lang="EN-US">cache</span>所有的查询请求，而这对于常用的系统而言是完全没有必要的。大多数真正需要缓存的应用场景，往往是 数据量庞大，交互操作较多的系统，而一般真正需要缓存的数据只有少量的查询，如果所有的查询都缓存，缓存的效率会大大降低而且会浪费很多内存，可能效率还 不如不用缓存。例如<span lang="EN-US">javaeye</span>论坛的版面帖子列表，我们希望缓存的往往也就是每一个版的第<span lang="EN-US">1</span>，<span lang="EN-US">2</span>页帖子，如果用户翻老帖子，则不去缓存。这种场景应该 是经常用到的缓存场景，而<span lang="EN-US">hibernate</span>查询缓存恰恰不能自动做到，这个就是我们将要讨论解决的问题。<span lang="EN-US"><o:p></o:p></span></span></p>
<ol start="2" type="1">
    <li class="MsoNormal" style="text-align: left;"><strong style=""><span style="font-family: 宋体;">我们会用多少的查询缓存？<span lang="EN-US"><o:p></o:p></span></span></strong></li>
</ol>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span style="font-family: 宋体;">一级缓存<span lang="EN-US">HibernateTemplate</span>只有<span lang="EN-US">load()</span>和<span lang="EN-US">get()</span>方法才会使用，如果您用的是<span lang="EN-US">list(..;)</span>或者其他的方法都是不缓存的。如果您的系统有内容审核这么一说（如只有审核通过的才能对外显示，删除的不对外显示等等），即使是提取一个帖子（可以用<span lang="EN-US">get()</span>的情形），你们组程序员提取数据的语句一般也会写成<span lang="EN-US">list(from XXXX where id = &hellip; and </span>状态<span lang="EN-US"> = </span>审核通过的<span lang="EN-US">)</span>，以图方便或者为了数据库连接可以为<span lang="EN-US">readonly</span>事务，这样<span lang="EN-US">hibernate</span>仅有的一级缓存也会被跳过，您的查询语句都是没有缓存的！这时候一个有效的查询缓存将会给你的系统带来巨大的性能提升。<span lang="EN-US"><o:p></o:p></span></span></p>
<ol start="3" type="1" style="margin-top: 0cm;">
    <li class="MsoNormal" style=""><strong style=""><span style="font-family: 宋体;">一般的应用场景与通用的查询缓存应该具备的功能</span></strong><strong style=""><span lang="EN-US" style=""><o:p></o:p></span></strong></li>
</ol>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span style="font-family: 宋体;">缓存的使用目的是为了提供性能，缓存的使用后果是数据将会有延迟。如果我们决心使用缓存，一般的应用场景应该具有如下特点：事务要求低，数据实时性要求低，并发量要求高，系统可扩展性要求高，机器硬件成本要求低，总之非常适合大面积的空间换时间设计方法并且对数据的完整<span lang="EN-US">/</span>准确度要求不高。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span style="font-family: 宋体;">缓存还应该是通用的，应用系统只要配置下即可使用；不能每个系统都单独开发，这样也就没有讨论的意义了。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span style="font-family: 宋体;">对于要缓存的东西，往往应用本身而且只有应用本身了解什么情况下需要缓存，所以查询缓存应该提供接口，由应用提供解释，来描述哪些查询是需要缓存的，哪些是不需要缓存的。如对于论坛的版面帖子列表，应用可以告诉缓存模块：<span lang="EN-US">Java</span>版缓存第<span lang="EN-US">1</span>，<span lang="EN-US">2</span>页的帖子，回收站不做缓存，其他版面缓存第<span lang="EN-US">1</span>页帖子列表，如果用户是登录用户则所有版面的帖子列表都不做缓存；只有这样才能真正的提高缓存的效率，降低缓存成本。<span lang="EN-US"><o:p></o:p></span></span></p>
<ol start="4" type="1" style="margin-top: 0cm;">
    <li class="MsoNormal" style=""><strong style=""><span style="font-family: 宋体;">一种基于域对象的缓存实现方式</span></strong><strong style=""><span lang="EN-US" style=""><o:p></o:p></span></strong></li>
</ol>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span style="font-family: 宋体;">针对前面的描述，偶做了一个实现，基于<span lang="EN-US">annotation</span>的定义（当然可以基于<span lang="EN-US">xml</span>配置或者基于数据库，然后可以在线的调试配置参数达到最优）。定义如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span lang="EN-US" style="font-family: 宋体;">
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar"> </div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span class="annotation">@SuppressWarnings</span><span>(</span><span class="string">&quot;serial&quot;</span><span>)  </span></span></li>
    <li class=""><span><span class="annotation">@Entity</span><span>  </span></span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span><span class="annotation">@Cachable</span><span>(interval=5)<br />
    </span></span></li>
    <li class="alt"><span><span class="annotation">@UniqueCondition</span><span>(combine = </span><span class="string">&quot;id=?::limit=2000;word=?::limit=2000&quot;</span><span>)  </span></span></li>
    <li class=""><span><span class="annotation">@QueryCondition</span><span>(combine = </span><span class="string">&quot;categoryId=?::limit=30::orderBy=id desc, parentCategoryId=?&amp;&amp;status=10&quot;</span><span>)  </span></span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> SomeObject {  </span></span></li>
    <li class="alt"><span>      </span></li>
    <li class=""><span>    <span class="keyword">private</span><span> </span><span class="keyword">int</span><span> id ;  </span></span></li>
    <li class="alt"><span>      </span></li>
    <li class=""><span>    <span class="comment">/**状态*/</span><span>  </span></span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">int</span><span> status ;  </span></span></li>
    <li class=""><span>      </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">double</span><span> symbolLength ;  </span></span></li>
    <li class=""><span>      </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> String word ;  </span></span></li>
    <li class=""><span>      </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> String symbol ;  </span></span></li>
    <li class=""><span>      </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">int</span><span> categoryId ;  </span></span></li>
    <li class=""><span>      </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">int</span><span> clickCount ;  </span></span></li>
    <li class=""><span>      </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">int</span><span> parentCategoryId ;  </span></span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="annotation">@Id</span><span>  </span></span></li>
    <li class=""><span>    <span class="annotation">@GeneratedValue</span><span>(strategy=GenerationType.AUTO)  </span></span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">int</span><span> getId() {  </span></span></li>
    <li class=""><span>           <span class="keyword">return</span><span> id;  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setId(</span><span class="keyword">int</span><span> id) {  </span></span></li>
    <li class=""><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.id = id;  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> String getSymbol() {  </span></span></li>
    <li class=""><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> symbol;  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setSymbol(String ipa) {  </span></span></li>
    <li class=""><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.symbol = ipa;  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="annotation">@QueryConditionIgnoreParseField</span><span>  </span></span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">double</span><span> getSymbolLength() {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> symbolLength;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setSymbolLength(</span><span class="keyword">double</span><span> length) {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.symbolLength = length;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> String getWord() {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> word;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setWord(String word) {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.word = word;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> String authSignature() {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">int</span><span> getCategoryId() {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> categoryId;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setCategoryId(</span><span class="keyword">int</span><span> categoryId) {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.categoryId = categoryId;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="annotation">@CacheIngoreUpdateField</span><span>  </span></span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">int</span><span> getClickCount() {  </span></span></li>
    <li class=""><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> clickCount;  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>      </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setClickCount(</span><span class="keyword">int</span><span> clickCount) {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.clickCount = clickCount;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">int</span><span> getParentCategoryId() {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> parentCategoryId;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setParentCategoryId(</span><span class="keyword">int</span><span> parentCategoryId) {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.parentCategoryId = parentCategoryId;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">int</span><span> getStatus() {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">return</span><span> status;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setStatus(</span><span class="keyword">int</span><span> status) {  </span></span></li>
    <li class="alt"><span lang="EN-US" style="font-family: 宋体;"><span>           </span></span><span><span class="keyword">this</span><span>.status = status;  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>}  </span></li>
</ol>
</div>
<o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="margin-left: 21pt; text-align: left; text-indent: 21pt;"><span style="font-family: 宋体;"><strong>各项定义解释：</strong><span lang="EN-US"><o:p></o:p></span></span></p>
<ul>
    <li><!--[if !supportLists]--><span lang="EN-US" style="font-family: Wingdings;"><span style=""><span new="" font-style:="" font-stretch:="" font-size:="" times="" font-weight:="" line-height:="" roman="" font-size-adjust:="" style="" font-variant:=""></span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体;">Cachable </span><span style="font-family: 宋体;">，指定这个实体是要进行缓存的。<span lang="EN-US">interval=5</span>，表示对象<span lang="EN-US">cache 5</span>秒失效。 <span lang="EN-US"><o:p></o:p></span></span></li>
    <li><!--[if !supportLists]--><span lang="EN-US" style="font-family: Wingdings;"><span style=""><span new="" font-style:="" font-stretch:="" font-size:="" times="" font-weight:="" line-height:="" roman="" font-size-adjust:="" style="" font-variant:="">         </span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体;">QueryCondition</span><span style="font-family: 宋体;">为一般的查询缓存，指定那些条件下进行结果集<span lang="EN-US">cache</span>，如此处就是说当条件为<span lang="EN-US">cateogory=</span>某一个值，并且按照<span lang="EN-US">id desc</span>进行排序时<span lang="EN-US">cache</span>查询记录的前<span lang="EN-US">30</span>条（如果一页显示<span lang="EN-US">15</span>条，则缓存第<span lang="EN-US">1</span>，<span lang="EN-US">2</span>页，第<span lang="EN-US">3</span>，<span lang="EN-US">4</span>，<span lang="EN-US">5</span>。。。不做缓存）。或者当条件为<span lang="EN-US">parentCategoryId=?</span>并且<span lang="EN-US">status=10</span>进行缓存，缓存不考虑排序字段，并且缓存所有结果。<span lang="EN-US"><o:p></o:p></span></span></li>
    <li><!--[if !supportLists]--><span lang="EN-US" style="font-family: Wingdings;"><span style=""><span new="" font-style:="" font-stretch:="" font-size:="" times="" font-weight:="" line-height:="" roman="" font-size-adjust:="" style="" font-variant:=""></span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体;">UnqiueConditon</span><span style="font-family: 宋体;">，指定对象的唯一性条件，当满足这个条件时可以保证数据库只有一个对象，常见情形如用户表的<span lang="EN-US">username, nickName</span>，<span lang="EN-US">id</span>等。此处按照<span lang="EN-US">id</span>查询时进行缓存，最多缓存<span lang="EN-US">2000</span>条记录；如果按照<span lang="EN-US">word</span>字段进行查询，也进行缓存，最多缓存<span lang="EN-US">2000</span>条记录。如对于查询条件<span lang="EN-US"> id = 134343 and status = 10 ;cache</span>分析出含有记录唯一保证的字段<span lang="EN-US">id</span>，<span lang="EN-US">status</span>就可以暂时忽略，先通过<span lang="EN-US">id=134343</span>从<span lang="EN-US">cache</span>中读取记录，然后在利用好比反射的方 法查看对象的<span lang="EN-US">status</span>是否为<span lang="EN-US">10</span>，如果是，就直接对象，不是返回<span lang="EN-US">null</span>；保证同一个对象尽量占用同样的<span lang="EN-US">cache</span>位置。<span lang="EN-US"> <o:p></o:p></span></span></li>
    <li><!--[if !supportLists]--><span lang="EN-US" style="font-family: Wingdings;"><span style=""></span><span lang="EN-US" style="font-family: 宋体;">CacheIngoreUpdateField </span><span style="font-family: 宋体;">这个表示忽略的更新字段。因为<span lang="EN-US">clickCount</span>用户每次打开都会更新<span lang="EN-US">+1</span>，如果此时刷新<span lang="EN-US">cache</span>，<span lang="EN-US">cache</span>也就可以撤消了。所以我们通过定义 这个标记，如果某一个<span lang="EN-US">update</span>操作只是更新了<span lang="EN-US">clickCount</span>字段，只更新数据库，<span lang="EN-US">cache</span>依然有效不做更新。等到<span lang="EN-US">Cachable</span>标记的<span lang="EN-US"> interval</span>让对象失效以后再更新，保证<span lang="EN-US">cache</span>的低刷新频率。 <span lang="EN-US"><o:p></o:p></span></span></span></li>
    <li><!--[if !supportLists]--><span lang="EN-US" style="font-family: Wingdings;"><span style=""><span new="" font-style:="" font-stretch:="" font-size:="" times="" font-weight:="" line-height:="" roman="" font-size-adjust:="" style="" font-variant:="">         </span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体;">QueryConditionIgnoreParseField </span><span style="font-family: 宋体;">表示此字段不参与是否需要<span lang="EN-US">cache</span>的匹配，如此处的<span lang="EN-US">symbolLength</span>，只要标记了<span lang="EN-US">@ QueryConditionIgnoreParseField</span>，无论查询条件中有没有<span lang="EN-US">symbolLength</span>条件，都不影响查询缓存决定当前查询是否需要做缓存。<span lang="EN-US"><o:p></o:p></span></span></li>
    <li><!--[if !supportLists]--><span lang="EN-US" style="font-family: Wingdings;"><span style=""><span new="" font-style:="" font-stretch:="" font-size:="" times="" font-weight:="" line-height:="" roman="" font-size-adjust:="" style="" font-variant:=""></span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体;">Entity</span><span style="font-family: 宋体;">为<span lang="EN-US">hibernate</span>的标记。</span></li>
</ul>
<br />
----编辑器看到的效果好像和显示的不一样，一直排不对版面:(
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/148687#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, 16 Dec 2007 15:56:57 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/148687</link>
        <guid>http://myreligion.javaeye.com/blog/148687</guid>
      </item>
      <item>
        <title>对于应用高并发，DB千万级数量该如何设计系统哪？</title>
        <author>myreligion</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myreligion.javaeye.com">myreligion</a>&nbsp;
          链接：<a href="http://myreligion.javaeye.com/blog/38879" style="color:red;">http://myreligion.javaeye.com/blog/38879</a>&nbsp;
          发表时间: 2006年12月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>背景：</strong>  博客类型的应用，系统实时交互性比较强。各种统计，计数器，页面的相关查询之类的都要频繁操作数据库。数据量要求在千万级，同时在线用户可能会有几万人活跃。系统现在是基于spring + hibernate + jstl + mysql的，在2千人在线，几十万记录下没有什么压力。可对于千万记录以及数万活跃用户没什么经验和信心。  对于这些，我的一点设计想法与问题，欢迎大家指导：    <strong>一. 加强cache</strong>    由于web2类型的网站，用squid反向代理可能不是很适用；由于这种情况下需要cluster，jvm上作过多cache可能会引起其他问题；所以比较合适的应该是采用静态发布的方式，把数据发布成xml文件，然后通过xml + xslt 拼接各模块(div)显示。（直接发布成html文件用jstl感觉不是很方便，也没用过，请有经验的介绍下），主要目的就是把压力拦截在Apache上。或者用memcached cache文章内容，用户资料等对象。  <strong>二. 数据库分库</strong>    分库有两种，一种是分表，把经常访问的放一张表，不常访问的放一张表。 好比对于博客，文章表可以分为文章基本信息（标题，作者，正文&hellip;&hellip;）不常改动的信息，和文章统计信息（阅读次数，评论次数&hellip;&hellip;）经常变动的信息，以期望update统计信息之类的可以快一点（这个东西实践起来弊端也会比较明显：查询文章时需要多查询一次统计信息表，到底能不能提高性能还没有具体数据，欢迎有经验的给点数据：） ）。 对于记录过多，好比千万级，这样的分法显然也解决不了问题，那么就需要归档处理了。归档大致就是创建一个同样的表，把旧内容（好比三个月以前的）都移到旧表里面，保持活跃的表记录不多。（mysql本身有一个archive引擎，看资料感觉对解决大量数据没什么用处，连索引都不支持，用过的朋友可以给点建议）。归档带来的最大问题就是：归档以后的数据如何访问哪？如果用户要访问以前的数据就会比较麻烦了。（mysql的merge查询？）大家这方面有没有好的practice？我还没想到好的办法。 分库的另外一种方式是物理的分，就是装他几十台mysql服务器，然后按照某种方式把数据分散到不同的服务器上，这种方式也有利于备份恢复和系统的稳定性（一台数据库宕了，也只会影响一部分功能或用户）。例如对于博客应用，比较理想的分库模式可以按照用户分，好比我把用户id在1&hellip;10万的资料都存到mysql1上，把10万。。。20万的存到mysql2&hellip;.，依次类推，通过线性增加服务器的方式解决大数据问题。 呵呵，还算完美吧~~，就是给统计排名带来了麻烦&hellip;&hellip; 按照第二种分库方式，数据库连接将发生变化，如果数据达到千万，10几个mysql应该是需要的，这时候连接池就要废掉了，采用每次查询取链接的方式。或者需要改造出一个特别的连接池了。  <strong>三．采用Ibatis</strong>    把hibernate废掉，改用ibatis，毕竟ibatis可以很方便的进行sql优化，有什么问题优化起来方便多了（还没有用过ibatis，只是感觉）。另一方面，如果物理分库有效果，好像严格的sql优化意义也就不大了。这应该也是一个优化方面。   总结一下我的结构：把文章，用户资料，各种分类，tag, 链接，好友之类的进行静态化（xml + xslt 读取显示） + 物理分库 + ibatis sql优化 + JVM短暂性的cache总的用户数，在线用户数等极个别数据，其他的全部不cache（包括关闭hibernate二级缓存，如果用hibernate）
          <br/>
          <span style="color:red;">
            <a href="http://myreligion.javaeye.com/blog/38879#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, 13 Dec 2006 14:54:01 +0800</pubDate>
        <link>http://myreligion.javaeye.com/blog/38879</link>
        <guid>http://myreligion.javaeye.com/blog/38879</guid>
      </item>
  </channel>
</rss>