﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-常言笑的家-随笔分类-数据库</title><link>http://www.blogjava.net/wealupa/category/23608.html</link><description>Spring, Hibernate, Struts, Ajax, RoR</description><language>zh-cn</language><lastBuildDate>Wed, 07 Jul 2010 04:12:07 GMT</lastBuildDate><pubDate>Wed, 07 Jul 2010 04:12:07 GMT</pubDate><ttl>60</ttl><item><title>权限管理的数据库设计</title><link>http://www.blogjava.net/wealupa/archive/2010/07/06/325373.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Tue, 06 Jul 2010 07:54:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2010/07/06/325373.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/325373.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2010/07/06/325373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/325373.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/325373.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;*/use&nbsp;[master]go&nbsp;--&nbsp;检查数据库&nbsp;[RBAC]是否存在,如果存在则删除(只测试用,不然会丢数据.)--&nbsp;Search&nbsp;from&nbsp;the&nbsp;sysdatabase&nbsp;to&nbsp;see&nbsp;that&nbsp;if&nbsp;the&nbsp;[RBAC]...&nbsp;&nbsp;<a href='http://www.blogjava.net/wealupa/archive/2010/07/06/325373.html'>阅读全文</a><img src ="http://www.blogjava.net/wealupa/aggbug/325373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2010-07-06 15:54 <a href="http://www.blogjava.net/wealupa/archive/2010/07/06/325373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sql server 2005 版本</title><link>http://www.blogjava.net/wealupa/archive/2008/04/25/195808.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Fri, 25 Apr 2008 01:25:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2008/04/25/195808.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/195808.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2008/04/25/195808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/195808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/195808.html</trackback:ping><description><![CDATA[<p>SQL2005 分五个版本，如下所列，&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;1.Enterprise(企业版),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;2.Development(开发版),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;3.Workgroup,(工作群版)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;4.Standard,(标准版)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;5.Express.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;简单的比较一下 Enterprise, Development 和 Express 等三个版本:以功能言，Enterprise 版和 Development 版的功能一模一样。两者的差别，除了授权不同外，最主要的差别是:&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;Enterprise版的数据库引擎只能安装在Win2003Server(或其他Server)。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;如果你想安装在WindowsXP Pro系统上，你应该安装SQL2005Development版(开发版)。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;什么是「数据库引擎」。数据库引擎是SQL2005的核心，是最主要的数据库管理功能模块。没有它，就不是数据库管理系统了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;因此，如果你是初学者，如果你只是想要在家里学习学习，如果你的环境是 WindowsXP Pro，那么，你应该选择的是 SQL2005Development(开发版)，而不是SQL2005Enterprise(企业版)或SQL2005Express(简易版)。<br />
</p>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;以在生产环境中使用所有版本的 SQL Server 2005，但 SQL Server 2005 Developer Edition 和 SQL Server 2005 Evaluation Edition 除外。以下段落介绍 SQL Server 2005 的多个版本。
<dl>
<dt><strong>SQL Server 2005 Enterprise Edition（32 位和 64 位）</strong>
<dd>
<p>Enterprise Edition 达到了支持超大型企业进行联机事务处理 (OLTP)、高度复杂的数据分析、数据仓库系统和网站所需的性能水平。Enterprise Edition 的全面商业智能和分析能力及其高可用性功能（如故障转移群集），使它可以处理大多数关键业务的企业工作负荷。Enterprise Edition 是最全面的 SQL Server 版本，是超大型企业的理想选择，能够满足最复杂的要求。</p>
</dd></dl>
<dl>
<dt><strong>SQL&nbsp;Server&nbsp;2005 Evaluation Edition（32 位和 64 位）</strong>
<dd>
<p>SQL Server 2005 还推出了适用于 32 位或 64 位平台的 180 天 Evaluation Edition。SQL Server Evaluation Edition 支持与 SQL Server 2005 Enterprise Edition 相同的功能集。可以根据生产需要升级 SQL Server Evaluation Edition。</p>
</dd></dl>
<dl>
<dt><strong>SQL Server 2005 Standard Edition（32 位和 64 位）</strong>
<dd>
<p>SQL Server 2005 Standard Edition 是适合中小型企业的数据管理和分析平台。它包括电子商务、数据仓库和业务流解决方案所需的基本功能。Standard Edition 的集成商业智能和高可用性功能可以为企业提供支持其运营所需的基本功能。SQL Server 2005 Standard Edition 是需要全面的数据管理和分析平台的中小型企业的理想选择。</p>
</dd></dl>
<dl>
<dt><strong>SQL Server 2005 Workgroup Edition（仅适用于 32 位）</strong>
<dd>
<p>对于那些需要在大小和用户数量上没有限制的数据库的小型企业，SQL Server 2005 Workgroup Edition 是理想的数据管理解决方案。SQL Server 2005 Workgroup Edition 可以用作前端 Web 服务器，也可以用于部门或分支机构的运营。它包括 SQL Server 产品系列的核心数据库功能，并且可以轻松地升级至 SQL Server 2005 Standard Edition 或 SQL Server 2005 Enterprise Edition。SQL Server 2005 Workgroup Edition 是理想的入门级数据库，具有可靠、功能强大且易于管理的特点。</p>
</dd></dl>
<dl>
<dt><strong>SQL Server 2005 Developer Edition（32 位和 64 位）</strong>
<dd>
<p>SQL Server 2005 Developer Edition 允许开发人员在 SQL Server 顶部生成任何类型的应用程序。该应用程序包括 SQL Server 2005 Enterprise Edition 的所有功能，但许可用作开发和测试系统，而不用作生产服务器。SQL Server 2005 Developer Edition 是独立软件供应商 (ISV)、咨询人员、系统集成商、解决方案供应商以及生成和测试应用程序的企业开发人员的理想选择。可以根据生产需要升级 SQL Server 2005 Developer Edition。</p>
</dd></dl>
<dl>
<dt><strong>SQL Server 2005 Express Edition（仅适用于 32 位）</strong>
<dd>
<p>SQL Server Express 数据库平台基于 Microsoft SQL Server 2005。它也可以替换 Microsoft Desktop Engine (MSDE)。通过与 Microsoft Visual Studio 2005 集成，SQL Server Express 简化了功能丰富、存储安全且部署快速的数据驱动应用程序的开发过程。</p>
<p>SQL Server Express 是免费的，可以再分发（受制于协议），还可以充当客户端数据库以及基本服务器数据库。SQL Server Express 是独立软件供应商 ISV、服务器用户、非专业开发人员、Web 应用程序开发人员、网站主机和创建客户端应用程序的编程爱好者的理想选择。如果需要更多的高级数据库功能，可将 SQL Server Express 无缝升级到更复杂的 SQL Server 版本。</p>
<p>SQL Server Express 还提供了一些附加组件，这些组件都作为具有高级服务的 Microsoft SQL Server 2005 Express Edition (SQL Server Express) 的一部分提供。除了 SQL Server Express 的功能外，具有高级服务的 SQL Server Express 还包括以下功能：</p>
<ul>
    <li>SQL Server Management Studio Express (SSMSE)，SQL Server Management Studio 的子集。<br />
    <li>支持全文目录。<br />
    <li>支持通过 Reporting Services 查看报表。<br />
    </li>
</ul>
</dd></dl>
<dl>
<dt><strong>SQL Server 2005 Mobile Edition（仅 32 位）</strong>
<dd>
<p>SQL Server Mobile 是简版数据库，将企业数据管理功能扩展到小型设备上。SQL Server Mobile 能够复制 Microsoft SQL Server 2005 和 Microsoft SQL Server 2000 的数据，并且允许用户维护与主数据库同步的移动数据存储。SQL Server Mobile 是唯一为智能设备提供关系数据库管理功能的 SQL Server 版本。</p>
</dd></dl>
<dl>
<dt><strong>SQL&nbsp;Server&nbsp;2005 Runtime Edition（32 位和 64 位）</strong>
<dd>
<p>SQL Server 2005 Runtime Edition 随 Microsoft ISV Royalty Program 提供。根据 SQL Server 2005 Runtime Edition 的最终用户许可协议，如果用户不使用 SQL Server 代码运行任何其他应用程序或者在任何其他上下文中使用 SQL Server 代码，独立软件供应商 (ISV) 可能将 SQL Server 代码嵌入到他们提供的解决方案中。关于 SQL Server Runtime Edition 的详细信息，请参阅 Microsoft 知识库中的文章<a onclick="javascript:Track('ctl00_LibFrame_ctl02|ctl00_LibFrame_ctl03',this);" href="http://support.microsoft.com/kb/917400">如何获取 SQL Server Runtime 许可证</a> (<a href="http://support.microsoft.com/kb/917400">http://support.microsoft.com/kb/917400</a>)。<br />
<br />
<strong><span style="color: red">注意点：</span></strong></p>
<dd>
<p>&nbsp;在XP上不能安装 Enterprise 版本，<br />
<br />
&nbsp;Express版本只能在本地访问，不能进行远程访问。<br />
<br />
&nbsp;Express版本连接时需要在连接字符串中写 ***\SQLExpress<br />
<br />
&nbsp;Developer版本可以进行远程访问，记住要启用TCP/IP连接，同时要设置好防火墙</p>
</dd></dl>
<img src ="http://www.blogjava.net/wealupa/aggbug/195808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2008-04-25 09:25 <a href="http://www.blogjava.net/wealupa/archive/2008/04/25/195808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据仓库初探</title><link>http://www.blogjava.net/wealupa/archive/2007/06/26/126314.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Tue, 26 Jun 2007 05:11:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2007/06/26/126314.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/126314.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2007/06/26/126314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/126314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/126314.html</trackback:ping><description><![CDATA[<p><font color=#0000ff>数据仓库的概念</font><br>数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合，用于支持管理决策。<br>1.<font color=#ff0000>面向主题</font>：不同于操作型数据库，主题是个抽象概念，是指用户使用数据仓库进行决策时所关心的重点方面。涉及业务流程的方方面面，而不像操作型数据库一样相互隔离。<br>2.<font color=#ff0000>集成的</font>:操作型数据库通常与某些特定的应用相关，而数据库往往相互独立，他们是异构的。数据仓库是对原有的分散数据进行了整合，进行了数据类型转化，消除了数据中的不一致性。<br>3.<font color=#ff0000>相对稳定</font>：数据仓库是稳定的，由于要做企业分析决策之用，一般情况下将被长期保留，以备日后参考查询。而说他是相对稳定的是因为，数据仓库要保存历史信息，以便反映某一事物的变化情况，作为分析决策的原始资料，所以数据仓库必须维护历史信息，所以他是相对稳定的。Write once, read many times.<br>4.<font color=#ff0000>反映历史变化</font>：以支持分析决策，由过去的发展历程总结出规律，从而对未来作出合理的预测。</p>
<p><font color=#0000ff>数据仓库环境<br></font>1.<font color=#ff0000>ETL</font>：数据抽取、转化和载入<br>2.<font color=#ff0000>OLAP</font>：OnLine Analytical Processing Engine<br>3.<font color=#ff0000>DSS</font>：决策支持系统<br>4.<font color=#ff0000>客户分析与报表工具</font><br>5.<font color=#ff0000>其他数据收集和数据输出工具</font></p>
<p><font color=#0000ff>数据仓库的构架</font><br>数据仓库大体可以分为四个层次：<br>数据源、数据管理与存储层、OLAP服务器和前端工具。<br>1.<font color=#ff0000>数据源</font>：他是数据仓库的基础，位于数据仓库构架的最底层，是数据仓库的数据源泉。包括各个业务处理子系统的信息。<br>2.<font color=#ff0000>数据管理与存储层</font>：是数据仓库的核心。数据仓库如何高效管理数据是区别与面向操作数据库的主要标准。完成按照主题管理数据，聚合数据存放于多维数据库中。<br>3.<font color=#ff0000>OLAP服务器</font>：对数据进行有效集成，按多维模型予以组织。<br>4.<font color=#ff0000>前端工具</font>：主要包括各种报表工具、查询工具、数据挖掘工具等。</p>
<p><font color=#0000ff>有关ETL</font><br>数据进入数据仓库的过程一般都要经过抽取（extracted）、转化（transformed）和载入（loaded）三个过程，这个过程被简称为ETL。一般使用现有工具来实现ETL的过程。<br>1.<font color=#ff0000>E:数据抽取。</font>在数据抽取的同时，数据不能被修改。可以抽取的文件格式为：数据库对象，比如表可以整个地从源系统中导出。比如，MS SQL Server 2000的bcp "select * from Northwind..customers" queryout "D:temp.txt"? -c -p -U"sa" -P"sa"。抽取过程为动态抽取，即目标有变化才抽取，不做无谓的工作而影响效率。一种实现的办法就是加时间戳；另一种方法就是分别在不同的表中进行描述。<br>2.<font color=#ff0000>T:数据转化。</font>即将数据从一个系统转移到另外一个系统中。顺序为：源系统 -&gt; staging database -&gt; 数据仓库 -&gt; data mart。有三种方式：a.flat files(无范式) b.区分操作 c.使用交换分区。<br>3.<font color=#ff0000>L:数据输入</font></p>
<p><font color=#0000ff>其他</font></p>
<p>数据仓库不一定要用数据库来实现</p>
<p>数据仓库不满足第三范式，并且不满足范式，他只含有&#8220;键（key）&#8221;。（第一范式：有主键，主观上形象的看，是符合常理的分类或组织；第二范式：满足第一范式，并且所有除主键之外的列都与所有的主键有关系；第三范式：满足第二范式，并且所有除主键之外的列相互之间没有关系）</p>
<img src ="http://www.blogjava.net/wealupa/aggbug/126314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2007-06-26 13:11 <a href="http://www.blogjava.net/wealupa/archive/2007/06/26/126314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实时数据库的简介</title><link>http://www.blogjava.net/wealupa/archive/2007/06/26/126250.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Tue, 26 Jun 2007 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2007/06/26/126250.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/126250.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2007/06/26/126250.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/126250.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/126250.html</trackback:ping><description><![CDATA[<div class=postText>关系数据库使用得比较广，为大部分人所熟悉，以至于谈到数据库，缺省情况下指的就是关系数据库，但实际上还有一些其他种类的数据库在生产生活中被广泛使用，比如我将谈到的实时数据库，它们用在要求非常严格、数据量非常大的生产工控中。<br><br>当今国际国内广泛使用的实时数据库只有三个产品：<br>a. 美国OSI公司的 PI ( Plant Information System )<br>b. 美国HONEYWELL公司的 PHD ( Process History Database )<br>c. 美国AspenTech公司的 IP21 ( InfoPlus .21 )<br><br>这些实时数据库的价格是非常昂贵的，以百万人民币为单位，但是它们不全是以套也不全是以点(可容纳的数据点)为单位来出售，所以无法数字化的比较其价格。因为工作的关系，我有幸能接触到这三种数据库，在此对它们做一个比较。<br><br>1. PI<br>采用了旋转门压缩专利技术和独到的二次过滤技术，使进入到PI数据库的数据经过了最有效的压缩，极大地节省了硬盘空间。据计算，每秒1万点数据存储一年，仅需要4G的空间，即一只普通硬盘也可存贮五到十年的数据。是效率最高，使用最简单，使用最广泛的实时数据库，因为其杰出的性能，PI已经多次提高了它的价格，确实不坠OSI的名号，而且PI在其文档中公开了她的各种算法，比如上面提到的旋转门压缩和二次过滤。<br><br>2. PHD<br>HONEYWELL占据了DCS大部分份额，因此PHD使用得也比较广泛，PHD在内部其实使用了Oracle关系数据库，因此购买PHD就必须先购买Oracle。因为 PHD内部使用Oracle简化了开发量 和 Oracle的性能限制比较严重，所以 PHD 的价格在这三种数据库最低，算不上正宗的实时数据库。但不要以为PHD内部使用Oracle就认为Oracle很强，如果直接使用Oracle，只要两三秒的时间，巨大的数据量就会令它崩溃。HONEYWELL其志不在实时数据库这一块，而是她的DCS。<br><br>3. IP21<br>IP21基本上还未进入中国市场，它正在通过先期赠送的办法打开中国市场。<br>在评价IP21之前，我需要先申明&#8220;我对IP21的看法只是个人看法，不是任何产品的托儿&#8221;。<br>IP21是我见过的最差的关系数据库，也是我见过的最差的一个软件，<br>a. 其软件的安装程序的运行需要一个硬狗，这种小气的做法和PI公开算法的做法没法比，问题还在于它的这条狗经常会死翘翘。<br>b. 其软件的安装即使是其公司的专业员工也不能保证安装成功，10台计算机让它的专业员工来安装大约只能成功一两台。<br>c. 其软件的安装盘只有一张，但这一张盘需要安装四个小时以上，中途不停地看到在安装某个版本的Java解释器，其后它们又被删除。<br>d. 没有实现真正的自动安装，在安装之前它们的工程师需要在计算机上修改不少的文件。<br>e. 安装中途如果出现错误是不立即报告的，需要四个小时之后安装完毕才能看到安装失败的字样，但也仅仅只能知道安装失败，不知道在哪一步安装失败。<br>f. 管理维护软件非常的复杂，除非有人愿意牺牲以后的前途来学习它，否则就只能让它自己的员工来鼓弄。<br>g. 运行效率非常低下，而且占用系统资源非常严重，一台服务器只能给一个IP21使用。<br><br>实时数据库的访问方式<br>a. 使用自己的API，这种方式效率最高，其实也最简单。<br>b. 使用ODBC，这种方式其实没有多大作用，因为实时数据库不同于关系数据库，ODBC没有太大的用武之地，所以在使用ODBC时有非常多的限制，大部分功能并不支持ODBC方式。<br>c. 使用OPC方式（OLE for Process Control）<br>&nbsp;&nbsp;因为太多的数据库和DCS使用自己的API方式存取数据，无法做到算法的通用，因为提出了一个标准的存取接口，这就是OPC，如今有超过两百家产商加入到OPC组织中，声势浩大，包括臭名昭著的M$，之所以讲M$臭名昭著是因为M$强制性的在这个标准的存取接口中使用了COM/DCOM，令OPC只能在windows下使用，且效率（因为是工控场合，所以效率非常重要）低下。M$在OPC组织中非常的积极，所以现在的OPC基本上也脱离了当初制定的目标，令很多产商不满，包括OSI在内，虽然OSI PI提供OPC接口，但OSI不建议客户使用它，也不对它进行技术支持。在OPC中的COM还有另外一个大问题，因为COM规定必须支持先前制定的接口，而工控要求又非常严格，开发测试的费用和时间都非常高，没有任何厂商愿意支持先前的COM接口，因此没有真正符合COM标准的OPC。&nbsp;&nbsp;</div>
<div class=postText></div>
<div class=postText>1. OSIsoft正在淡化PI的概念，严格来说2000年后PI就不叫实时数据库了，现在OSIsoft推出的是实时企业智能化解决方案RtPM，PI实时历史数据引擎是RtPM中RtBaseline的一小部分。只是国内现在看来还没到那个阶段:) 国内电力行业用PI作为企业实时数据库的比较多，石化用的不多，其他行业就更少了，主要还是一些合资企业带进来的。PI的价格其实一直比较稳定，面向的是高端客户群，若比较性能价格比的话，PI明显优于PHD和IP.21，变来变去的是OSIsoft在中国的政策。OSIsoft是OPC基金会的成员，主要在OPC内部制定HDA的标准，没有听说过OSIsoft不支持OPC接口,OSIsoft的OPC接口是其版本更新速度最快的一个接口。 <br><br>2. Honeywell曾经是OSIsoft公司最大的集成商，80年代至90年代初期，通过Honeywell销售的PI比OSIsoft自己销售的PI还多。Honeywell现在卖PHD的目的不是帮助DCS的销售，而是Honeywell在石化行业的信息解决方案，如APC等需要一个实时数据平台的支撑，靠卖PHD，Honeywell是不能存活的，事实上用户如果买Honeywell的APC等应用，PHD可以免费，不过羊毛出在羊身上，再说要是用了PHD，最好就一直买Honeywell的高级应用了。 <br><br>3. Aspentech的IP.21和Honeywell的PHD定位一样，靠卖IP.21,Aspentech也活不了。Aspentech产品线很长，几乎都是靠收购来的产品，买来后整合难度很大。IP.21也是Aspentech买来的产品，原来是SetPoint公司的产品，现在IP.21维护更新的开发队伍也就几个人，没准哪天IP.21赔的太多，这个部门就砍了。 <br><br>总结：OSIsoft卖PI赢利，在实时数据处理方面是越来越专，越来越深。Honeywell和Aspentech卖PHD和IP.21赔本，现在在实时数据库技术上吃老本，商务上是能黑就黑一把，最好是买他们的一体化解决方案，永远上他们的贼船。 </div>
<img src ="http://www.blogjava.net/wealupa/aggbug/126250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2007-06-26 09:23 <a href="http://www.blogjava.net/wealupa/archive/2007/06/26/126250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>db2数使用帮助总结</title><link>http://www.blogjava.net/wealupa/archive/2007/06/13/123778.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Wed, 13 Jun 2007 01:52:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2007/06/13/123778.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/123778.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2007/06/13/123778.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/123778.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/123778.html</trackback:ping><description><![CDATA[<strong>一.数据定义语言(DDL)</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、使用create语句创建数据库对象,包括[缓冲池(Buffer pool), 事件监视器(Event monitor), 函数(Function), 索引(Index), 模式(Schema), 存储过程(Stored procedure), 表(Table), 表空间(Table space), 触发器(Trigger), 视图(View)], 例如: <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">CREATE</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">TABLE</span><span style="COLOR: #000000">&nbsp;T_CI_YCLLRDZ<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>(<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;FD_YCLLRDZ_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-WEIGHT: bold; COLOR: #000000">CHAR</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">35</span><span style="COLOR: #000000">)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">NOT</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">NULL</span><span style="COLOR: #000000">,<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;FD_CIYGBH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CHA</span><span style="FONT-WEIGHT: bold; COLOR: #000000">RACTER</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">20</span><span style="COLOR: #000000">),<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;FD_CJYGMC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-WEIGHT: bold; COLOR: #000000">CHARACTER</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">50</span><span style="COLOR: #000000">),<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;FD_WZYGBH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-WEIGHT: bold; COLOR: #000000">CHARACTER</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">20</span><span style="COLOR: #000000">),<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;FD_WZYGMC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-WEIGHT: bold; COLOR: #000000">CHARACTER</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">50</span><span style="COLOR: #000000">),<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">CONSTRAINT</span><span style="COLOR: #000000">&nbsp;P_KEY_1&nbsp;</span><span style="COLOR: #0000ff">PRIMARY</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">KEY</span><span style="COLOR: #000000">&nbsp;(FD_YCLLRDZ_ID)<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>);</span></div>
&nbsp;&nbsp;&nbsp;&nbsp; 2、创建临时表, declare语句创建表的时候于create相同, 只不过declare创建的是临时表, 例如<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">Declare</span><span style="COLOR: #000000">&nbsp;GLOBAL&nbsp;</span><span style="COLOR: #0000ff">TEMPORARY</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">TABLE</span><span style="COLOR: #000000">&nbsp;session.temp1&nbsp;</span><span style="COLOR: #808080">like</span><span style="COLOR: #000000">&nbsp;employee&nbsp;</span><span style="COLOR: #0000ff">on</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">commit</span><span style="COLOR: #000000">&nbsp;PRESERVE&nbsp;ROWS&nbsp;</span><span style="COLOR: #808080">NOT</span><span style="COLOR: #000000">&nbsp;LOGGED&nbsp;</span><span style="COLOR: #808080">IN</span><span style="COLOR: #000000">&nbsp;mytempspace</span></div>
<p>这个语句用来声明一个临时表,表明为temp1, 位于现有的表空间mytempspace中(这个表空间必须存在), 和employee表结构一模一样, 每当处理commit语句时,临时表的行就会被保存下来(不会被删除), 最后对临时表的修改不用记入日志.&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; 3、ALter语句可以用来改变数据库中的一些特征, 比如[缓冲池(Buffer pool), 模式(Schema), 表(Table), 表空间(Table Space), 触发器(Trigger), 视图(View)], 注意: 不能修改索引, 如果想修改索引, 必须删除该索引后重新添加、例如: alter table t_ci_yclsqjhzb add column fd_sxygbh CHARACTER(20); 为修改表t_ci_yclsqjhzb, 添加一个字段fd_sxygbh。修改字段属性：alter table t_ci_yclsqjhzb alter column fd_sxygbh set datatype CHARACTER(50);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 4、Drop语句用来删除一些数据库特征, 比如包括[缓冲池(Buffer pool), 事件监视器(Event monitor), 函数(Function), 索引(Index), 模式(Schema), 存储过程(Stored procedure), 表(Table), 表空间(Table space), 触发器(Trigger), 视图(View)], 简单的例子 drop table temp, 就是删除表temp.</p>
<p>二、数据库操作语言(DML)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1、使用Select, 用于检索表或者视图中的数据、例子 select * from temp;<br>&nbsp;&nbsp;&nbsp;&nbsp; 2、使用Insert, 向表或者视图中添加一条数据, 例子 Insert into temp (字段1, 字段2, 字段3) values (值1, 值2, 值3);<br>&nbsp;&nbsp;&nbsp;&nbsp; 3、使用update, 修改表数据或者视图中数据、例子1: update temp set 字段1=值1, 字段2=值2 例子2: update temp set(字段1,字段2)=(值1,值2);<br>&nbsp;&nbsp;&nbsp;&nbsp; 4、使用delete, 删除表数据或者视图中的数据、例子 delete from temp<br>&nbsp;&nbsp;&nbsp;&nbsp; 5、表中数据非常多的时候，500万条以上，需要使用表分区来提高效率。</p>
<p>三、SQL工具</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1、内连接<br>&nbsp;&nbsp;&nbsp;&nbsp; 2、外连接(左连接, 右连接, 全连接).内连接时，返回查询结果集合中之仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件之行。而采用外连接时，它返回到查询结果集合中之不仅包含符合连接条件之行，而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中之所有数据行。 <br>&nbsp;&nbsp;&nbsp;&nbsp; 3、就DB2而言, 连接查询的效率要比子查询要高.<br>&nbsp;&nbsp;&nbsp;&nbsp; 4、Having和where的区别, 只有使用了group by的语句才能使用having.<br>&nbsp;&nbsp;&nbsp;&nbsp; 5、Case语句在sql 中的应用,例如: select 字段1, 字段2 CASR type when 'T' then 'TABLE' when 'V' then 'VIEW' else 'OTHERS' END from temp,相当于, select 字段1,字段2,table from temp where type = 'T' union all select 字段1,字段2,view from temp where type = 'V';<br>&nbsp;&nbsp;&nbsp;&nbsp; 6、合并查询Union.</p>
<p>四、SQL函数</p>
<p>1、列函数<br>&nbsp; 1.1 AVG函数, 平均值的函数.<br>&nbsp; 1.2 COUNT函数, 计算表中某列的行数.<br>&nbsp; 1.3 MAX函数, MIN函数, <br>&nbsp; 1.4 STDDEV函数, 返回一组数的标准方差, stddev函数的参数可以是任何数字型数据类型, 返回结果是双精度浮点型.<br>&nbsp; 1.5 SUM函数, 求和<br>&nbsp; 1.6 VARIANCE,返回一组数据的方差, VARIANCE函数的参数可以是任何数字型数据类型, 返回结果是双精度浮点型.<br>2、标量函数<br>&nbsp; 2.1 ABS 绝对值, HEX返回值的十六进制表示.<br>&nbsp; 2.2 LENGTH返回参数中的字节数长度.<br>&nbsp; 2.3 YEAR抽取参数中的年份.</p>
<p>五、DB2 UDB图形用户界面</p>
<p>1、配置助手, 指令: db2ca, 使用配置助手来配置和维护将要使用的数据库对象, 必须在db2上配置了将要存储的数据库后才能使用这些数据库.<br>2、控制中心, 指令: db2cc, 用户可以在对象窗格或者内容窗格中选中要操作的对象, 然后右键弹出快捷菜单, 然后通过快捷菜单的命令, 对该对象进行相应的操作.<br>3、命令编辑器, 指令: db2ce, 用户可以在命令编辑器中输入指令或者调用现成的命令脚本, 然后查看执行后的结果.<br>4、命令窗口, 指令: db2cmd, 用户可以在窗口中输入命令或调用现成的命令脚本, 然后执行, 并查看结果.<br>5、信息中心, 指令: db2ic, db2提供了丰富的信息, 几乎所有的信息都可以通过信息中心来获得.<br>6、开发中心, 指令: db2dc, 开发中心可以完成多种任务, 如创建项目, 添加数据库连接, 创建存储过程, 创建UDF等基本任务, 也可以完成更改环境设置.<br>7、健康中心, 指令: db2hc.<br>8、任务中心, 指令: db2tc, 可以创建一些命令脚本.<br>9、复制中心, 指令: db2rc, </p>
<p>六、DB2安全控制</p>
<p>1、验证，数据库安全性中最基本的概念之一就是验证，这是一个相当简单的过程，系统通过这个过程来证实用户身份。用户可以通过提供身份证明或验证令。来响应验证请求。<br>2、验证选项，dbm cfg authentication 参数的许多设置在逻辑上可以分组为以下四个不同类别：server（服务器）、client（客户机）、dce、kerberos。<br>3、server（服务器）缺省安全性机制，指明验证应该使用服务器的操作系统在服务器上发生。如果用户标识和密码是在连接期间指定的，那么 db2 将调用操作系统函数来验证提交的用户标识和密码。（在基于 windows 的环境中，用户标识常被称为用户名。用户名和密码合起来常被称为用户账户。） <br>4、client（客户机）验证。该组仅有的选项 client 指明验证将在客户机上发生。如果客户机驻留在原本就具有安全特性的操作系统（例如，aix）上，那么它就是可信任客户机。通常，除 microsoft windows 95 和 98 被认为不可信任之外，所有客户机都是可信任的。 </p>
<p>七、DB2备份恢复操作</p>
<p>1、整个备份，在控制中心，直接备份，这个备份包括表结构（描述、注释、数据库函数、触发器、存储过程...），恢复的时候也直接在控制中心点恢复库就可以了，这里要注意恢复的路径目录，日期等。<br>2、db2move方法，一般只用来备份表数据，如果没有表结构也会同时新建表，但是没有其他例如注释、触发器等等的恢复。备份的例子：db2move cjdbgq[tablename] export -u bscj[user] -p baosight[password]，这里也能备份单表。恢复的例子：db2move cjdbgq[tablename] import-u bscj[user] -p baosight[password]；这里需要注意操作的目录，应选择为Dos进入目录。<br>3、单表数据导出、导入，导出例子：export to c:\test\test.ixf of ixf select * from test；导入数据：import from c:\test\test.ixf of ixf insert into bscj.T_CI_ALERM；这里的import是添加的方式，所以在操作前需要delete from bscj.T_CI_ALERM，把已有数据清除。<br></p>
<img src ="http://www.blogjava.net/wealupa/aggbug/123778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2007-06-13 09:52 <a href="http://www.blogjava.net/wealupa/archive/2007/06/13/123778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate实践</title><link>http://www.blogjava.net/wealupa/archive/2007/01/18/94625.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Thu, 18 Jan 2007 06:20:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2007/01/18/94625.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/94625.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2007/01/18/94625.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/94625.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/94625.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 序在实际项目中使用Hibernate有两年多了，在两年多的实践过程中既体验到了Hibernate带来的N多好处，同时也碰到不少的问题，特写此篇文章做个总结，记录自己在Hibernate实践中的一些经验，希望对于新使用Hibernate的朋友能有个...&nbsp;&nbsp;<a href='http://www.blogjava.net/wealupa/archive/2007/01/18/94625.html'>阅读全文</a><img src ="http://www.blogjava.net/wealupa/aggbug/94625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2007-01-18 14:20 <a href="http://www.blogjava.net/wealupa/archive/2007/01/18/94625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库常见问题集锦</title><link>http://www.blogjava.net/wealupa/archive/2006/12/16/88269.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Sat, 16 Dec 2006 14:38:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2006/12/16/88269.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/88269.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2006/12/16/88269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/88269.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/88269.html</trackback:ping><description><![CDATA[<div class="subtable altbg2 t_msg" style="WIDTH: auto; HEIGHT: auto"><strong>1、几种Int型的区别</strong> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong><span style="COLOR: #0000cd">MIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAX<br></span></strong>TINYINT&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; 1&nbsp; &nbsp;&nbsp; &nbsp; -128&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 127&nbsp;&nbsp;<br>SMALLINT&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;2&nbsp; &nbsp;&nbsp; &nbsp; -32768&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32767&nbsp;&nbsp;<br>MEDIUMINT&nbsp; &nbsp;&nbsp; &nbsp;3&nbsp; &nbsp;&nbsp; &nbsp; -8388608&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8388607&nbsp;&nbsp;<br>INT&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp; &nbsp;&nbsp; &nbsp; -2147483648&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2147483647&nbsp;&nbsp;<br>BIGINT&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;8&nbsp; &nbsp;&nbsp; &nbsp; -9223372036854775808&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;9223372036854775807</div>
<img src ="http://www.blogjava.net/wealupa/aggbug/88269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2006-12-16 22:38 <a href="http://www.blogjava.net/wealupa/archive/2006/12/16/88269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的延迟加载问题</title><link>http://www.blogjava.net/wealupa/archive/2006/12/16/88266.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Sat, 16 Dec 2006 14:36:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2006/12/16/88266.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/88266.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2006/12/16/88266.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/88266.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/88266.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 众所周知,到了Hibernate3.0以后,关联关系的对象默认都是使用延迟加载,例如&lt;one-to-many&gt;时.但我在映射&lt;one-to-one&gt;,&lt;many-to-one&gt;关系时指定了lazy="true",但是在查询对象时,我只想查询一个对象,仍然会把这个对象所关联的&lt;one-to-one&gt;,&lt;many-to-one&gt;对象一起查询出来,这样造成了极大的性能浪费.在不指定lazy属性时,&lt;many-to-one&gt;所关联的对象反而会延迟加载,这让我大为困惑,还以为是Hibernate的bug.&nbsp;
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在网上查找资料,说在为了延迟加载&lt;one-to-one&gt;,&lt;many-to-one&gt;所关联的对象,需要设置被关联的对象&lt;class name="" lazy="true"&gt;,我也这样做了,但是仍然没有效果. </div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 仔细阅读了Hibernate的手册,才发现原来要延迟加载&lt;one-to-one&gt;,&lt;many-to-one&gt;所关联的对象时,除了要指定lazy="true"外,还需要运行期字节码增强,而我省去了这一步,所以延迟加载没有效果.同时还发现在默认情况下,&lt;one-to-one&gt;,&lt;many-to-one&gt;的lazy属性是"proxy"而不是"true"!因此如果直接采用lazy的默认值,是可以延迟加载的. </div>
<div><br><strong>总结一下: </strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-one&gt;默认的属性是lazy="proxy",此时默认是会延迟加载的.在指定了lazy="true"之后,必须要经过运行期字节码增加,延迟加载才有效果. </div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而&lt;one-to-one&gt;相对要复杂一点,延迟加载还要受到constrained属性的限制.constrained="false"时表明实体和被关联到的实体的约束不是强制的,即存在一个实体时,它通过&lt;one-to-one&gt;关联的实体可能存在,也可能不存在,这时在查询实体时,Hibernate总会发起一次查询检查&lt;one-to-one&gt;所关联的实体是否存在,而这时已经可以把one-to-one关联的实体查询出来了,因此在&lt;one-to-one&gt;关系中,如果constrained="false",总是会立即加载关联到的实体. </div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果当constrained="true",且lazy="proxy"(默认),是可以延迟加载的. </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果当constrained="true",且lazy="true"时,需要经过运行期字节码增加,延迟加载才会奏效.</div>
<div>&nbsp;</div>
<div><strong>Open Session In View</strong></div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用Open Session In View就有一个好处，就是当页面需要使用关联后的实体时才会去查找缓存中是否已经有所需要的对象实体了，如果有直接返回结果，如果没有才重新查询。</div>
<div>&nbsp;</div>
<div><strong>cache</strong></div>
<div><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong>cache就是Hibernate使用的缓存。如果你的数据是频繁更新的，比如银行系统，那么，你的数据做cache是不安全的，那么你的取数据的策略需要级别高一些，甚至是需要事务级的取缓存数据；如果你的数据是频繁读取，修改少的，我可以放心的缓存，不必设置过高的缓存并发控制级别，比如是论坛系统，那么你说的问题几乎不可能出现啊。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 两面性是有，但是我们根据场合，在合适的场合使用合适的一面，那就不ok了？我得问题讨论的前提是使用cache没有并发更新之类问题的前提下的，是指在使用cache时不需要考虑另一面性的前提下，这种情况下谈何两面性。</div>
<div><strong></strong>&nbsp;</div>
<div><strong>什么样的数据适合存放到第二级缓存中？</strong></div>
<div><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong>1、<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">很少被修改的数据</span></div>
<div><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;2、不是很重要的数据，允许出现偶尔并发的数据</span></div>
<div><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;3、不会被并发访问的数据</span></div>
<div><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;4、参考数据<br><br><strong>不适合存放到第二级缓存的数据？</strong><br>&nbsp;&nbsp; 1、经常被修改的数据</span></div>
<div><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;2、财务数据，绝对不允许出现并发</span></div>
<div><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;3、与其他应用共享的数据。</span></div>
<img src ="http://www.blogjava.net/wealupa/aggbug/88266.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2006-12-16 22:36 <a href="http://www.blogjava.net/wealupa/archive/2006/12/16/88266.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的数据缓存</title><link>http://www.blogjava.net/wealupa/archive/2006/12/16/88265.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Sat, 16 Dec 2006 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2006/12/16/88265.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/88265.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2006/12/16/88265.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/88265.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/88265.html</trackback:ping><description><![CDATA[一般而言，ORM的数据缓存应包含如下几个层次：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 事务级缓存（Transcation Layer Cache）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 应用级/进程级缓存（Application/Process Layer Cache）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 分布式缓存（Cluster Layer Cache）<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate数据缓存（Cache）分为两个层次，以Hibernate语义加以区分，可分为：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 内部缓存（Session Level，也称为一级缓存）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 二级缓存（SessionFactory Level，也称为二级缓存）<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate中，缓存将在以下情况中发挥作用：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 通过id[主键]加载数据时<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 延迟加载<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;内部缓存正常情况下由Hibernate自动维护，如果需要手动干预，可以通过以下方法完成：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Session.evict<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;将某个特定对象从内部缓存清除。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Session.clear<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;清空内部缓存。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Hibernate中，二级缓存涵盖了应用级缓存和分布式缓存领域。如果数据满足以下条件，则可将其纳入缓存管理。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 数据不会被第三方应用修改；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 数据大小(Data Size)在可接收的范围之内；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 数据更新频率较低；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. 同一数据可能会被系统频繁引用；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. 非关键数据(关键数据，如金融帐户数据)。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate本身并未提供二级缓存的产品化实现，而是为众多的第三方缓存组件提供了接入接口，较常用的第三方组件有：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. JCS<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. EHCache<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. OSCache<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. JBossCache<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. SwarmCache<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate中启用二级缓存，需要在hibernate.cfg.xml配置hibernate.cache.provider_class参数，之后，需要在映射文件中指定各个映射实体(以及collection)的缓存同步策略。Hibernate提供了一下4种内置的缓存同步策略：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. read-only<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;只读。对于不会发生改变的数据，可使用只读型缓存。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. nonstrict-read-write<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果程序对并发访问下的数据同步要求不是非常严格，且数据更新操作频率较低，可以采用本选项，获得较好的性能。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. read-write<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;严格可读写缓存。基于时间戳判定机制，实现了&#8220;read committed&#8221;事务隔离等级。可用于对数据同步要求严格的情况，但不支持分布式缓存。这也是实际应用中使用最多的同步策略。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. transactional<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;事务型缓存，必须运行在JTA事务环境中。 
<img src ="http://www.blogjava.net/wealupa/aggbug/88265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2006-12-16 22:35 <a href="http://www.blogjava.net/wealupa/archive/2006/12/16/88265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate二级缓存攻略</title><link>http://www.blogjava.net/wealupa/archive/2006/12/16/88264.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Sat, 16 Dec 2006 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2006/12/16/88264.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/88264.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2006/12/16/88264.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/88264.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/88264.html</trackback:ping><description><![CDATA[<p>很多人对二级缓存都不太了解，或者是有错误的认识，我一直想写一篇文章介绍一下hibernate的二级缓存的，今天终于忍不住了。 <br>我的经验主要来自hibernate2.1版本，基本原理和3.0、3.1是一样的，请原谅我的顽固不化。</p>
<p>hibernate的session提供了一级缓存，每个session，对同一个id进行两次load，不会发送两条sql给数据库，但是session关闭的时候，一级缓存就失效了。</p>
<p>二级缓存是SessionFactory级别的全局缓存，它底下可以使用不同的缓存类库，比如ehcache、oscache等，需要设置hibernate.cache.provider_class，我们这里用ehcache，在2.1中就是 <br>hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider <br>如果使用查询缓存，加上 <br>hibernate.cache.use_query_cache=true</p>
<p>缓存可以简单的看成一个Map，通过key在缓存里面找。</p>
<p><strong>Class的缓存</strong> <br>对于一条记录，也就是一个PO来说，是根据ID来找的，缓存的key就是ID，是POJO。无论list，load还是iterate，只要读出一个对象，都会填充缓存。但是list不会使用缓存，而iterate会先取数据库select id出来，然后一个id一个id的load，如果在缓存里面有，就从缓存取，没有的话就去数据库load。假设是读写缓存，需要设置： </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">usage</span> <span style="COLOR: #0000ff">="read-write"</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;</span> </div>
<p>如果你使用的二级缓存实现是ehcache的话，需要配置ehcache.xml </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">name</span> <span style="COLOR: #0000ff">="com.xxx.pojo.Foo"</span> <span style="COLOR: #ff0000">&nbsp;maxElementsInMemory</span> <span style="COLOR: #0000ff">="500"</span> <span style="COLOR: #ff0000">&nbsp;eternal</span> <span style="COLOR: #0000ff">="false"</span> <span style="COLOR: #ff0000">&nbsp;timeToLiveSeconds</span> <span style="COLOR: #0000ff">="7200"</span> <span style="COLOR: #ff0000">&nbsp;timeToIdleSeconds</span> <span style="COLOR: #0000ff">="3600"</span> <span style="COLOR: #ff0000">&nbsp;overflowToDisk</span> <span style="COLOR: #0000ff">="true"</span> <span style="COLOR: #ff0000">&nbsp;</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;</span> </div>
<p>其中eternal表示缓存是不是永远不超时，timeToLiveSeconds是缓存中每个元素（这里也就是一个POJO）的超时时间，如果eternal="false"，超过指定的时间，这个元素就被移走了。timeToIdleSeconds是发呆时间，是可选的。当往缓存里面put的元素超过500个时，如果overflowToDisk="true"，就会把缓存中的部分数据保存在硬盘上的临时文件里面。 <br>每个需要缓存的class都要这样配置。如果你没有配置，hibernate会在启动的时候警告你，然后使用defaultCache的配置，这样多个class会共享一个配置。 <br>当某个ID通过hibernate修改时，hibernate会知道，于是移除缓存。 <br>这样大家可能会想，同样的查询条件，第一次先list，第二次再iterate，就可以使用到缓存了。实际上这是很难的，因为你无法判断什么时候是第一次，而且每次查询的条件通常是不一样的，假如数据库里面有100条记录，id从1到100，第一次list的时候出了前50个id，第二次iterate的时候却查询到30至70号id，那么30-50是从缓存里面取的，51到70是从数据库取的，共发送1+20条sql。所以我一直认为iterate没有什么用，总是会有1+N的问题。 <br>（题外话：有说法说大型查询用list会把整个结果集装入内存，很慢，而iterate只select id比较好，但是大型查询总是要分页查的，谁也不会真的把整个结果集装进来，假如一页20条的话，iterate共需要执行21条语句，list虽然选择若干字段，比iterate第一条select id语句慢一些，但只有一条语句，不装入整个结果集hibernate还会根据数据库方言做优化，比如使用mysql的limit，整体看来应该还是list快。） <br>如果想要对list或者iterate查询的结果缓存，就要用到查询缓存了</p>
<p><strong>查询缓存</strong> <br>首先需要配置hibernate.cache.use_query_cache=true <br>如果用ehcache，配置ehcache.xml，注意hibernate3.0以后不是net.sf的包名了 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">name</span> <span style="COLOR: #0000ff">="net.sf.hibernate.cache.StandardQueryCache"</span> <span style="COLOR: #ff0000">&nbsp;<br></span><span style="COLOR: #008080">2</span> <span style="COLOR: #ff0000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>maxElementsInMemory</span> <span style="COLOR: #0000ff">="50"</span> <span style="COLOR: #ff0000">&nbsp;eternal</span> <span style="COLOR: #0000ff">="false"</span> <span style="COLOR: #ff0000">&nbsp;timeToIdleSeconds</span> <span style="COLOR: #0000ff">="3600"</span> <span style="COLOR: #ff0000">&nbsp;<br></span><span style="COLOR: #008080">3</span> <span style="COLOR: #ff0000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>timeToLiveSeconds</span> <span style="COLOR: #0000ff">="7200"</span> <span style="COLOR: #ff0000">&nbsp;overflowToDisk</span> <span style="COLOR: #0000ff">="true"</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">name</span> <span style="COLOR: #0000ff">="net.sf.hibernate.cache.UpdateTimestampsCache"</span> <span style="COLOR: #ff0000">&nbsp;<br></span><span style="COLOR: #008080">5</span> <span style="COLOR: #ff0000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>maxElementsInMemory</span> <span style="COLOR: #0000ff">="5000"</span> <span style="COLOR: #ff0000">&nbsp;eternal</span> <span style="COLOR: #0000ff">="true"</span> <span style="COLOR: #ff0000">&nbsp;overflowToDisk</span> <span style="COLOR: #0000ff">="true"</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;</span> </div>
<p>然后 <br>query.setCacheable(true);//激活查询缓存 <br>query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion，可选 <br>第二行指定要使用的cacheRegion是myCacheRegion，即你可以给每个查询缓存做一个单独的配置，使用setCacheRegion来做这个指定，需要在ehcache.xml里面配置它： </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">name</span> <span style="COLOR: #0000ff">="myCacheRegion"</span> <span style="COLOR: #ff0000">&nbsp;maxElementsInMemory</span> <span style="COLOR: #0000ff">="10"</span> <span style="COLOR: #ff0000">&nbsp;eternal</span> <span style="COLOR: #0000ff">="false"</span> <span style="COLOR: #ff0000">&nbsp;timeToIdleSeconds</span> <span style="COLOR: #0000ff">="3600"</span> <span style="COLOR: #ff0000">&nbsp;timeToLiveSeconds</span> <span style="COLOR: #0000ff">="7200"</span> <span style="COLOR: #ff0000">&nbsp;overflowToDisk</span> <span style="COLOR: #0000ff">="true"</span> <span style="COLOR: #ff0000">&nbsp;</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;</span> </div>
<p>如果省略第二行，不设置cacheRegion的话，那么会使用上面提到的标准查询缓存的配置，也就是net.sf.hibernate.cache.StandardQueryCache</p>
<p>对于查询缓存来说，缓存的key是根据hql生成的sql，再加上参数，分页等信息（可以通过日志输出看到，不过它的输出不是很可读，最好改一下它的代码）。 <br>比如hql： <br>from Cat c where c.name like ? <br>生成大致如下的sql： <br>select * from cat c where c.name like ? <br>参数是"tiger%"，那么查询缓存的key*大约*是这样的字符串（我是凭记忆写的，并不精确，不过看了也该明白了）： <br>select * from cat c where c.name like ? , parameter:tiger% <br>这样，保证了同样的查询、同样的参数等条件下具有一样的key。 <br>现在说说缓存的，如果是list方式的话，在这里并不是整个结果集，而是查询出来的这一串ID。也就是说，不管是list方法还是iterate方法，第一次查询的时候，它们的查询方式很它们平时的方式是一样的，list执行一条sql，iterate执行1+N条，多出来的行为是它们填充了缓存。但是到同样条件第二次查询的时候，就都和iterate的行为一样了，根据缓存的key去缓存里面查到了，是一串id，然后在到class的缓存里面去一个一个的load出来。这样做是为了节约内存。 <br>可以看出来，查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候，都是既填充查询缓存又填充class缓存的。 <br><strong>这里还有一个很容易被忽视的重要问题，即打开查询缓存以后，即使是list方法也可能遇到1+N的问题！</strong>相同条件第一次list的时候，因为查询缓存中找不到，不管class缓存是否存在数据，总是发送一条sql语句到数据库获取全部数据，然后填充查询缓存和class缓存。但是第二次执行的时候，问题就来了，如果你的class缓存的超时时间比较短，现在class缓存都超时了，但是查询缓存还在，那么list方法在获取id串以后，将会一个一个去数据库load！因此，class缓存的超时时间一定不能短于查询缓存设置的超时时间！如果还设置了发呆时间的话，保证class缓存的发呆时间也大于查询的缓存的生存时间。这里还有其他情况，比如class缓存被程序强制evict了，这种情况就请自己注意了。</p>
<p>另外，如果hql查询包含select字句，那么查询缓存里面的就是整个结果集了。</p>
<p>当hibernate更新数据库的时候，它怎么知道更新哪些查询缓存呢？ <br>hibernate在一个地方维护每个表的最后更新时间，其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。 <br>当通过hibernate更新的时候，hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表，当hibernate查询一个缓存是否存在的时候，如果缓存存在，它还要取出缓存的生成时间和这个缓存所查询的表，然后去查找这些表的最后更新时间，如果有一个表在生成时间后更新过了，那么这个缓存是无效的。 <br>可以看出，只要更新过一个表，那么凡是涉及到这个表的查询缓存就失效了，因此查询缓存的命中率可能会比较低。</p>
<p><strong>Collection缓存</strong> <br>需要在hbm的collection里面设置 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">usage</span> <span style="COLOR: #0000ff">="read-write"</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;</span> </div>
<p>假如class是Cat，collection叫children，那么ehcache里面配置 </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">&lt;</span> <span style="COLOR: #800000">cache&nbsp;</span> <span style="COLOR: #ff0000">name</span> <span style="COLOR: #0000ff">="com.xxx.pojo.Cat.children"</span> <span style="COLOR: #ff0000">&nbsp;<br></span><span style="COLOR: #008080">2</span> <span style="COLOR: #ff0000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>maxElementsInMemory</span> <span style="COLOR: #0000ff">="20"</span> <span style="COLOR: #ff0000">&nbsp;eternal</span> <span style="COLOR: #0000ff">="false"</span> <span style="COLOR: #ff0000">&nbsp;timeToIdleSeconds</span> <span style="COLOR: #0000ff">="3600"</span> <span style="COLOR: #ff0000">&nbsp;timeToLiveSeconds</span> <span style="COLOR: #0000ff">="7200"</span> <span style="COLOR: #ff0000">&nbsp;<br></span><span style="COLOR: #008080">3</span> <span style="COLOR: #ff0000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>overflowToDisk</span> <span style="COLOR: #0000ff">="true"</span> <span style="COLOR: #ff0000">&nbsp;</span> <span style="COLOR: #0000ff">/&gt;</span> <span style="COLOR: #000000">&nbsp;</span> </div>
<p>Collection的缓存和前面查询缓存的list一样，也是只保持一串id，但它不会因为这个表更新过就失效，一个collection缓存仅在这个collection里面的元素有增删时才失效。 <br>这样有一个问题，如果你的collection是根据某个字段排序的，当其中一个元素更新了该字段时，导致顺序改变时，collection缓存里面的顺序没有做更新。</p>
<p><strong>缓存策略</strong> <br>只读缓存（read-only）：没有什么好说的 <br>读/写缓存（read-write）:程序可能要的更新数据 <br>不严格的读/写缓存（nonstrict-read-write）：需要更新数据，但是两个事务更新同一条记录的可能性很小，性能比读写缓存好 <br>事务缓存（transactional）：缓存支持事务，发生异常的时候，缓存也能够回滚，只支持jta环境，这个我没有怎么研究过</p>
<p>读写缓存和不严格读写缓存在实现上的区别在于，读写缓存更新缓存的时候会把缓存里面的数据换成一个锁，其他事务如果去取相应的缓存数据，发现被锁住了，然后就直接取数据库查询。 <br>在hibernate2.1的ehcache实现中，如果锁住部分缓存的事务发生了异常，那么缓存会一直被锁住，直到60秒后超时。 <br>不严格读写缓存不锁定缓存中的数据。</p>
<p><strong>使用二级缓存的前置条件</strong> <br>你的hibernate程序对数据库有独占的写访问权，其他的进程更新了数据库，hibernate是不可能知道的。你操作数据库必需直接通过hibernate，如果你调用存储过程，或者自己使用jdbc更新数据库，hibernate也是不知道的。hibernate3.0的大批量更新和删除是不更新二级缓存的，但是据说3.1已经解决了这个问题。 <br>这个限制相当的棘手，有时候hibernate做批量更新、删除很慢，但是你却不能自己写jdbc来优化，很郁闷吧。 <br>SessionFactory也提供了移除缓存的方法，你一定要自己写一些JDBC的话，可以调用这些方法移除缓存，这些方法是： <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;evict(Class&nbsp;persistentClass)&nbsp;<br></span><span style="COLOR: #008080">&nbsp;2</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Evict&nbsp;all&nbsp;entries&nbsp;from&nbsp;the&nbsp;second</span> <span style="COLOR: #000000">-</span> <span style="COLOR: #000000">level&nbsp;cache.&nbsp;<br></span><span style="COLOR: #008080">&nbsp;3</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;evict(Class&nbsp;persistentClass,&nbsp;Serializable&nbsp;id)&nbsp;<br></span><span style="COLOR: #008080">&nbsp;4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Evict&nbsp;an&nbsp;entry&nbsp;from&nbsp;the&nbsp;second</span> <span style="COLOR: #000000">-</span> <span style="COLOR: #000000">level&nbsp;cache.&nbsp;<br></span><span style="COLOR: #008080">&nbsp;5</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;evictCollection(String&nbsp;roleName)&nbsp;<br></span><span style="COLOR: #008080">&nbsp;6</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Evict&nbsp;all&nbsp;entries&nbsp;from&nbsp;the&nbsp;second</span> <span style="COLOR: #000000">-</span> <span style="COLOR: #000000">level&nbsp;cache.&nbsp;<br></span><span style="COLOR: #008080">&nbsp;7</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;evictCollection(String&nbsp;roleName,&nbsp;Serializable&nbsp;id)&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Evict&nbsp;an&nbsp;entry&nbsp;from&nbsp;the&nbsp;second</span> <span style="COLOR: #000000">-</span> <span style="COLOR: #000000">level&nbsp;cache.&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;evictQueries()&nbsp;<br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Evict&nbsp;any&nbsp;query&nbsp;result&nbsp;sets&nbsp;cached&nbsp;in&nbsp;the&nbsp;</span> <span style="COLOR: #0000ff">default</span> <span style="COLOR: #000000">&nbsp;query&nbsp;cache&nbsp;region.&nbsp;<br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;evictQueries(String&nbsp;cacheRegion)&nbsp;<br></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Evict&nbsp;any&nbsp;query&nbsp;result&nbsp;sets&nbsp;cached&nbsp;in&nbsp;the&nbsp;named&nbsp;query&nbsp;cache&nbsp;region.&nbsp;</span> </div>
<p>不过我不建议这样做，因为这样很难维护。比如你现在用JDBC批量更新了某个表，有3个查询缓存会用到这个表，用evictQueries(String cacheRegion)移除了3个查询缓存，然后用evict(Class persistentClass)移除了class缓存，看上去好像完整了。不过哪天你添加了一个相关查询缓存，可能会忘记更新这里的移除代码。如果你的jdbc代码到处都是，在你添加一个查询缓存的时候，还知道其他什么地方也要做相应的改动吗？</p>
<p>----------------------------------------------------</p>
<p><strong>总结：</strong> <br>不要想当然的以为缓存一定能提高性能，仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的，不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用，可能会有1+N的问题。不当的使用还可能导致读出脏数据。 <br>如果受不了hibernate的诸多限制，那么还是自己在应用程序的层面上做缓存吧。 <br>在越高的层面上做缓存，效果就会越好。就好像尽管磁盘有缓存，数据库还是要实现自己的缓存，尽管数据库有缓存，咱们的应用程序还是要做缓存。因为底层的缓存它并不知道高层要用这些数据干什么，只能做的比较通用，而高层可以有针对性的实现缓存，所以在更高的级别上做缓存，效果也要好些吧。</p>
<img src ="http://www.blogjava.net/wealupa/aggbug/88264.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2006-12-16 22:35 <a href="http://www.blogjava.net/wealupa/archive/2006/12/16/88264.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的主键生成器generator在SQLServer中的使用</title><link>http://www.blogjava.net/wealupa/archive/2006/12/16/88251.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Sat, 16 Dec 2006 14:18:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2006/12/16/88251.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/88251.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2006/12/16/88251.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/88251.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/88251.html</trackback:ping><description><![CDATA[<strong>1、如果主键字段为自增类型，<br></strong>那么对应的.hbm.xml文件中的id字段的xml声明，<br>应该这么写：<br>&lt;generator class="native" /&gt;<br>例如：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">id<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #ff0000">column</span><span style="COLOR: #0000ff">="user_id"</span><span style="COLOR: #ff0000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>name</span><span style="COLOR: #0000ff">="Id"</span><span style="COLOR: #ff0000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>type</span><span style="COLOR: #0000ff">="integer"</span><span style="COLOR: #ff0000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">generator&nbsp;</span><span style="COLOR: #ff0000">class</span><span style="COLOR: #0000ff">="native"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">id</span><span style="COLOR: #0000ff">&gt;</span></div>
<br>其实这个native并非实际的类型，而是hiberante根据<br>当前使用的数据库，自动使用对应的类型。<br>例如：如果sqlserver，native就对应identity<br>见Hiberante参考：<br>native（本地）<br>根据底层数据库的能力选择identity, sequence 或者hilo中的一个。 <br><br><strong>2、如果主键字段不设置为自增，但是是int型的，</strong><br>可以使用increment，由hibernate产生主键。<br>&lt;generator class="increment" /&gt;<br>不过这种方法，对于并发量大的应用，似乎最好不要采用。<br>见hiberante参考：<br>increment（递增）<br>用于为long, short或者int类型生成唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 <br><br>在集群下不要使用。 <br><br><strong>3、如果使用uuid.hex产生的随机32位数最为主键，</strong><br>那么数据库的id字段类型为char，长度为32<br>hbm.xml中写为： &lt;generator class="uuid.hex" /&gt;<br>另外，uuid.string也是功能类似。<br>uuid.hex产生的是32位的16进制数字的字符串。<br>而uuid.string产生的是16个字符长的任意ASCII字符组成的字符串<br>见参考：<br>uuid.hex<br>用一个128-bit的UUID算法生成字符串类型的标识符。在一个网络中唯一（使用了IP地址）。UUID被编<br><br>码为一个32位16进制数字的字符串。 <br><br>uuid.string<br>使用同样的UUID算法。UUID被编码为一个16个字符长的任意ASCII字符组成的字符串。不能使用<br><br>在PostgreSQL数据库中 
<img src ="http://www.blogjava.net/wealupa/aggbug/88251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2006-12-16 22:18 <a href="http://www.blogjava.net/wealupa/archive/2006/12/16/88251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库主键设计之思考</title><link>http://www.blogjava.net/wealupa/archive/2006/12/16/88250.html</link><dc:creator>常言笑</dc:creator><author>常言笑</author><pubDate>Sat, 16 Dec 2006 14:16:00 GMT</pubDate><guid>http://www.blogjava.net/wealupa/archive/2006/12/16/88250.html</guid><wfw:comment>http://www.blogjava.net/wealupa/comments/88250.html</wfw:comment><comments>http://www.blogjava.net/wealupa/archive/2006/12/16/88250.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wealupa/comments/commentRss/88250.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wealupa/services/trackbacks/88250.html</trackback:ping><description><![CDATA[<div><span style="FONT-SIZE: 10pt"><strong>主键的必要性: <br></strong>　&nbsp;&nbsp; 有些朋友可能不提倡数据库表必须要主键，但在我的思考中，觉得每个表都应该具有主键，不管是单主键还是双主键，主键的存在就代表着表结构的完整性，表的记录必须得有唯一区分的字段，主键主要是用于其他表的外键关联，本记录的修改与删除，当我们没有主键时，这些操作会变的非常麻烦。 </span></div>
<span style="FONT-SIZE: 10pt">
<div><br><strong>主键的无意义性：<br></strong>　&nbsp;&nbsp; 我强调主键不应该具有实际的意义，这可能对于一些朋友来说不太认同，比如订单表吧，会有&#8220;订单编号&#8221;字段，而这个字段呢在业务实际中本身就是应该具有唯一性，具有唯一标识记录的功能，但我是不推荐采用订单编号字段作为主键的，因为具有实际意义的字段，具有&#8220;意义更改&#8221;的可能性，比如订单编号在刚开始的时候我们一切顺利，后来客户说&#8220;订单可以作废，并重新生成订单，而且订单号要保持原订单号一致&#8221;，这样原来的主键就面临危险了。因此，具有唯一性的实际字段也代表可以作为主键。因此，我推荐是新设一个字段专门用为主键，此主键本身在业务逻辑上不体现，不具有实际意义。而这种主键在一定程序增加了复杂度，所以要视实际系统的规模大小而定，对于小项目，以后扩展不会很大的话，也查允许用实际唯一的字段作主键的。 </div>
<div><br><strong>主键的选择：</strong> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们现在在思考一下，应该采用什么来作表的主键比较合理，申明一下，主键的设计没有一个定论，各人有各人的方法，哪怕同一个，在不同的项目中，也会采用不同的主键设计原则。</div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>第一：编号作主键 </strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此方法就是采用实际业务中的唯一字段的&#8220;编号&#8221;作为主键设计，这在小型的项目中是推荐这样做的，因为这可以使项目比较简单化，但在使用中却可能带来一些麻烦，比如要进行&#8220;编号修改&#8221;时，可能要涉及到很多相关联的其他表，就象黎叔说的&#8220;后果很严重&#8221;;还有就是上面提到的&#8220;业务要求允许编号重复时&#8221;，我们再那么先知，都无法知道业务将会修改成什么? </div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>第二：自动编号主键</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这种方法也是很多朋友在使用的，就是新建一个ID字段，自动增长，非常方便也满足主键的原则。</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>优点是：</strong>数据库自动编号，速度快，而且是增量增长，聚集型主键按顺序存放，对于检索非常有利;数字型的，占用空间小，易排序，在程序中传递也方便;如果通过非系统增加记录（比如手动录入，或是用其他工具直接在表里插入新记录，或老系统数据导入）时，非常方便，不用担心主键重复问题。 </div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>缺点：</strong>其实缺点也就是来自其优点，就是因为自动增长，在手动要插入指定ID的记录时会显得麻烦，尤其是当系统与其他系统集成时，需要数据导入时，很难保证原系统的ID不发生主键冲突（前提是老系统也是数字型的）;如果其他系统主键不是数字型那就麻烦更大了，会导致修改主键数据类型了，这也会导致其他相关表的修改，后果同样很严重;就算其他系统也是数字型的，在导入时，为了区分新老数据，可能想在老数据主键前统一加一个&#8220;o&#8221;(old)来表示这是老数据，那么自动增长的数字型又面临一个挑战。</div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>第三：Max加一 <br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于自动编号存在那些问题，所以有些朋友就采用自己生成，同样是数字型的，只是把自动增长去掉了，采用在Insert时，读取Max值后加一，这种方法可以避免自动编号的问题，但也存在一个效率问题，如果记录非常大的话，那么Max()也会影响效率的;更严重的是并发性问题，如果同时有两人读到相同的Max后，加一后插入的ID值会重复，这已经是有经验教训的了。 </div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>第四：自制加一</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 考虑Max加一的效率后，有人采用自制加一，也就是建一个特别的表，字段为：表名，当前序列值。这样在往表中插入值时，先从此表中找到相应表的最大值后加一，进行插入，有人可能发现，也可能会存在并发处理，这个并发处理，我们可以采用lock线程的方式来避免，在生成此值的时，先Lock，取到值以后，再unLock出来，这样不会有两人同时生成了。这比Max加一的速度要快多了。但同样存在一个问题：在与其他系统集成时，脱离了系统中的生成方法后，很麻烦保证自制表中的最大值与导入后的保持一致，而且数字型都存在上面讲到的&#8220;o&#8221;老数据的导入问题。因此在&#8220;自制加一&#8221;中可以把主键设为字符型的。字符型的自制加一我倒是蛮推荐的，应该字符型主键可以应付很多我们意想不到的情况。</div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>第五：GUID主键</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目前一个比较好的主键是采用GUID，当然我是推荐主键还是字符型的，但值由GUID生成，GUID是可以自动生成，也可以程序生成，而且键值不可能重复，可以解决系统集成问题，几个系统的GUID值导到一起时，也不会发生重复，就算有&#8220;o&#8221;老数据也可以区分，而且效率很高，在.NET里可以直接使用System.Guid.NewGuid()进行生成，在SQL里也可以使用 NewID()生成。</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>优点是：</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同 IDENTITY 列相比，uniqueidentifier 列可以通过 NewID() 函数提前得知新增加的行 ID，为应用程序的后续处理提供了很大方便。便于数据库移植，其它数据库中并不一定具有 IDENTITY 列，而 Guid 列可以作为字符型列转换到其它数据库中，同时将应用程序中产生的 GUID 值存入数据库，它不会对原有数据带来影响。&nbsp;便于数据库初始化，如果应用程序要加载一些初始数据， IDENTITY 列的处理方式就比较麻烦，而 uniqueidentifier 列则无需任何处理，直接用 T-SQL 加载即可。 便于对某些对象或常量进行永久标识，如类的 ClassID，对象的实例标识，UDDI 中的联系人、服务接口、tModel标识定义等。 </div>
<div><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong> 缺点是：</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GUID 值较长，不容易记忆和输入，而且这个值是随机、无顺序的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GUID 的值有 16 个字节，与其它那些诸如 4 字节的整数相比要相对大一些。这意味着如果在数据库中使用 uniqueidentifier 键，可能会带来两方面的消极影响：存储空间增大；索引时间较慢。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我也不是推荐GUID最好，其实在不同的情况，我们都可以采用上面的某一种方式，思考了一些利与弊，也方便大家在进行设计时参考。这些也只是我的一点思考而已，而且可能我知识面限制，会有一些误论在里面，希望大家有什么想法欢迎讨论。</div>
</span>
<img src ="http://www.blogjava.net/wealupa/aggbug/88250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wealupa/" target="_blank">常言笑</a> 2006-12-16 22:16 <a href="http://www.blogjava.net/wealupa/archive/2006/12/16/88250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>