??xml version="1.0" encoding="utf-8" standalone="yes"?>成视频在线免费观看,色婷婷av在线,亚洲一区色图http://www.aygfsteel.com/weibogao/my second lifespacezh-cnThu, 19 Jun 2025 05:43:57 GMTThu, 19 Jun 2025 05:43:57 GMT60常用的算法网站汇?/title><link>http://www.aygfsteel.com/weibogao/archive/2010/03/04/314514.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 04 Mar 2010 06:21:00 GMT</pubDate><guid>http://www.aygfsteel.com/weibogao/archive/2010/03/04/314514.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/314514.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2010/03/04/314514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/314514.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/314514.html</trackback:ping><description><![CDATA[1.http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/AlgorithmGossip.htmQ包括cQjava{的不同实现Q基l习很有用)<br /> 2.http://www.javaeye.com/forums/tag/algorithmQ专业java|站上的论坛Q很不错Q?br /> 3.待箋。。。。。?br /> <img src ="http://www.aygfsteel.com/weibogao/aggbug/314514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2010-03-04 14:21 <a href="http://www.aygfsteel.com/weibogao/archive/2010/03/04/314514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用CVS来管理自qE序http://www.aygfsteel.com/weibogao/archive/2007/01/16/94195.htmlweibogaoweibogaoTue, 16 Jan 2007 04:49:00 GMThttp://www.aygfsteel.com/weibogao/archive/2007/01/16/94195.htmlhttp://www.aygfsteel.com/weibogao/comments/94195.htmlhttp://www.aygfsteel.com/weibogao/archive/2007/01/16/94195.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/94195.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/94195.html http://51cmm.csai.cn/casepanel/CM/No047.htm

每个~写E序的h也许都有q这L体验Q对~写的程序作了一些修改,几天以后Q我们可能发Cơ的修改D了其它的矛盾Q甚至编译不能通过Q但q时我们却很难找到自己刚在哪里作了改动。一般说来,我们L希望自己完整的记录下一个程序开发的q程Q记录下q个E序的每一Ҏq和调整。或许我们可以用备䆾的方法来解决q个问题Q于是我们徏立一个backup的目录,定期或不定期的将自己的源E序打包放进去,直到某一天整个硬盘都被这些文件撑满。这当然有些夸张Q但q种机制带给我们的不方便是显而易见的。更q一步,现在一个Y件品的开发,一个h单枪匚w很难完成。可能是包含几个、几十个乃至上百个程序员协作开发,q时的源代码又该如何理Q解决问题的Ҏ是使用CVS?
  CVS - Concurrent Versions System(q发版本理pȝ)是一个版本控制管理系l,它是目前最为广泛用的一个系l。从gftp到gtk到KDEQ你几乎可以在每一个你熟悉的自pY件的源码里看到它的踪q?下面我们会知道,它的t迹指一个称为cvs的子目录)。同P你也可以在几乎每一个Linux的发行版本里看到CVSpȝ。可以说Q如果失MCVSQ现有的许多多h协作、自由开发的软g都会在一定程度上放慢自己发展的步伐?  CVS到底有哪些功能,使得它有如此强大的魅力呢Q?br />  1.CVS能做什么?
   如上所_CVS首先是一个版本管理系l,它可以保留Y件开发过E中的每一个版本的信息Q包括谁、在何时、作了什么样的修改以及ؓ什么作q样的修改等。这个功能和以前行于Linux和Unix的版本管理系lRCS(Revision Control System)和SCCS(Source Code Control System)很象。但CVS的功能远非仅此。它的最大的特点是它的ƈ发性,卛_支持分布式项目的开发。在互联|席卷一切的今天Q这个功能太为重要了。小C个办公室内部开发一个OApȝQ大到KDE组利用互联|开发新版本的KDEQCVS都可以一展n手。一个程序员开发出了自p责模块的新版本后Q迅速的通过CVS让开发组的每一个成员都分n自己的最新成果。甚臻ICVS通过特定的机制允许多个程序员同时修改同一个源E序文g?br />  另外CVS增强的目录结构以及对二进制文件良好的处理Q都使得它远q优于其它的版本理pȝ。最后,必须一提的是CVS是基于RCS开发而成的?br />  2.如何得到CVS?
   CVS在几乎包含在所有的Linux发布版本中,如RedHat、Turbo Linux、Slackware以及国的红旗、Xteam Linux{。你可以试着敲一下cvs命oQ大多数情况下都会出CUsage: cvs开头的一堆信息,提示你如何用cvsQ这意味着在你的机器上早已有了CVSQ只是遗憄是它一直未被你发现和利用。运气不好的话,你会看到形如cvs: Command not found.的提C,q意味着你的机器没有安装CVS。这时你有两U选择。一是找C的Linux安装盘,从那里安装CVS。例如在使用RPM方式安装的Linux(上面介绍的几个发布版本中g除了SlackwareQ其他都?发布版本中,扑ֈcvs***.rpmQ用rpm命oq行安装。第二种方式是到一些站点cvs的源代码Q然后遵循里面附带的指导q行安装Q需要的读者请讉K站点www.cyclic.com/或者http://www.loria.fr/~molli/cvs-index.html?br />  3.CVS的基本用方?br />   在这一节里Q我们来学习掌握CVS的一些基本用方法。现在我们假定已l安装好了CVSQƈ且我们打用它来理自己正在开发的一个YӞ软g名叫netantsQ它存放在硬盘上一个叫做netants的目录里Q目前里面有了文件netants.c、netants.h、http.c、http.h和Makefile。我们ƈ没有和它人协作开发这个YӞ也没有利用Internet或者Intranet来开发这个Y件。或许,它只是自q一个业余作品,试图写出一个比Windows下的|络蚂蚁更好的下载工具出来?br />  3.1初始化CVS 
  我们首先要用的命o是cvs initQ这个命令用来初始化CVSpȝ。正如我们所看到的,所有的CVS命o都以cvs开_然后在后面紧跟命令、参数和一些选项。初始化CVSpȝ主要是ؓ了创Z个ؓCVS所使用的源码储存库(repository)。创建的时候,需要指定在那个目录下创个源码储存库。有两种Ҏ来指定目录。一是利?-d "选项来指定,例如Q?d /usr/local/cvsroot。另一U更方便的方法是在shell里设定一个名叫CVSROOT的环境变量。用csh或者tcsh的用户可以用命令setenv来设定,在文?csh rc或者文?tcshrc里添加入下的一行: setenv CVSROOT /usr/local/cvsroot 使用sh或者bash的用户需要在文g.profile或者文?bashrc里添加如下两行: CVSROOT=/usr/local/cvsroot export CVSROOT 讄了环境变量CVSROOT后,我们q行命ocvs initQCVS在指定的目录下面徏立自己所需要的一些文Ӟ以后我们使用CVS理的Q何项目,都会被CVS储存在这个目录之下。不q千万要注意的是Q永q不要去试图修改q个目录下的文g。这个目录是由CVS自己q行理的,ȝ的改动可能会D你丢׃部分或全部的交由CVS理的源代码或其他资源?br />  3.2导入目到CVS中去
  初始化结束以后,我们p真正开始利用CVS来管理自qE序|络蚂蚁了。第一步,我们这个项目交由CVS理。用如下的CVS的import命oQ将源程序导入到CVS的源码储存库中去Q cd netants cvs import -m "start my project: Netants" netants yoyo start q个命o看v来有些复杂,需要解释一下。import是cvs的导入命令,默认状况下,它@环的当前目录下的所有文?包括子目?导入到源码库(即CVSROOT指定的目?里去?m "start my project: Netants"告诉CVS你对q一步操作的说明。这是CVS强制要求的,如果你没有用这U?m "字符?的选项QCVS会弹出一个文本编辑器(如果自己不特别指定的话,在Linux下一般是viQ而在Windows下则是Notepad)Q让你输入一些说明信息它才Ş休。netants是这个项目被CVS存储时的路径名,即CVS在创徏一?CVSROOT/netants的目录,q在此目录下存放此项目的文gQ当Ӟ它不是原不动的存储QCVS会做一番处理。最后两个字W串讑֮了两个标?tag)Q现在ƈ没有什么用处,但它们同hCVS指定必需的,所以我们添上这两个参数。执行此命oӞCVS自动所有的文g版本设ؓ1.1Q这是它所认ؓ的最低版本。以下ؓ执行上述命o后的昄信息QN netants/netants.c N netants/http.c N netants/http.h N netants/netants.h N netants/Makefile No conflicts created by this import N表示NewQCVS成功的加载了q些文gQƈ没有发现冲突。 上面的命令稍长了一些,而且昑־有些J琐Q相信我QCVS不Lq样的,q点"J琐"相对它给我们带来的便利是完全可以忽略不计的?br />  3.3从CVS中导出项目 
  好了Q我们把自己的netants的项目交l了CVSȝ理,现在Q我们完全可以删除原有的存储我们代码的netants目录(当然Q安全v见,你或许应该再做一ơ备份,q希望是最后一?。我们要q行开发工作了Q徏一个目录,叫什么呢Q就叫worktmp吧。我们进到此目录下,执行命ocvs checkout netantsQ我们将会看到如下的信息Qcvs checkout: Updating netants U netants/Makefile U netants/http.c U netants/http.h U netants/netants.c U netants/netants.h CVS在当前目录下建立一个叫做netants的目录,我们原先的代码文仉在这个目录下出现了,而且q多了一个名为CVS的目录。目录CVS下面存放的是一些文本文Ӟ记录了CVSROOT的位|、此目对应源码库中那个目录{一些信息?br />  3.4保存修改到CVS?br />   现在Q我们开始艰苦卓的~程工作。经q数十分钟、数时乃至数天的工作,我们对原有的代码做了较大的修改,现在要告一D落了。我们将修改的内Ҏ交给CVSQ于是,我们需要执行命令 cvs commit -m "Made some useful changes on some files" q时Q我们将会看到CVSl出一些提CZ息,它扫描ƈ比较此目录下的现有文件和它在源码库中保存的原有文Ӟ做了修改的文件将被更斎ͼq且有了新的版本P1.2?m参数如同前面所_是ؓ了不惛_启动一个文本编辑器来让自己输入。如果我们仅是修改了其中一两个文gQ我们可以在上面的命令的最后附上文件名Q这样CVS只会比较、更新指定的文g。注意的是,和自己做备䆾不同QCVS只是保存了不同版本之间的差异Qƈ没有完整的保存各个版本。现在,你是不是觉得CVS有点用处了?br />  3.5d文g到项目中
  有一天,我们开始考虑l我们的|络蚂蚁加上从ftp站点下蝲文g的功能,于是Q我们需要在原有的项目里d两个文gQftp.c和ftp.h。首先,我们在工作目录下建立q编辑、修攏V生成了q两个文Ӟ然后我们使用命oadd命o来添加。 cvs add ftp.c ftp.h 此时Q文件ƈ没有真正的被dQ只是相当于"注册"了一下,要ɘq个q程生效Q我们仍焉要用commit命oQ cvs commit ftp.c ftp.h -m "Add two files: ftp.c and ftp.h" 此时QCVS把q两个文件添加到目中去Q他们的版本均ؓ初始?.1。  3.6从项目中删除文g
  除了d以外Q我们有的时候可能需要删除某个文Ӟ例如我们发现文gnetants.h其实没有什么用。于是,我们执行下面几个命o来完成删除工作: rm netants.h cvs remove netants.h cvs commit netants.h -m "Delete a file." 要注意的是,CVS只是删除了当前版本的netants.hQ它以前的版本依然存在,除非它恰好仅?.1版本?br />  3.7讑֮特定版本受
  l过一D|间的工作Q程序已l初兯模,形成了较E_的版本。这个时候,netants.c可能已经?.4版本Q而http.c可能?.5版本Q而我们希望将当前的代码作一个版本发布。此Ӟ我们需要用的是tag命o。这个命令赋予指定的一个或多个文g一个给定的文本形式的版本号。版本号必须以字母开始,可以包含数字、下划线和连接符?-)。我们想l当前项目的所有文件赋予相同的版本hQ可以不指定文g或\径参敎ͼCVS默认选择当前目录下所有在CVS中注册的文g(循环q子目录)。下面既是一个例子: 键入命oQcvs tag release0-1 提示信息Q    cvs tag: Tagging .    T Makefile    T ftp.c    T ftp.h    T http.c    T http.h    T netants.c q样当前版本的所有文仉有了一个叫做release0-1的版本代受当我们需要这个版本的时候,我们使用-r (版本代号)参数来得到指定的版本。例如命令: cvs checkout -r release0-1 netants 在当前目录下徏立netants目录Qƈ导出所有版本代号ؓrelease0-1的文件?br />  3.8更新当前工作目录中的文g
   q里使用的命令ؓupdateQ它比较指定的在CVS源码库中的文件和当前目录下的文gQ如果CVS源码库中有更高版本的源文Ӟ则更新当前目录下的文件。这个功能主要是多h协作开发项目时使用的,让你及时分n同伴的工作成果。但它另外一个重要的用途,同样适用于单人开发的目。这个用途需要?j参数Q我们看下面的例子: cvs update -j 1.5 -j 1.3 netants.c q个命o的功能是Q在当前目录的netants.c文g中,忽略从版?.3到版?.5所作的修改。毫无疑问,对程序员来说Q这是一个非帔R要的功能。因为在某个阶段我们对程序所作的修改在现在可能会被视为是无效乃至错误的,q个功能很好的解决了q个问题。 在更新的q程中,CVS执行一个自动合q的q程。例如我们的工作目录中的netants.c文g版本?.1Qƈ且我们已l对此文件作了一番修改,而CVS源码库中的是版本2.2Q此时我们执行update命oӞCVSq不是简单的版?.2覆盖版本2.1Q而是试图自版本2.1到版?.2的修Ҏ加到当前目录中的文g中去Q如果它和我们刚刚所作的修改有冲H,则CVS会以字符?>>>>"表示由冲H发生,期待用户M攏VCVS拒绝接受包含有上q特定字W串的文件。下面即是一个冲H的例子Qnetants.c:版本?.2Q保存在CVS中……getPartFile( ); showFinished(); return(A); }…?br />  netants:版本?.1l过我们的修改……getPartFile( ); return(B); }……我们执行命令cvs update netants.c后,会包含如下内容的新的netants.cQ?br />  ……getPartFile( ); showFinished(); >>>>>> 2.2 }…… 除非我们做出修改q删?>>>>>>"Q否则在执行cvs commit的时候,netants.c不会更新原有的2.2版本?br />  4.CVS的其他功?br />  CVS当然q不止上面所说的q些内容Q这些仅是CVS的基本功能,CVSq有许多重要的功能,如上面所说的|络工作方式、支持二q制文g{。下面我们对q些功能作简单的说明?br />  4.1 CVS的网l工作方式 
  CVS的网l功能采用client-serverl构Q两地均需安装CVS。CVS采用rsh方式或者口令校验方式进行工作。对client端,同前面讲q的讄环境变量CVSROOT一P用户需要设|新的环境变量CVS_SERVERQ指明CVS在server上的路径Q例如:/usr/local/cvsroot1。CVS?d参数指定路径名,它后面可以用Q?local或server或ext)Q来指明是在本地q是在异地服务器上,默认当然是在本地Q正如我们在初始化CVS一节所使用的那栗下面的命o假定我们的CVS服务器ؓcvs.rdcps.ac.cnQ用户名为crazyyaoQCVS源码库在服务器的/usr/local/cvsroot1目录下,我们的工作项目还是netantsQ我们用rsh方式导出目文gQ cvs -d : server : crazyyao@cvs.rdcps.ac.cn :/usr/local/cvsroot1 checkout netants 采用口o校验方式Ӟ需要对修改pȝ文g/etc/inetd.confQ以便inetd知道如何分配、处理CVS Server的请求和响应。CVS会在源码库所在的目录中创Z个名为passwd的口令文Ӟ对用戯行校验。用口令校验时QCVS支持匿名登陆Q而且CVS目用户可以讄目中文件的存取权限。 关于如何配置CVS使之工作在网l方式下的详l信息请参考CVS的文档?br />  4.2 CVS的分支和融合功能
   CVS增强的目录工作方式得CVS提供分支和融合功能。有的时候,当项目进展到一定程度时Q可能需要暂时中断,d另外一些修改和发展。例如,我们的Y件原有版本ؓ1.0Qƈ已提交用户用,现在正在开?.0。某一天,1.0的用户发C一个较大的bug或者需要添加某个短的功能Q这时我们不能让用户L?.0版本Q又必须l用h意的{复Q比较理想的解决方式是把现在的工作先攑ֈ一边,另开一个分支,L用L需要。当此分支完成后Q程序源q可以用CVS的融合功能将q一部分修改d到我们开?.0版本的主工作q程中去。 创徏分支可以使用tag -b命o。例如下面的命o   cvs tag -b netants-1-0-patch 在当前的工作目录的基上创Z个叫做netant-1-0-patch的分支。 融合的命令参数是-jQ我们在前面已经提及它了?br />  4.3 CVS处理二进制文件的功能 
  CVS可以保存二进制文Ӟ但和文本文g相比Q它的许多功能׃。对于文本文ӞCVS可以辨别出文件的M一Ҏ动,但对于二q制文g它无能ؓ力。但是,CVS可以区分出文件作了改动,q会提示用户自己修改、保存。与文本文g不同QCVS保存二进制文件每个版本的完整信息。在操作二进制文件时Q需要添加参?KBQ以便告诉CVS不把它当作文本文件看待?br />  4.4 CVS比较文g的功能 
  执行的命令ؓdiffQ这个功能和shell下的diff功能基本一栗例如下面的命o比较CVS源码库中的最新的netants.c文g和当前目录下netants.c文g有什么不同: cvs diff netatns.c
  5.l束?br />  通过上面的介l,希望能激起大家用CVS的兴,q掌握用CVS的一些基本方法。碰到困难时Q别忘了阅CVS附带的手册,不过Q它有厚厚的172c希望CVS能加速你的Y件开发?/p>


weibogao 2007-01-16 12:49 发表评论
]]>
WinCVS与CVSNT明用手??http://www.aygfsteel.com/weibogao/archive/2007/01/16/94192.htmlweibogaoweibogaoTue, 16 Jan 2007 04:43:00 GMThttp://www.aygfsteel.com/weibogao/archive/2007/01/16/94192.htmlhttp://www.aygfsteel.com/weibogao/comments/94192.htmlhttp://www.aygfsteel.com/weibogao/archive/2007/01/16/94192.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/94192.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/94192.html阅读全文

weibogao 2007-01-16 12:43 发表评论
]]>
WinCVS与CVSNT明用手?一)http://www.aygfsteel.com/weibogao/archive/2007/01/16/94191.htmlweibogaoweibogaoTue, 16 Jan 2007 04:42:00 GMThttp://www.aygfsteel.com/weibogao/archive/2007/01/16/94191.htmlhttp://www.aygfsteel.com/weibogao/comments/94191.htmlhttp://www.aygfsteel.com/weibogao/archive/2007/01/16/94191.html#Feedback3http://www.aygfsteel.com/weibogao/comments/commentRss/94191.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/94191.html阅读全文

weibogao 2007-01-16 12:42 发表评论
]]>
《CVSNT用户理Ҏ》{?/title><link>http://www.aygfsteel.com/weibogao/archive/2007/01/16/94190.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Tue, 16 Jan 2007 04:38:00 GMT</pubDate><guid>http://www.aygfsteel.com/weibogao/archive/2007/01/16/94190.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/94190.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2007/01/16/94190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/94190.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/94190.html</trackback:ping><description><![CDATA[ <font color="#333333"> <font face="宋体">   所有这些操作基于的环境和Y件版本:WINDOWS2000 Pro、CVSNT2.0.4、WinCVS1.3.9.1Beta9 在前面的介绍CVSNT配合WinCVSq行用户理的文章中Q已l对CVSNT的用L理,权限分配q行了比较详l的叙述Q但是还有一些概忉|有交待清楚,在这里,我会Ҏ目的实际需要,以及自己的一些经验给Z套用L理、权限管理方案,在看q篇文章之前你最好已l阅M前面的一文章,对用L增加删除Q权限的修改Q等{这些操作能够了解,否则Q会有一点困难?br /><b><span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  1?CVSNT的用户验证方?/span></b></font> </font> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br /> </span> </b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  我们q里所讨论的是工作在pserver方式下?br />  在CVSNT的文档中l出了两U验证方式,我ȝ了一下,可以q样U呼QWindow和CVSNT混合验证方式QCVSNT独立验证方式。在前面的文章中Q我们没有详l的l出q两U方式的内容Q所讲述的启C就是؜合验证方式?br />  军_CVSNT工作于何U验证方式是由CVS的管理文件来军_的,q些理文g处在库的目录下的CVSROOT目录中,q里可以得出l论Q对于不同的库,可以l不同的验证方式。所以,在每个库建立的时候要首先讑֮好这些前提?br />  下面的操作如果没有特D指出则都是在客L来进行管理的Q下面首先是对一些控制原理和相关的文件做一些说明,如果你正在进行相关的模拟操作Q请停下来暂时停止你的操作,因ؓq些操作的步骤是有先后的Q如果你序不对Q那么你可能权限失效,q行不了下面的操作了?br /></span> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  1Q? config文g</span> </b> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br /> </span> </b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  在库建立好了以后Q你q没有对控制文gq行修改之前QCVSNT是工作在混合验证方式之下的,q个时候,CVS服务器的理员就是CVSNT的管理员Q你以一个管理员w䆾登陆Q检Z要操作的库的CVSROOT模块Q看一下文件列表,控制CVSNT的验证工作方式的是config文gQ你可以在文件列表中扑ֈ它,双击看看其中的内容,q里Ҏ们最重要的就是第一个设|内容,你会看到下面的内容:<br />  # Set this to `no' if pserver shouldn't check system users/passwords<br />  #SystemAuth=yes<br />  W二行就是我们要修改的内容,默认状态是被注释掉的,SystemAuth有两个值yes和no<br />yesQpserver用系l用h据库和passwd文gQ这个文件后面会详细讲述Q来共同验证Q若passwd文g不存在或者文件中没有相应的资料,则用pȝ用户来进行验证)默认为yes<br />  noQ所有的用户必须在passwd中存在,Ҏpasswd的内Ҏq行用户的验证?br />  我这里所阐述的方案就是工作在no的下面的Q修改完之后提交到服务器Q提交完毕服务器处在CVSNT的独立验证模式下了。在q个工作方式下,NT本地的用户和CVSNT用户没有M本质的联pd影响Q仅仅是要徏立一个别名)?br /></span> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  1Q? passwd文g</span> </b> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br /> </span> </b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  在讲qC面的时候提Cq个文gQ在服务器工作在CVSNT验证模式下的时候,q个文g可以称之ؓCVSNT的用h据库Q这个里面存储着用户列表Q用L密码Q以及别名的一些信息。默认状态下q个文g是不存在的,所以,如果我们要在CVSNT验证模式下工作,必须建立q个文g。注意:q个文g是不能够在客Lq行修改的。这个文件的内容是相当简单的Q就像下面:<br />  bach:ULtgRLXo7NRxs<br />  spwang:1sOp854gDF3DY<br />  melissa:tGX1fS8sun6rY:pubcvs<br />  qproj:XR4EZcEs0szik:pubcvs<br />  q里分别拿第一个用户bach和第三个用户melissa来进行说明,每一行代表一个用Pd有三部分信息Q用户名、密码、本地用户三部分之间使用冒号?”来q行分割?br />  用户名:是登陆CVS的用户名<br />  ?码:用户的密码,q里是经q加密的Q如果ؓI,那么是I密?br />  本地用户QCVS用户q个别名对应的本地用PQ跟本地用户没有M其他关系Q仅仅是别名的关p)<br />  如果在本地系l中存在一个用户名bashQ那么要在CVS建立一个bachq样的用户就不需要在后面指出对应的系l用Pmelissa后面的pubcvs是pȝ用户Q在本地pȝ上面存在的用戗对于要用命令增加这两种用户的格式如下:<br />  cvs passwd –a bach<br />  cvs passwd –r pubcvs –a melissa<br />  在库建立的时候可以在服务器上建立一个简单的passwd初始化文Ӟ加一?br />  cvsadmin:<br />  q样Q就l出了一个cvsadminq个I密码用P本地pȝ中有q样的用P可以不加到后面去)Q然后在客户端来q行修改和以后的用户增加工作。注意:在客Lq行其他之前请先首先修改q个密码Q以防止别hq行破坏?br />  在服务器端徏立了q个文g以后Q就不用再手动进行修改了Q当你在客户端进行密码或者用L增加删除的时候,pȝ会自动进行这个文件的更新。这个文件是理着CVSNTpȝ中的所有的用户Q所以,要特别重视,不了解这个文件格式的Q不要去随便修改Q更加不要尝试在客户端进行修改!<br /></span> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  1Q? admin文g</span> </b> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br /> </span> </b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  q个文g是指定CVSNT的管理员列表的文ӞCVSNT会根据这个文件中的内Ҏ判断一个用h否是理员。这个文件的内容很简单,是一个用户列表。类g?br />  user1<br />  user2<br />  user3<br />  q些代表user1,user2,user3都是理员,当然Q这些用户必要存在才能够正登陆系l来执行理?br />  q个文g默认状态下是没有的Q但是,可以在客Lq行dQ在你的客户端进行新个文件然后add上去再commit一下,q个文g可以上传到服务器,但是q个时候还没有生效Q请修改checkoutlistq个文gQ加入adminq一行,checkoutlist也可以在客户端进行修改再提交Q这个时候admin可以被pȝ自动的build了?br />  Checkoutlist是维护的一个文件列表,可以攑օpȝ自动build的用戯定义的系l文件列表,注意Q对passwd没有用!Q?br /></span> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  1Q? group文g</span> </b> <b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br /> </span> </b> <span lang="EN-US" style="COLOR: #333333; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">  q个文g是定义系l的l,我们可以同h质的用户归入一个组Q然后用l用戯权限的方式给l赋权限Q这P一个组的用户就会具有同L权限。Group的内容如下:<br />  group1:user1 user2 user3<br />  group2:me you he<br />  group3:tom honey<br />  有上面可以看出来Q这个文件的内容也是相当的简单,首先是组的名U然后是冒号Q接着是用户名Q多个用户名之间用空格来q行分割?br />  Group文g可以在客Lq行新徏和修改,不用修改checkoutlistq个文gQ系l会自动buildq个文gq且使之生效?br />  作ؓl里面的特定成员q可以赋l特定的权限Q权限分Zcc,w,r和nQ否定权限是有高的优先的?br />  好,上面已经介绍了本Ҏ所涉及到的几个重要的文件以及修Ҏ式。这里再一下,passwd只能够再服务器端q行建立和修改,不能够在客户端进行操作!<br />现在Ҏ上面介绍的内容,可以开始你的操作了Q下面给Z攚w序,库刚刚徏立v来的时候,使用一个服务器上的本地理员用戯行登陆检出CVSROOT模块?br />  1?现在服务器端加上passwd文gQ给一个初始的用户Q比如cvsadmin:<br />  2?在客L增加adminQ将cvsadmin加入admin文gQ作为出是管理员Qƈ提交加入到库中?br />  3?在修改checkoutlist文gQ加入adminQ其能够自动build?br />  4?最后修改config文g的SystemAuth=noQ在提交之前要确认一下你上面的修Ҏ否正,如果提交了这个文ӞCVSNT验证模式开始生效了Q?br />  5?好,现在请修改你的参数再重新q行的登陆吧。因Z的系l已l切换了工作模式Q你当前的用户已l失效了?br />  完成了上面的步骤Q整个服务器׃有效的工作在CVSNT验证模式下了。而group文g在你需要的M时候可以加入?br />  在上面的文章关于CVSNT的用L理Ҏ的,在这里做一点补充,在后面的操作中全部是针对在客L使用WinCVS来进行的Q出了增加passwdQ文Ӟ其实Q在我的实践当中configQpasswdQadminQcheckoutlistQ这些文件的起始修改Q初始化Q都可以在新Z库以后一起完成,然后再让相应的库的管理员来进行相关的操作?br /></span> <img src ="http://www.aygfsteel.com/weibogao/aggbug/94190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2007-01-16 12:38 <a href="http://www.aygfsteel.com/weibogao/archive/2007/01/16/94190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle的物化视?/title><link>http://www.aygfsteel.com/weibogao/archive/2007/01/15/93914.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Mon, 15 Jan 2007 04:05:00 GMT</pubDate><guid>http://www.aygfsteel.com/weibogao/archive/2007/01/15/93914.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/93914.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2007/01/15/93914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/93914.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/93914.html</trackback:ping><description><![CDATA[     摘要: Oracle 的物化视图提供了强大的功能,可以用在不同的环境中。在不同的环境中Q物化视囄作用也不相同? 数据仓库中的物化视图主要用于预先计算q保存表q接或聚集等耗时较多的操作的l果Q这P在执行查询时Q就可以避免q行q些耗时的操作,而从快速的得到l果。在数据仓库中,q经怋用查询重写( ...  <a href='http://www.aygfsteel.com/weibogao/archive/2007/01/15/93914.html'>阅读全文</a><img src ="http://www.aygfsteel.com/weibogao/aggbug/93914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2007-01-15 12:05 <a href="http://www.aygfsteel.com/weibogao/archive/2007/01/15/93914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective SQLhttp://www.aygfsteel.com/weibogao/archive/2007/01/12/93392.htmlweibogaoweibogaoFri, 12 Jan 2007 04:56:00 GMThttp://www.aygfsteel.com/weibogao/archive/2007/01/12/93392.htmlhttp://www.aygfsteel.com/weibogao/comments/93392.htmlhttp://www.aygfsteel.com/weibogao/archive/2007/01/12/93392.html#Feedback2http://www.aygfsteel.com/weibogao/comments/commentRss/93392.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/93392.html一.名词解释Q?
0。SQL l构化查询语a(Structured Query Language)

1。非关系型数据库pȝ
做ؓW一代数据库pȝ的ȝQ其包括2U类型:“层ơ”数据库与“网状”数据库

“层ơ”数据库理pȝ eg:IBM&IMS (Information  Management System)
特点:数据按层ơ模型组l?

"|状"数据?
特点Q数据按|状模型l织

2。关pd数据库系l?
关系性数据库理pȝ (RDBMS)
eg:SQL/DS , DB2, Oracle ,Informix ,Unity,dBASE{?
特点Q数据按二维的表格组l?

3。数据库(DataBase)
按一定结构存储在计算Z怺兌的数据的集合?

4。数据库理pȝDBMS(Database Management System)
一个通用的Y件系l。就是让你怎么理你的数据库。其中包括存储,安全Q完整性管?br />{?

5。数据库应用pȝDBAS QDatabase Application SystemQ?
数据库应用程序系l,建立在DBMS基础之上的。就是一个面向用L软gpȝ?

6。ANSI标准 QAmerican National Standards InstituteQ美国国家标准委员会
因ؓ1999q第2ơ更新SQLQ所以SQL又称为SQL99或SQL3Q第3版,?个版本分别ؓ1986q?br />的sql ,1992 q的sql2/sql92Q?

7。SQL语句?U类?
数据操作语句(Data Manipulation Language ) DML 关于数据操作命o的?eg:select,in
sert,update,delete
数据定义语句(Data Definition Language ) DDL     关于数据对象讉K的?eg:createQ?br /> drop
数据控制语句(Data Control Language) DCL         关于权限的?eg:grant Qrevoke


8。PL/SQL Procedural Language/sql
用于oracle的语a

9.T-SQL  transact-sql
用于 microsoft sql server 和sybase adaptive server

10。E.F.Codd关于关系型数据库12条检验原则(MYSQLQ不支持视图和原子事物处理,所?br />排除Q?
内容Q暂?

11。数据库设计之新奥尔良方法?
需求分?=》概念设?=》逻辑设计==》物理设?
4个步骤的具体中以需求分析最重要.
需求分析的内容:暂略
概念设计的内?暂略
逻辑设计的内?暂略
物理设计的内?暂略


?数据库优化方?
1.索引
一 概述

  可以利用索引快速访问数据库表中的特定信息。烦引是Ҏ据库表中一个或多个列的?br />q行排序的结构?
  索引提供指针以指向存储在表中指定列的数据|然后Ҏ指定的排序次序排列这些指
针?
  数据库用烦引的方式与用书的目录很怼Q通过搜烦索引扑ֈ特定的|
  然后跟随指针到达包含该值的?

索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的?br />向表中物理标识这些值的数据늚逻辑指针清单?

一个表的存储是׃部分l成的,一部分用来存放表的数据面Q另一部分存放索引面
。烦引就存放在烦引页面上

?索引的两U类型:

聚集索引=集索引

聚集索引Z数据行的键值在表内排序和存储这些数据行。由于数据行按基于聚集烦引键
的排序次序存储,
因此聚集索引Ҏ找行很有效。每个表只能有一个聚集烦引,因ؓ数据行本w只能按一?br />序存储?
数据行本w构成聚集烦引的最低别?

只有当表包含聚集索引Ӟ表内的数据行才按排序ơ序存储。如果表没有聚集索引Q?
则其数据行按堆集方式存储?

聚集索引对于那些l常要搜索范围值的列特别有效。用聚集烦引找到包含第一个值的?br />后,
便可以确保包含后l烦引值的行在物理盔R。例如,如果应用E序执行的一个查询经常检
索某一日期范围
内的记录Q则使用聚集索引可以q速找到包含开始日期的行,然后索表中所有相ȝ?br />Q?
直到到达l束日期。这h助于提高此类查询的性能。同P如果对从表中索的数据q?br />行排序时
l常要用到某一列,则可以将该表在该列上聚集Q物理排序)Q避免每ơ查询该列时都进
行排序,
从而节省成?

非聚集烦?

非聚集烦引具有完全独立于数据行的l构。非聚集索引的最低行包含非聚集烦引的键|

q且每个键值项都有指针指向包含该键值的数据行。数据行不按Z非聚集键的次序存?br />?

在非聚集索引内,从烦引行指向数据行的指针UCؓ行定位器?
行定位器的结构取决于数据늚存储方式是堆集还是聚集。对于堆集,行定位器是指向行
的指针?
对于有聚集烦引的表,行定位器是聚集烦引键?
只有在表上创Z聚集索引Ӟ表内的行才按特定的顺序存储。这些行基于聚集烦引键
按顺序存储?
如果一个表只有非聚集烦引,它的数据行将按无序的堆集方式存储
非聚集烦引可以徏多个,两者都能改善查询性能

非聚集烦引与聚集索引一h B 树结构,但是有两个重大差别:
数据行不按非聚集索引键的序排序和存储?
非聚集烦引的叶层不包含数据页?
相反Q叶节点包含索引行。每个烦引行包含非聚集键g及一个或多个行定位器Q?
q些行定位器指向有该键值的数据行(如果索引不唯一Q则可能是多行)?
非聚集烦引可以在有聚集烦引的表、堆集或索引视图上定?


聚集索引-->序表结?其物理数据和逻辑排序紧邻.
非聚集烦?->单链表结?L理和逻辑排序不按序排列.

打个比方.
一本字?你现在查一个陈?你有2U方?首先,你在知道他念chen的情况下L照拼韛_
母去查找.他是排在字母A,B
于是你很Ҏ的就扑ֈ"??W?U方法则是按~旁查找,先找到x?LC个?br />的编旁表在去??q个?然后按照l出?
|扑ֈ相应的位|?
昄,W一U方法就是聚集烦?按照物理位置Ҏ排序来查?
W?U方法则是非聚集索引,按照一个时烦引来查找.

另外
唯一索引

唯一索引可以保索引列不包含重复的倹{在多列唯一索引的情况下Q该索引可以保?br />引列中每个值组
合都是唯一的。唯一索引既是索引也是U束?

复合索引
索引Ҏ多个的就叫组合烦引,也叫复合索引。复合烦引用时需要注意烦引项的次序?br />

?索引的创?

有两U方法可以在 SQL Server 内定义烦? CREATE INDEX 语句和CREATE TABLE 语句


CREATE TABLE支持在创建烦引时使用下列U束Q?

PRIMARY KEY 创徏唯一索引来强制执行主?
UNIQUE 创徏唯一索引
CLUSTERED 创徏聚集索引
NONCLUSTERED 创徏非聚集烦?

? 1 定义索引Ӟ可以指定每列的数据是按升序还是降序存储。如果不指定Q则默认?br />升序
   2 支持在计列上创建烦?
   3 为烦引指定填充因?
     可标识填充因子来指定每个索引늚填满E度。烦引页上的IZI间量很重要Q?
     因ؓ当烦引页填满Ӟpȝ必须花时间拆分它以便为新行腾出空间?


?索引的维护语?

DBCC DBREINDEX    重徏指定数据库中表的一个或多个索引
DBCC INDEXFRAG  整理指定的表或视囄聚集索引和辅助烦引碎?

比较

            速度    兼容性   ?日志影响      数据讉K影响       额外盘I间

DBCC        最快    ?最q  ??但能通过把 ?操作q程中数据不   需要大
DBREINDEX             可以重 ?故障q原模型设?能访问,影响?
                     建所有 ?为简单减日志  ?
                     有烦?

DBCC        慢     ?但可   必须分 ?            ?数据未被锁定        需要小

INDEXDEFRAG          随时l?别指?
                    止执行 ?
                              

drop index    中等  必须分 ??但能通过把  ?仅在操作执行时  ?中等Q操作在 
 
create index        别指定 ?故障q原模型设 ?锁定数据          tempdb中进?

                            为简单减日?


?查看索引的方?

sp_indexes        q回指定q程表的索引信息
INDEXKEY_PROPERTY q回有关索引键的信息
sysindexespȝ表?数据库中的每个烦引和表在表中各占一行,该表存储在每个数据库?br />


?可以通过执行计划
  查看sql语句执行时是否徏立在索引之上

比如
CREATE TABLE Test
(Field_1 int NOT NULL,
Field_2 int CONSTRAINT PK_Test
PRIMARY KEY CLUSTERED (Field_1))

CREATE index IX_Test ON Test (Field_2)

1 SELECT * FROM Test WHERE Field_2 =408
执行计划可以看出使用了IX_Test索引
2 SELECT * FROM Test WHERE Field_1 =1
执行计划可以看出使用了PK_Test
3 但如果是SELECT * FROM Test with (index(IX_Test)) WHERE Field_1 =1
则指定用烦?


?索引的具体?

1Q?索引的设?
A:量避免表扫?
查你的查询语句的where子句Q因是优化器重要x的地斏V包含在where里面的每
一列(column)都是可能的侯选烦引,辑ֈ最优的性能Q考虑在下面给出的例子Q对?br />在where子句中给Zcolumn1q个列?
下面的两个条件可以提高烦引的优化查询性能Q?
W一Q在表中的column1列上有一个单索引
W二Q在表中有多索引Q但是column1是第一个烦引的?
避免定义多烦引而column1是第二个或后面的索引Q这L索引不能优化服务器性能
例如Q下面的例子用了pubs数据库?
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = ’White?
按下面几个列上徏立的索引会是对优化器有用的索引
?au_lname
?au_lname, au_fname
而在下面几个列上建立的烦引将不会对优化器起到好的作用
?au_address
?au_fname, au_lname
考虑使用H的索引在一个或两个列上Q窄索引比多索引和复合烦引更能有效。用H的索引
Q在每一上
会有更多的行和更少的烦引别(相对与多索引和复合烦引而言Q,q将推进pȝ性能
?
对于多列索引QSQL Serverl持一个在所有列的烦引上的密度统计(用于联合Q和在第一
个烦引上?
histogramQ柱状图Q统计。根据统计结果,如果在复合烦引上的第一个烦引很被选择?br />用,那么优化器对很多查询h不会用烦引?
有用的烦引会提高select语句的性能Q包括insert,uodate,delete?
但是Q由于改变一个表的内容,会影响索引。每一个insert,update,delete语句会?br />性能下降一些。实验表明,不要在一个单表上用大量的索引Q不要在׃n的列上(指在?br />表中用了参考约束)使用重叠的烦引?
在某一列上查唯一的数据的个数Q比较它与表中数据的行数做一个比较。这是数据?br />选择性,q比较结果将会帮助你军_是否某一列作Z选的索引列,如果需要,建哪一
U烦引。你可以用下面的查询语句q回某一列的不同值的数目?
select count(distinct cloumn_name) from table_name
假设column_name是一?0000行的表,则看column_nameq回值来军_是否应该使用Q及?br />该用什么烦引?
Unique values Index

5000 Nonclustered index
20 Clustered index
3 No index


2) 镞烦引和非镞索引的选择

<1:>镞烦引是行的物理序和烦引的序是一致的。页U,低层{烦引的各个U别上都?br />含实际的数据c一个表只能是有一个镞索引。由于update,delete语句要求相对多一些的
L作,因此镞烦引常常能加速这L操作。在臛_有一个烦引的表中Q你应该有一个镞
索引?
在下面的几个情况下,你可以考虑用镞索引Q?
例如Q?某列包括的不同值的个数是有限的Q但是不是极的Q?
֮表的州名列有50个左右的不同州名的羃写|可以使用镞烦引?
例如Q?对返回一定范围内值的列可以用镞索引Q比如用between,>,>=,<,<={等来对?br />q行操作的列上?
select * from sales where ord_date between ?/1/93?and ?/1/93?
例如Q?Ҏ询时q回大量l果的列可以使用镞烦引?
SELECT * FROM phonebook WHERE last_name = ’Smith?

当有大量的行正在被插入表中时Q要避免在本表一个自然增长(例如Qidentity列)的列
上徏立镞索引。如果你建立了镞的烦引,那么insert的性能׃大大降低。因为每一个插
入的行必d表的最后,表的最后一个数据页?
当一个数据正在被插入Q这时这个数据页是被锁定的)Q所有的其他插入行必ȝ待直?br />当前的插入已l结束?
一个烦引的叶中包括实际的数据页Qƈ且在盘上的数据늚ơ序是跟镞烦引的逻辑
ơ序一L?

<2:>一个非镞的索引是行的物理ơ序与烦引的ơ序是不同的。一个非镞烦引的叶包含
了指向行数据늚指针?
在一个表中可以有多个非镞索引Q你可以在以下几个情况下考虑使用非镞索引?
在有很多不同值的列上可以考虑使用非镞索引
例如Q一个part_id列在一个part表中
select * from employee where emp_id = ’pcm9809f?
查询语句中用order by 子句的列上可以考虑使用镞烦?



3) 一个表列如果设Z?primary key),它会自动生成一个聚烦?
q时不能直接使用Drop index Table1.Tableindex1语句
必须删除主键U束Q用语句:alter table table1 drop constraint U束?如pk_xxx)



?全文索引
use pubs
  go

  --打开数据库全文烦引的支持

 execute sp_fulltext_database 'enable'
 go

  --建立全文目录ft_titles

  execute sp_fulltext_catalog 'ft_titles', 'create'
  go

  --为titles表徏立全文烦引数据元QUPKCL_titleidind是主键所建立的唯一索引Q可
由sp_help titles得知

  execute sp_fulltext_table 'titles','create', 'ft_titles', 'UPKCL_titleidin
d'
  go

  --讄全文索引列名

  exec sp_fulltext_column 'titles', 'title', 'add'
  go
  exec sp_fulltext_column 'titles', 'notes', 'add'
  go

  --建立全文索引

  exec sp_fulltext_table 'titles', 'activate'
  go

  --填充全文索引目录

  exec sp_fulltext_catalog 'ft_titles', 'start_full'
  go

  --使用contains和freetext

  select title, notes from titles
  where contains(title, '"computer Cooking"')
  go
  select title, notes from titles
  where freetext(title, 'computer Cooking')
  go
  select title, notes from titles
  where freetext(title, '"computer Cooking"')
  go
  select title, notes from titles
  where contains(title, 'computer')
  go
  select title, notes from titles
  where freetext (*, 'computer')
  go

q里提一下google的搜索引擎的原理.
他把每个字词都做为单元去查询.
打个比方:我在字典里查?现在我要搜烦"树型"q个?他会把这个树型这个词全文扫描一
?生成一个二叉树.q记下他的页?
然后当我W?ơ查扄时候显然这?记忆"提示,然后"提取".如果你对某一个字D做了全?br />索引的话Q他会全文扫描表一?然后U录?
相应的纪?生成二叉?
如果我要查找"树叶",同理也可以得出页?但当我们L找一?树型l构"他则会把"树型
"?树型l构"?U录"下来.

?巧妙的用烦?
SELECT SUM(quantity) AS quantity FROM test WHERE...
1.若WHERE 里用的是字段与常量比较,MSSQL会自动引用该字段上的索引Q若用的是变量,
MSSQL不会自动引用该字D上的烦引而是Ҏ聚集索引q行扫描
2.加上with(index(索引?)指定索引Q即Q?
SELECT SUM(quantity) AS quantity FROM with(index(索引?) test WHERE...
指定索引后,WHERE 里不论是帔Rq是变量QMSSQL都根据指定的索引q行扫描
3.DBCC DBREINDEX执行q不一定能优化MSSQL性能Q慎?
4.如果在pub_id上徏立烦引的?
select * from titles where pub_id-500 >1000   ---------(a)
select * from titles where pub_id >1000+500  -----------(b)
请选用(b)语句,q样的话Q他会利用烦??a)的话׃对字D|作了,所以不会利用烦?br />.
5.量避免用like语句,
如果L找baa%,caa%的话
如果是like '%aa%','_aa%','[m-z]o%'  则根本不会用到烦?
替换Ҏ.columns like 'baa%' or  columns like 'caa %'
6什么情况下应不建或徏索引
a.表记录太?.因ؓ索引的话Q要Ҏ据库往q?ơ操?如果1个表只有几行字段的话Q数
据库会对他的U录一ơ性全部取出来,q样的效率要q远高于索引.
b.l常insert,delete,update的表  对一些经常处理的业务表应在查询允许的情况下尽?br />减少索引
c.数据重复且分布^均的表字D??性别字段,各占50%的话Q你即Z,也v不到明显?br />作用.
d.l常和主字段一块查询但dD늃引值比较多的表字段
表经常按收费序号、户标识~号、抄表日期、电费发生年月、操作标志来具体查询某一W?br />收款的情况,如果所有的字段都徏在一个烦引里那将会增加数据的修改、插入、删除时
_从实际上分析一W收Ƒ֦果按收费序号索引已l将记录减少到只有几条,如果再按
后面的几个字D늃引查询将Ҏ能不生太大的影响?
e.如果一个表的记录达?00万以上的话,要对其中一个字D徏索引可能要花很长的时_
甚至D服务器数据库LQ因为在建烦引的时?ORACLE要将索引字段所有的内容取出q?br />q行全面排序Q数据量大的话可能导致服务器排序内存不而引用磁盘交换空间进行,q?br />严重媄响服务器数据库的工作。解x法是增大数据库启动初始化中的排序内存参数Q?br />如果要进行大量的索引修改可以讄10M以上的排序内存(ORACLE~省大小?4KQ,在烦
引徏立完成后应将参数修改回来Q因为在实际OLTP数据库应用中一般不会用到这么大的排
序内存?


以下转蝲
great_domino ?Blog

探讨如何在有着1000万条数据的MS SQL SERVER数据库中实现快速的数据提取和数据分c?br />以下代码说明了我们实例中数据库的“红头文件”一表的部分数据l构Q?

CREATE TABLE [dbo].[TGongwen] (    --TGongwen是红头文件表?

  [Gid] [int] IDENTITY (1, 1) NOT NULL ,
--本表的idP也是主键

  [title] [varchar] (80) COLLATE Chinese_PRC_CI_AS NULL ,
--U头文g的标?

  [fariqi] [datetime] NULL ,
--发布日期

  [neibuYonghu] [varchar] (70) COLLATE Chinese_PRC_CI_AS NULL ,
--发布用户

  [reader] [varchar] (900) COLLATE Chinese_PRC_CI_AS NULL ,

--需要浏览的用户。每个用户中间用分隔W?”分开

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO


  下面Q我们来往数据库中d1000万条数据Q?

declare @i int

set @i=1

while @i<=250000

begin

   insert into Tgongwen(fariqi,neibuyonghu,reader,title) values('2004-2-5','?br />信科','通信U?办公?王局?刘局?张局?admin,刑侦支队,特勤支队,交E警支?l?br />侦支? hU?d支队,外事U?,'q是最先的25万条记录')

   set @i=@i+1

end

GO



declare @i int

set @i=1

while @i<=250000

begin

   insert into Tgongwen(fariqi,neibuyonghu,reader,title) values('2004-9-16','?br />公室','办公?通信U?王局?刘局?张局?admin,刑侦支队,特勤支队,交E警支?l?br />侦支?hU?外事U?,'q是中间?5万条记录')

   set @i=@i+1

end

GO



declare @h int

set @h=1

while @h<=100

begin

declare @i int

set @i=2002

while @i<=2003

begin

declare @j int

       set @j=0

       while @j<50

           begin

declare @k int

           set @k=0

           while @k<50

           begin

   insert into Tgongwen(fariqi,neibuyonghu,reader,title) values(cast(@i as var
char(4))+'-8-15 3:'+cast(@j as varchar(2))+':'+cast(@j as varchar(2)),'通信U?
,'办公?通信U?王局?刘局?张局?admin,刑侦支队,特勤支队,交E警支?l侦?br />?hU?外事U?,'q是最后的50万条记录')

           set @k=@k+1

           end

set @j=@j+1

       end

set @i=@i+1

end

set @h=@h+1

end

GO



declare @i int

set @i=1

while @i<=9000000

begin

   insert into Tgongwen(fariqi,neibuyonghu,reader,title) values('2004-5-5','?br />信科','通信U?办公?王局?刘局?张局?admin,刑侦支队,特勤支队,交E警支?l?br />侦支? hU?d支队,外事U?,'q是最后添加的900万条记录')

   set @i=@i+1000000

end

GO

通过以上语句Q我们创Z25万条׃2004q??日发布的记录Q?5万条由办公室?004
q??日发布的记录Q?002q和2003q各 100?500条相同日期、不同分U的记录Q共50
万条Q,q有由通信U于2004q??日发布的900万条记录Q合?000万条?

何时使用聚集索引或非聚集索引

  下面的表ȝ了何时用聚集烦引或非聚集烦引(很重要)?

  动作描述
   使用聚集索引
   使用非聚集烦?

  列经常被分组排序
   ?
   ?

  q回某范围内的数?
   ?
   不应

  一个或极少不同?
   不应
   不应

  数目的不同?
   ?
   不应

  大数目的不同?
   不应
   ?

  频繁更新的列
   不应
   ?

  外键?
   ?
   ?

  主键?
   ?
   ?

  频繁修改索引?
   不应
   ?


  事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如Q返
回某范围内的数据一V比如您的某个表有一个时间列Q恰好您把聚合烦引徏立在了该?br />Q这时您查询2004q??日至2004q?0?日之间的全部数据Ӟq个速度将是很快的Q?br />因ؓ您的q本字典正文是按日期q行排序的,聚类索引只需要找到要索的所有数据中?br />开头和l尾数据卛_Q而不像非聚集索引Q必d查到目录中查到每一Ҏ据对应的늠
Q然后再Ҏ늠查到具体内容?

Q三Q结合实际,谈烦引用的误区

  理论的目的是应用。虽然我们刚才列Z何时应用聚集烦引或非聚集烦引,但在?br />践中以上规则却很Ҏ被忽视或不能Ҏ实际情况q行l合分析。下面我们将Ҏ在实?br />中遇到的实际问题来谈一下烦引用的误区Q以便于大家掌握索引建立的方法?

  1、主键就是聚集烦?

  q种xW者认为是极端错误的,是对聚集索引的一U浪贏V虽然SQL SERVER默认?br />在主键上建立聚集索引的?

  通常Q我们会在每个表中都建立一个ID列,以区分每条数据,q且q个ID列是自动?br />大的Q步长一般ؓ1。我们的q个办公自动化的实例中的?Gid是如此。此Ӟ如果我们
这个列设ؓ主键QSQL SERVER会将此列默认集烦引。这样做有好处,是可以让您
的数据在数据库中按照IDq行物理排序Q但W者认样做意义不大?

  显而易见,聚集索引的优势是很明昄Q而每个表中只能有一个聚集烦引的规则Q这
使得聚集索引变得更加珍贵?

  从我们前面谈到的聚集索引的定义我们可以看出,使用聚集索引的最大好处就是能?br />Ҏ查询要求Q迅速羃查询范_避免全表扫描。在实际应用中,因ؓIDh自动生成
的,我们q不知道每条记录的IDP所以我们很隑֜实践中用IDhq行查询。这׃?br />ID可个主键作集烦引成ZU资源浪贏V其ơ,让每个ID号都不同的字D作?br />索引也不W合“大数目的不同值情况下不应建立聚合索引”规则;当然Q这U情况只是针
对用L怿改记录内容,特别是烦引项的时候会负作用,但对于查询速度q没有媄响?br />

  在办公自动化pȝ中,无论是系l首|C的需要用L收的文g、会议还是用戯
行文件查询等M情况下进行数据查询都M开字段的是“日期”还有用hw的“用?br />名”?

  通常Q办公自动化的首会昄每个用户未{收的文件或会议。虽然我们的where?br />句可以仅仅限制当前用户尚未签收的情况Q但如果您的pȝ已徏立了很长旉Qƈ且数?br />量很大,那么Q每ơ每个用h开首页的时候都q行一ơ全表扫描,q样做意义是不大?br />Q绝大多数的用户1个月前的文g都已l浏览过了,q样做只能徒增数据库的开销而已。事
实上Q我们完全可以让用户打开pȝ首页Ӟ数据库仅仅查询这个用戯3个月来未阅览?br />文gQ通过“日期”这个字D|限制表扫描,提高查询速度。如果您的办公自动化pȝ?br />l徏立的2q_那么您的首页昄速度理论上将是原来速度8倍,甚至更快?

  在这里之所以提到“理Z”三字,是因为如果您的聚集烦引还是盲目地建在IDq个
主键上时Q您的查询速度是没有这么高的,即您在“日期”这个字D上建立的烦引(?br />聚合索引Q。下面我们就来看一下在1000万条数据量的情况下各U查询的速度表现Q?个月
内的数据?5万条Q:

  Q?Q仅在主键上建立聚集索引Qƈ且不划分旉D:

Select gid,fariqi,neibuyonghu,title from tgongwen

  用时Q?28470毫秒Q即Q?28U)

  Q?Q在主键上徏立聚集烦引,在fariq上徏立非聚集索引Q?

select gid,fariqi,neibuyonghu,title from Tgongwen

where fariqi> dateadd(day,-90,getdate())

  用时Q?3763毫秒Q?4U)

  Q?Q将聚合索引建立在日期列QfariqiQ上Q?

select gid,fariqi,neibuyonghu,title from Tgongwen

where fariqi> dateadd(day,-90,getdate())

  用时Q?423毫秒Q?U)

  虽然每条语句提取出来的都?5万条数据Q各U情늚差异却是巨大的,特别是将?br />集烦引徏立在日期列时的差异。事实上Q如果您的数据库真的?1000万容量的话,把主?br />建立在ID列上Q就像以上的W??U情况,在网上的表现就是超ӞҎ无法显C?br />q也是我摒弃ID列作集烦引的一个最重要的因素?

  得出以上速度的方法是Q在各个select语句前加Qdeclare @d datetime

set @d=getdate()

q在select语句后加Q?

select [语句执行p旉(毫秒)]=datediff(ms,@d,getdate())

  2、只要徏立烦引就能显著提高查询速度

  事实上,我们可以发现上面的例子中Q第2?条语句完全相同,且徏立烦引的字段?br />相同Q不同的仅是前者在fariqi字段上徏立的是非聚合索引Q后者在此字D上建立的是?br />合烦引,但查询速度却有着天壤之别。所以,q是在M字段上简单地建立索引p?br />高查询速度?

  从徏表的语句中,我们可以看到q个有着1000万数据的表中fariqi字段?003个不?br />记录。在此字D上建立聚合索引是再合适不q了。在现实中,我们每天都会发几个文Ӟ
q几个文件的发文日期q同,q完全符合徏立聚集烦引要求的Q“既不能l大多数都相
同,又不能只有极数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们
提高查询速度是非帔R要的?

  3、把所有需要提高查询速度的字D都加进聚集索引Q以提高查询速度

  上面已经谈到Q在q行数据查询旉M开字段的是“日期”还有用hw的“用?br />名”。既然这两个字段都是如此的重要,我们可以把他们合qv来,建立一个复合烦引(
compound indexQ?

  很多为只要把M字段加进聚集索引Q就能提高查询速度Q也有h感到qhQ如
果把复合的聚集烦引字D分开查询Q那么查询速度会减慢吗Q带着q个问题Q我们来看一
下以下的查询速度Q结果集都是25万条数据Q:Q日期列fariqi首先排在复合聚集索引?br />起始列,用户名neibuyonghu排在后列Q?

  Q?Qselect gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>'2004-
5-5'

  查询速度Q?513毫秒

  Q?Qselect gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>'2004-
5-5' and neibuyonghu='办公?

  查询速度Q?516毫秒

  Q?Qselect gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu='
办公?

  查询速度Q?0280毫秒

  从以上试验中Q我们可以看到如果仅用聚集烦引的起始列作为查询条件和同时用到?br />合聚集烦引的全部列的查询速度是几乎一LQ甚x用上全部的复合烦引列q要略快Q?br />在查询结果集数目一L情况下)Q而如果仅用复合聚集烦引的非v始列作ؓ查询条g?br />话,q个索引是不起Q何作用的。当Ӟ语句1?的查询速度一h因ؓ查询的条目数一
P如果复合索引的所有列都用上,而且查询l果的话,q样׃形成“烦引覆盖”,
因而性能可以辑ֈ最优。同Ӟ误住:无论您是否经怋用聚合烦引的其他列,但其?br />导列一定要是用最频繁的列?

Q四Q其他书上没有的索引使用l验ȝ

  1、用聚合索引比用不是聚合索引的主键速度?

  下面是实例语句:Q都是提?5万条数据Q?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-
16'

  使用旉Q?326毫秒

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid<=250000

  使用旉Q?470毫秒

  q里Q用聚合索引比用不是聚合索引的主键速度快了q?/4?

  2、用聚合索引比用一般的主键作order by旉度快,特别是在数据量情况?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by fariqi

  用时Q?2936

select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid

  用时Q?8843

  q里Q用聚合索引比用一般的主键作order byӞ速度快了3/10。事实上Q如果数?br />量很的话,用聚集烦引作为排序列要比使用非聚集烦引速度快得明显的多Q而数据量?br />果很大的话,?0万以上,则二者的速度差别不明显?

  3、用聚合烦引内的时间段Q搜索时间会按数据占整个数据表的癑ֈ比成比例减少Q?br />而无合烦引用了多少?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>'2004-1-
1'

  用时Q?343毫秒Q提?00万条Q?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>'2004-6-
6'

  用时Q?170毫秒Q提?0万条Q?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-
16'

  用时Q?326毫秒Q和上句的结果一模一栗如果采集的数量一P那么用大于号和等
于号是一LQ?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>'2004-1-
1' and fariqi<'2004-6-6'

  用时Q?280毫秒

  4 、日期列不会因ؓ有分U的输入而减慢查询速度

  下面的例子中Q共?00万条数据Q?004q??日以后的数据?0万条Q但只有两个?br />同的日期Q日期精到日;之前有数?0万条Q有5000个不同的日期Q日期精到U?


select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>'2004-1-
1' order by fariqi

  用时Q?390毫秒

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi<'2004-1-
1' order by fariqi

  用时Q?453毫秒

  Q五Q其他注意事?

  “水可蝲舟,亦可覆舟”,索引也一栗烦引有助于提高索性能Q但q多或不当的
索引也会Dpȝ低效。因为用户在表中每加q一个烦引,数据库就要做更多的工作。过
多的索引甚至会导致烦引碎片?

  所以说Q我们要建立一个“适当”的索引体系Q特别是对聚合烦引的创徏Q更应精?br />求精Q以使您的数据库能得到高性能的发挥?

  当然Q在实践中,作ؓ一个尽职的数据库管理员Q您q要多测试一些方案,扑և哪种
Ҏ效率最高、最为有效?

二、改善SQL语句

  很多Z知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句?br />被SQL SERVER误解。比如:

select * from table1 where name='zhangsan' and tID > 10000

  和执?

select * from table1 where tID > 10000 and name='zhangsan'

  一些h不知道以上两条语句的执行效率是否一P因ؓ如果单的从语句先后上看,
q两个语句的是不一P如果tID是一个聚合烦引,那么后一句仅仅从表的10000条以?br />的记录中查找p了;而前一句则要先从全表中查找看有几个name='zhangsan'的,而后?br />Ҏ限制条g条g tID>10000来提出查询结果?

  事实上,q样的担心是不必要的。SQL SERVER中有一个“查询分析优化器”,它可?br />计算出where子句中的搜烦条gq确定哪个烦引能~小表扫描的搜烦I间Q也是_它能
实现自动优化?

  虽然查询优化器可以根据where子句自动的进行查询优化,但大家仍然有必要了解一?br />“查询优化器”的工作原理Q如非这P有时查询优化器就会不按照您的本意q行快速查
询?

  在查询分析阶D,查询优化器查看查询的每个阶段q决定限刉要扫描的数据量是?br />有用。如果一个阶D可以被用作一个扫描参敎ͼSARGQ,那么q之ؓ可优化的Qƈ且可
以利用烦引快速获得所需数据?

  SARG的定义:用于限制搜烦的一个操作,因ؓ它通常是指一个特定的匚wQ一个值得
范围内的匚w或者两个以上条件的ANDq接。Ş式如下:

列名 操作W?<常数 ?变量>

?

<常数 ?变量> 操作W列?

  列名可以出现在操作符的一边,而常数或变量出现在操作符的另一辏V如Q?

Name=’张三?

h>5000

5000<h

Name=’张三?and h>5000

  如果一个表辑ּ不能满SARG的Ş式,那它无法限制搜索的范围了,也就是SQL SE
RVER必须Ҏ一行都判断它是否满WHERE子句中的所有条件。所以一个烦引对于不满S
ARG形式的表辑ּ来说是无用的?

  介绍完SARG后,我们来ȝ一下用SARG以及在实践中遇到的和某些资料上结Z?br />的经验:

  1、Like语句是否属于SARG取决于所使用的通配W的cd

  如:name like ‘张%?Q这属于SARG

  而:name like ?张?,׃属于SARG?

  原因是通配W?在字W串的开通得烦引无法用?

  2、or 会引起全表扫?

Name=’张三?and h>5000 W号SARGQ而:Name=’张三?or h>5000 则不W合S
ARG。用or会引起全表扫描?

  3、非操作W、函数引L不满SARG形式的语?

  不满SARG形式的语句最典型的情况就是包括非操作W的语句Q如QNOT?=?lt;>?
<?>、NOT EXISTS、NOT IN、NOT LIKE{,另外q有函数。下面就是几个不满SARG形式
的例子:

ABS(h)<5000

Name like ?三?

  有些表达式,如:

WHERE h*2>5000

  SQL SERVER也会认ؓ是SARGQSQL SERVER会将此式转化为:

WHERE h>2500/2

  但我们不推荐q样使用Q因为有时SQL SERVER不能保证q种转化与原始表辑ּ是完?br />{h的?

  4、IN 的作用相当与OR

  语句Q?

Select * from table1 where tid in (2,3)

  ?

Select * from table1 where tid=2 or tid=3

  是一LQ都会引起全表扫描,如果tid上有索引Q其索引也会失效?

  5、尽量少用NOT

  6、exists ?in 的执行效率是一L

  很多资料上都昄_exists要比in的执行效率要高,同时应尽可能的用not exists
来代替not in。但事实上,我试验了一下,发现二者无论是前面带不带notQ二者之间的?br />行效率都是一L。因为涉及子查询Q我们试验这ơ用SQL SERVER自带的pubs数据库。运
行前我们可以把SQL SERVER的statistics I/O状态打开?

  Q?Qselect title,price from titles where title_id in (select title_id fro
m sales where qty>30)

  该句的执行结果ؓQ?

  ?'sales'。扫描计?18Q逻辑?56 ơ,物理?0 ơ,预读 0 ơ?

  ?'titles'。扫描计?1Q逻辑?2 ơ,物理?0 ơ,预读 0 ơ?

  Q?Qselect title,price from titles where exists (select * from sales wher
e sales.title_id=titles.title_id and qty>30)

  W二句的执行l果为:

  ?'sales'。扫描计?18Q逻辑?56 ơ,物理?0 ơ,预读 0 ơ?

  ?'titles'。扫描计?1Q逻辑?2 ơ,物理?0 ơ,预读 0 ơ?

  我们从此可以看到用exists和用in的执行效率是一L?

  7、用函数charindex()和前面加通配W?的LIKE执行效率一?

  前面Q我们谈刎ͼ如果在LIKE前面加上通配W?Q那么将会引起全表扫描,所以其执行
效率是低下的。但有的资料介绍_用函数charindex()来代替LIKE速度会有大的提升Q经
我试验,发现q种说明也是错误的:

select gid,title,fariqi,reader from tgongwen where charindex('刑侦支队',reader
)>0 and fariqi>'2004-5-5'

  用时Q?U,另外Q扫描计?4Q逻辑?7155 ơ,物理?0 ơ,预读 0 ơ?

select gid,title,fariqi,reader from tgongwen where reader like '%' + '刑侦支队
' + '%' and fariqi>'2004-5-5'

  用时Q?U,另外Q扫描计?4Q逻辑?7155 ơ,物理?0 ơ,预读 0 ơ?

  8、unionq不l对比or的执行效率高

  我们前面已经谈到了在where子句中用or会引起全表扫描,一般的Q我所见过的资?br />都是推荐q里用union来代替or。事实证明,q种说法对于大部分都是适用的?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-
16' or gid>9990000

  用时Q?8U。扫描计?1Q逻辑?404008 ơ,物理?283 ơ,预读 392163 ơ?


select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-
16'

union

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid>9990000

  用时Q?U。扫描计?8Q逻辑?67489 ơ,物理?216 ơ,预读 7499 ơ?

  看来Q用union在通常情况下比用or的效率要高的多?

  但经q试验,W者发现如果or两边的查询列是一L话,那么用union则反倒和用or?br />执行速度差很多,虽然q里union扫描的是索引Q而or扫描的是全表?

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-
16' or fariqi='2004-2-5'

  用时Q?423毫秒。扫描计?2Q逻辑?14726 ơ,物理?1 ơ,预读 7176 ơ?


select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-
16'

union

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where  fariqi='2004-2
-5'

  用时Q?1640毫秒。扫描计?8Q逻辑?14806 ơ,物理?108 ơ,预读 1144 ơ?br />

  9、字D|取要按照“需多少、提多少”的原则Q避免“select *?

  我们来做一个试验:

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc

  用时Q?673毫秒

select top 10000 gid,fariqi,title from tgongwen order by gid desc

  用时Q?376毫秒

select top 10000 gid,fariqi from tgongwen order by gid desc

  用时Q?0毫秒

  由此看来Q我们每提取一个字D,数据的提取速度׃有相应的提升。提升的速度
q要看您舍弃的字D늚大小来判断?

  10、count(*)不比count(字段)?

  某些资料上说Q用*会统计所有列Q显然要比一个世界的列名效率低。这U说法其实是
没有Ҏ的。我们来看:

select count(*) from Tgongwen

  用时Q?500毫秒

select count(gid) from Tgongwen

  用时Q?483毫秒

select count(fariqi) from Tgongwen

  用时Q?140毫秒

select count(title) from Tgongwen

  用时Q?2050毫秒

  从以上可以看出,如果用count(*)和用count(主键)的速度是相当的Q而count(*)却比
其他M除主键以外的字段汇总速度要快Q而且字段长Q汇ȝ速度p慢。我惻I?br />果用count(*)Q?SQL SERVER可能会自动查找最字D|汇ȝ。当Ӟ如果您直接写cou
nt(主键)会来的更直接些?

  11、order by按聚集烦引列排序效率最?

  我们来看Q(gid是主键,fariqi是聚合烦引列Q?

select top 10000 gid,fariqi,reader,title from tgongwen

  用时Q?96 毫秒?扫描计数 1Q逻辑?289 ơ,物理?1 ơ,预读 1527 ơ?

select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc

  用时Q?720毫秒?扫描计数 1Q逻辑?41956 ơ,物理?0 ơ,预读 1287 ơ?


select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc

  用时Q?736毫秒?扫描计数 1Q逻辑?55350 ơ,物理?10 ơ,预读 775 ơ?


select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc

  用时Q?73毫秒?扫描计数 1Q逻辑?290 ơ,物理?0 ơ,预读 0 ơ?

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc

  用时Q?56毫秒?扫描计数 1Q逻辑?289 ơ,物理?0 ơ,预读 0 ơ?

  从以上我们可以看出,不排序的速度以及逻辑L数都是和“order by 聚集索引列?br /> 的速度是相当的Q但q些都比“order by 非聚集烦引列”的查询速度是快得多的?

  同时Q按照某个字D进行排序的时候,无论是正序还是倒序Q速度是基本相当的?


  12、高效的TOP

  事实上,在查询和提取大定w的数据集Ӟ影响数据库响应时间的最大因素不是数
据查找,而是物理的I/0操作。如Q?

select top 10 * from (

select top 10000 gid,fariqi,title from tgongwen

where neibuyonghu='办公?

order by gid desc) as a

order by gid asc

  q条语句Q从理论上讲Q整条语句的执行旉应该比子句的执行旉长,但事实相?br />。因为,子句执行后返回的?0000条记录,而整条语句仅q回 10条语句,所以媄响数?br />库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效Ҏ之一是?br />用TOP关键词了。TOP关键词是 SQL SERVER中经q系l优化过的一个用来提取前几条或前?br />个百分比数据的词。经W者在实践中的应用Q发现TOP实很好用,效率也很高。但q个?br />在另外一个大型数据库ORACLE中却没有Q这不能说不是一个遗憾,虽然在ORACLE中可以用
其他ҎQ如QrownumberQ来解决。在以后的关于“实现千万数据的分|C存储过E?br />”的讨论中,我们将用到TOPq个关键词?

  到此为止Q我们上面讨Z如何实现从大定w的数据库中快速地查询出您所需要的?br />据方法。当Ӟ我们介绍的这些方法都是“Y”方法,在实践中Q我们还要考虑各种“硬
”因素,如:|络性能、服务器的性能、操作系l的性能Q甚至网卡、交换机{?

三、实现小数据量和量数据的通用分页昄存储q程

  建立一个web 应用Q分|览功能必不可。这个问题是数据库处理中十分常见的问
题。经典的数据分页Ҏ?ADO U录集分|Q也是利用ADO自带的分功能(利用?br />标)来实现分c但q种分页Ҏ仅适用于较数据量的情形,因ؓ游标本n有缺点:?br />标是存放在内存中Q很费内存。游标一建立Q就相关的记录锁住Q直到取消游标。游?br />提供了对特定集合中逐行扫描的手D,一般用游标来逐行遍历数据Q根据取出数据条?br />的不同进行不同的操作。而对于多表和大表中定义的游标Q大的数据集合)循环很容易
E序q入一个O长的{待甚至L?

  更重要的是,对于非常大的数据模型而言Q分|索时Q如果按照传l的每次都加?br />整个数据源的Ҏ是非常浪费资源的。现在流行的分页Ҏ一般是索页面大的块区?br />数据Q而非索所有的数据Q然后单步执行当前行?

  最早较好地实现q种Ҏ面大小和页码来提取数据的方法大概就是“俄|斯存储q?br />E”。这个存储过E用了游标,׃游标的局限性,所以这个方法ƈ没有得到大家的普?br />认可?

  后来Q网上有人改造了此存储过E,下面的存储过E就是结合我们的办公自动化实?br />写的分页存储q程Q?

CREATE procedure pagination1

(@pagesize int,  --面大小Q如每页存储20条记?

@pageindex int   --当前늠

)

as

set nocount on

begin

declare @indextable table(id int identity(1,1),nid int)  --定义表变?

declare @PageLowerBound int  --定义此页的底?

declare @PageUpperBound int  --定义此页的顶?

set @PageLowerBound=(@pageindex-1)*@pagesize

set @PageUpperBound=@PageLowerBound+@pagesize

set rowcount @PageUpperBound

insert into @indextable(nid) select gid from TGongwen where fariqi >dateadd(da
y,-365,getdate()) order by fariqi desc

select O.gid,O.mid,O.title,O.fadanwei,O.fariqi from TGongwen O,@indextable t w
here O.gid=t.nid

and t.id>@PageLowerBound and t.id<=@PageUpperBound order by t.id

end

set nocount off

  以上存储q程q用了SQL SERVER的最新技术――表变量。应该说q个存储q程也是一
个非怼U的分存储过E。当Ӟ在这个过E中Q您也可以把其中的表变量写成临时?br />Q?CREATE TABLE #Temp。但很明显,在SQL SERVER中,用时表是没有用表变量快的。所
以笔者刚开始用这个存储过E时Q感觉非常的不错Q速度也比原来的ADO的好。但后来Q?br />我又发现了比此方法更好的Ҏ?

  W者曾在网上看C一小短文《从数据表中取出Wn条到Wm条的记录的方法》,?br />文如下:

从publish 表中取出W?n 条到W?m 条的记录Q?
SELECT TOP m-n+1 *
FROM publish
WHERE (id NOT IN
    (SELECT TOP n-1 id
     FROM publish))

id 为publish 表的关键?

  我当时看到这文章的时候,真的是精ؓ之一振,觉得思\非常得好。等到后来,
我在作办公自动化pȝQASP.NET+ C#QSQL SERVERQ的时候,忽然惌v了这文章,我想
如果把这个语句改造一下,q就可能是一个非常好的分存储过E。于是我满|上找这
文章,没想刎ͼ文章q没扑ֈQ却扑ֈ了一根据此语句写的一个分存储过E,q个
存储q程也是目前较ؓ行的一U分存储过E,我很后悔没有争先把这D|字改造成?br />储过E:

CREATE PROCEDURE pagination2
(
@SQL nVARCHAR(4000),    --不带排序语句的SQL语句
@Page int,              --늠
@RecsPerPage int,       --每页容纳的记录数
@ID VARCHAR(255),       --需要排序的不重复的ID?
@Sort VARCHAR(255)      --排序字段及规?
)
AS

DECLARE @Str nVARCHAR(4000)

SET @Str='SELECT   TOP '+CAST(@RecsPerPage AS VARCHAR(20))+' * FROM ('+@SQL+')
T WHERE T.'+@ID+'NOT IN
(SELECT   TOP '+CAST((@RecsPerPage*(@Page-1)) AS VARCHAR(20))+' '+@ID+' FROM (
'+@SQL+') T9 ORDER BY '+@Sort+') ORDER BY '+@Sort

PRINT @Str

EXEC sp_ExecuteSql @Str
GO

  其实Q以上语句可以简化ؓQ?

SELECT TOP 大?*

FROM Table1

WHERE (ID NOT IN

         (SELECT TOP 大?| id

        FROM ?

        ORDER BY id))

ORDER BY ID

  但这个存储过E有一个致命的~点Q就是它含有NOT IN字样。虽然我可以把它攚wؓ
Q?

SELECT TOP 大?*

FROM Table1

WHERE not exists

(select * from (select top (大?|) * from table1 order by id) b where b.
id=a.id )

order by id

  卻I用not exists来代替not inQ但我们前面已经谈过了,二者的执行效率实际上是
没有区别的?

  既便如此Q用TOP l合NOT IN的这个方法还是比用游标要来得快一些?

  虽然用not existsq不能挽救上个存储过E的效率Q但使用SQL SERVER中的TOP关键?br />却是一个非常明智的选择。因为分优化的最l目的就是避免生过大的记录集,而我?br />在前面也已经提到了TOP的优势,通过TOP 卛_实现Ҏ据量的控制?

  在分늮法中Q媄响我们查询速度的关键因素有两点QTOP和NOT IN。TOP可以提高?br />们的查询速度Q而NOT IN会减慢我们的查询速度Q所以要提高我们整个分页法的速度Q?br />pd攚wNOT INQ同其他Ҏ来替代它?

  我们知道Q几乎Q何字D,我们都可以通过max(字段)或min(字段)来提取某个字D中
的最大或最|所以如果这个字D不重复Q那么就可以利用q些不重复的字段的max或m
in作ؓ分水岭,使其成ؓ分页法中分开每页的参照物。在q里Q我们可以用操作W?gt;?br />或?lt;”号来完成这个命,使查询语句符合SARG形式。如Q?

Select top 10 * from table1 where id>200

  于是有了如下分|案:

select top 大?*

from table1

where id>

     (select max (id) from

     (select top ((늠-1)*大? id from table1 order by id) as T

      )    

order by id

  在选择即不重复|又容易分辨大的列时Q我们通常会选择主键。下表列ZW?br />用有着1000万数据的办公自动化系l中的表Q在以GID QGID是主键,但ƈ不是聚集索引?br />Qؓ排序列、提取gid,fariqi,title字段Q分别以W??0?00?00?000?万?0 ?br />?5万?0万页ZQ测试以上三U分|案的执行速度Q(单位Q毫U)

??
Ҏ1
Ҏ2
Ҏ3

1
60
30
76

10
46
16
63

100
1076
720
130

500
540
12943
83

1000
17110
470
250

1?
24796
4500
140

10?
38326
42283
1553

25?
28140
128720
2330

50?
121686
127846
7168


  从上表中Q我们可以看出,三种存储q程在执?00以下的分页命oӞ都是可以?br />ȝQ速度都很好。但W一U方案在执行分页1000以上后Q速度降了下来。第二种?br />案大U是在执行分?万页以上后速度开始降了下来。而第三种Ҏ却始l没有大的降势,
后劲仍然很?

  在确定了W三U分|案后Q我们可以据此写一个存储过E。大家知道SQL SERVER?br />存储q程是事先编译好的SQL语句Q它的执行效率要比通过WEB面传来的SQL语句的执行效
率要高。下面的存储q程不仅含有分页ҎQ还会根据页面传来的参数来确定是否进行数
据Ll计?

-- 获取指定늚数据

CREATE PROCEDURE pagination3

@tblName   varchar(255),       -- 表名

@strGetFields varchar(1000) = '*',  -- 需要返回的?

@fldName varchar(255)='',      -- 排序的字D名

@PageSize   int = 10,          -- 尺?

@PageIndex  int = 1,           -- 늠

@doCount  bit = 0,   -- q回记录L, ?0 值则q回

@OrderType bit = 0,  -- 讄排序cd, ?0 值则降序

@strWhere  varchar(1500) = ''  -- 查询条g (注意: 不要?where)

AS

declare @strSQL   varchar(5000)       -- 主语?

declare @strTmp   varchar(110)        -- 临时变量

declare @strOrder varchar(400)        -- 排序cd



if @doCount != 0

begin

   if @strWhere !=''

   set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@st
rWhere

   else

   set @strSQL = "select count(*) as Total from [" + @tblName + "]"

end

--以上代码的意思是如果@doCount传递过来的不是0Q就执行Ll计。以下的所有代码都
是@doCount?的情?

else

begin



if @OrderType != 0

begin

   set @strTmp = "<(select min"

set @strOrder = " order by [" + @fldName +"] desc"

--如果@OrderType不是0Q就执行降序Q这句很重要Q?

end

else

begin

   set @strTmp = ">(select max"

   set @strOrder = " order by [" + @fldName +"] asc"

end



if @PageIndex = 1

begin

   if @strWhere != ''  

   set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from ["
+ @tblName + "] where " + @strWhere + " " + @strOrder

    else

    set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from [
"+ @tblName + "] "+ @strOrder

--如果是第一就执行以上代码Q这样会加快执行速度

end

else

begin

--以下代码赋予了@strSQL以真正执行的SQL代码

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from ["

   + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "])
from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "] from
[" + @tblName + "]" + @strOrder + ") as tblTmp)"+ @strOrder



if @strWhere != ''

   set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from ["


       + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["

       + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + "
["

       + @fldName + "] from [" + @tblName + "] where " + @strWhere + " "

       + @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder

end

end  

exec (@strSQL)

GO

  上面的这个存储过E是一个通用的存储过E,其注释已写在其中了?

  在大数据量的情况下,特别是在查询最后几늚时候,查询旉一般不会超q?U;?br />用其他存储过E,在实践中׃D时Q所以这个存储过E非帔R用于大定w数据库的
查询?

  W者希望能够通过对以上存储过E的解析Q能l大家带来一定的启示Qƈl工作带?br />一定的效率提升Q同时希望同行提出更优秀的实时数据分늮法?

四、聚集烦引的重要性和如何选择聚集索引

  在上一节的标题中,W者写的是Q实现小数据量和量数据的通用分页昄存储q程
。这是因为在本存储q程应用于“办公自动化”系l的实践中时Q笔者发现这W三U存
储过E在数据量的情况下Q有如下现象Q?

  1、分速度一般维持在1U和3U之间?

  2、在查询最后一|Q速度一般ؓ5U至8U,哪怕分|L只有3|30万页?

  虽然在超大容量情况下Q这个分늚实现q程是很快的Q但在分前几|Q这?Q?
U的速度比vW一U甚x有经q优化的分页Ҏ速度q要慢,借用L话说是“还?br />有ACCESS数据库速度快”,q个认识以D用户攑ּ使用您开发的pȝ?

  W者就此分析了一下,原来产生q种现象的症l是如此的简单,但又如此的重要:?br />序的字段不是聚集索引Q?

  本篇文章的题目是Q“查询优化及分页法Ҏ”。笔者只所以把“查询优化”和?br />分页法”这两个联系不是很大的论题放在一P是因ؓ二者都需要一个非帔R要的?br />襎쀕―聚集烦引?

  在前面的讨论中我们已l提CQ聚集烦引有两个最大的优势Q?

  1、以最快的速度~小查询范围?

  2、以最快的速度q行字段排序?

  W?条多用在查询优化Ӟ而第2条多用在q行分页时的数据排序?

  而聚集烦引在每个表内又只能徏立一个,q得聚集烦引显得更加的重要。聚集烦?br />的挑选可以说是实现“查询优化”和“高效分”的最关键因素?

  但要既聚集索引列既W合查询列的需要,又符合排序列的需要,q通常是一个矛?br />?

  W者前面“烦引”的讨论中,fariqiQ即用户发文日期作ؓ了聚集烦引的起始列,
日期的精度为“日”。这U作法的优点Q前面已l提CQ在q行划时间段的快速查?br />中,比用ID主键列有很大的优ѝ?

  但在分页Ӟ׃q个聚集索引列存在着重复记录Q所以无法用max或min来最为分
늚参照物,q而无法实现更为高效的排序。而如果将ID主键列作集烦引,那么聚集
索引除了用以排序之外Q没有Q何用处,实际上是费了聚集烦引这个宝늚资源?

   册个矛盾,W者后来又d了一个日期列Q其默认gؓgetdate()。用户在?br />入记录时Q这个列自动写入当时的时_旉_到毫U。即使这PZ避免可能性很
的重合Q还要在此列上创建UNIQUEU束。将此日期列作ؓ聚集索引列?

  有了q个旉型聚集烦引列之后Q用户就既可以用q个列查扄户在插入数据时的?br />个时间段的查询,又可以作为唯一列来实现max或minQ成为分늮法的参照物?

  l过q样的优化,W者发玎ͼ无论是大数据量的情况下还是小数据量的情况下,分页
速度一般都是几十毫U,甚至0毫秒。而用日期D늾范围的查询速度比原来也没有Mq?br />钝?

  聚集索引是如此的重要和珍贵,所以笔者ȝ了一下,一定要聚集烦引徏立在Q?


  1、您最频繁使用的、用以羃查询范围的字段上;

  2、您最频繁使用的、需要排序的字段上?

  l束语:

  希望q篇文章不仅能够l大家的工作带来一定的帮助Q也希望能让大家能够体会到分
析问题的ҎQ最重要的是Q希望这文章能够抛砖引玉,掀起大家的学习和讨论的兴趣
Q以共同促进?
  最后需要说明的是,在试验中Q发现用户在q行大数据量查询的时候,Ҏ据库速度
影响最大的不是内存大小Q而是CPU。在我的P4 2.4机器上试验的时候,查看“资源管理器
”,CPUl常出现持箋?00%的现象,而内存用量却q没有改变或者说没有大的改变。即?br />在我们的HP ML 350 G3服务器上试验ӞCPU峰g能达?0%Q一般持l在70%左右?

  本文的试验数据都是来自我们的HP ML 350服务器。服务器配置Q双Inter Xeon 线
E?CPU 2.4GQ内?GQ操作系lWindows Server 2003 Enterprise EditionQ数据库SQL
Server 2000 SP3?

转蝲完毕.


作者补?
1.columns in('aa','bb')
他等于columns = 'aa' or columns ='bb' 他先L询columns ='aa'攑֜一个时的I间
?然后{columns ='bb'查询完后,做个or查询得出l果.
至于效率的话Q在columns建立索引的话, columns ='aa' or columns ='bb'要来的效率高

语法分析器会columns in('aa','bb')转化
为columns ='aa' or columns ='bb'来执行。我们期望它会根据每个or子句分别查找Q再
结?
相加Q这样可以利用columns 上的索引Q但实际上(ҎshowplanQ?它却采用?OR{略
"
Q即先取出满x个or子句的行Q存入时数据库的工作表中,再徏立唯一索引以去?

重复行,最后从q个临时表中计算l果。因此,实际q程没有利用columns 上烦引,q且
?
成时间还要受tempdb数据库性能的媄响?


2.效率从高C count(1)>count(*)>count([id])

3.select max(cols) from table1 的效?gt;= select top 1 cols from table1 order by
cols desc

4.在where 做ƈ列条件句?where cols1='aa' and cols2='bb'
如果cols1 ='aa' ?5% cols2?%的话Q把cols2='bb'攑֜前面 ,因ؓ他在索cols ='
bb'的时候他只需查那5%,然后条g成立的话Q去在这5%的纪录里
L找cols1 ='aa'

5.避免用if条g?可以用or来替?
declare @vsql varchar(200)
set @vsql ='Renaski'
select * from titles where  @vsql ='Renaski' or price = 11.9500

如果@vsql为Renaski则把所有的U录都选出?如果不是的话Q则只查询price = 11.9500
的纪?

6.M对列的操作都导致表扫描Q它包括数据库函数、计表辑ּ{等Q查询时
要尽可能操作移至等号右辏V?

7.量避免使用游标.
如果使用了游标,p量避免在游标@环中再进行表q接的操?

8.取一个表的纪录数
Select rows from sysindexes where id=object_id(N'titles') and indid<2
效率?
select count(1) from titles来的?


9.取的一个表的数据信?
SELECT
表名=case when a.colorder=1 then d.name else '' end,
表说?case when a.colorder=1 then isnull(f.value,'') else '' end,
字段序号=a.colorder,
字段?a.name,
标识=case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '?else '' en
d,
主键=case when exists(SELECT 1 FROM sysobjects where xtype='PK' and name in (

SELECT name FROM sysindexes WHERE indid in(
SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid
))) then '? else '' end,
cd=b.name,
占用字节?a.length,
长度=COLUMNPROPERTY(a.id,a.name,'PRECISION'),
数位数=isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
允许I?case when a.isnullable=1 then '?else '' end,
默认?isnull(e.text,''),
字段说明=isnull(g.[value],''),
索引名称=isnull(h.索引名称,''),
索引序=isnull(h.排序,'')
FROM syscolumns a
left join systypes b on a.xtype=b.xusertype
inner join sysobjects d on a.id=d.id and d.xtype='U' and d.status>=0
left join syscomments e on a.cdefault=e.id
left join sysproperties g on a.id=g.id and a.colid=g.smallid
left join sysproperties f on d.id=f.id and f.smallid=0
left join(--q部分是索引信息,如果要显C烦引与表及字段的对应关p?可以只要此部?br />
select 索引名称=a.name,c.id,d.colid
,排序=case indexkey_property(c.id,b.indid,b.keyno,'isdescending')
when 1 then '降序' when 0 then '升序' end
from sysindexes a
join sysindexkeys b on a.id=b.id and a.indid=b.indid
join (--q里的作用是有多个烦引时,取烦引号最的那个
select id,colid,indid=min(indid) from sysindexkeys
group by id,colid) b1 on b.id=b1.id and b.colid=b1.colid and b.indid=b1.indid

join sysobjects c on b.id=c.id and c.xtype='U' and c.status>=0
join syscolumns d on b.id=d.id and b.colid=d.colid
where a.indid not in(0,255)
) h on a.id=h.id and a.colid=h.colid
--where d.name='要查询的? --如果只查询指定表,加上此条?
order by a.id,a.colorder


10.创徏一个表l构.
select * into #b from authors where 1=2;
注意:
#table1
##table1
@table1

局部时表
以一个井P#Q开头的那些表名。只有在创徏本地临时表的q接上才能看到这些表?

全局临时?
以两个井P##Q开头的那些表名。在所有连接上都能看到全局临时表。如果在创徏全局
临时表的q接断开前没有显式地除去q些表,那么只要所有其它Q务停止引用它们,q些
表即被除厅R当创徏全局临时表的q接断开后,新的d不能再引用它们。当前的语句一
执行完,d与表之间的关联即被除去;因此通常情况下,只要创徏全局临时表的q接?br />开Q全局临时表即被除厅R?

@?有和不同Q@@在内存,#在硬盘。我的体会是只要方便且数据量不大Q用@@?

11.视图
他只是记住要q接,兌列的信息,他不存放M物理数据.
在调用的时候他q是d各个表中的数?

12.量不要用text属?
pȝZ专门开辟一个空间来存放.
用t-sql/varchar替代
pl/sql  varchar2 替代.

13
GO语句是个命o识别q过osql和isql和SQL 查询分析器非T-SQL语句q行识别?
如果你用查询分析器作ؓ你的d发工P其他语句和库文g不会识别GO语句作ؓ一
个T-SQL命o

14.
用exec 效率来的?
declare @sql nvarchar(300)
  set @sql='select * from titles'
execute sp_executesql @sql

15,注意你的tempdb,使他自动增长.

16 使用no_log
select * from titles no_logs

17M重复U录?量用dictinct

18.量避免反复讉K同一张或几张表,其是数据量较大的表Q可以考虑先根据条件提?br />数据C时表中,然后再做q接?


19 量使用?gt;=”,不要使用?gt;”?他会扑ֈ某个定的数字进行筛??gt;则没?


20注意表之间连接的数据cdQ避免不同类型数据之间的q接?

21.可用ASE调优命oQset statistics io on, set statistics time on , set showpla
n on {?q行优化

22.truncate table 删除数据
而不是delete from table


?死锁

像SQL server一L关系数据库用锁来防止用户“互相踩到对方的脚趾头”。也是?br />Q锁可以防止用户造成修改数据时的撞。当一个用户锁住一D代码时候,其它的用户都
不能修改q段数据。另外,一个锁L了用戯看未被授权的数据修改。用户必ȝ待到
数据修改q保存之后才能够查看它。数据必M用不同的Ҏ来加锁。SQL Server 2000?br />用锁来实现多用户同时修改数据库同一数据时的同步控制
如果数据量超q?00个数据页面(400kQ,那么pȝ会q行锁升U,锁会升成表U?br />锁?  


死锁
一个数据库的死锁是发生在两个或多于两个讉K一些资源的数据库会话中的,q且q些?br />话相互之间有依赖关系。死锁是可以在Q意一个多U程的系l成出现的一个情况,不仅?br />局限于关系数据库管理系l。一个多U程pȝ中的U程可能需要一个或多个资源(例如Q锁
)。如果申L资源正在被另外一个线E所使用Q那么第一个线E就需要等待持有该资源?br />U程的释攑֮所需要的资源。假讄待线E持有一个那个正拥有U程所依赖的资源。下?br />的这一D代码就可以造成死锁异常现象的发生:
System.Data.SqlClient.SqlException: Transaction (Process ID 12) was deadlocked
on lock resources with another process and has been chosen as the deadlock vi
ctim. Rerun the transaction.

当一个SQL Server的调用和另外一个资源发生冲H时׃抛出异常Q这个资源持有一个必
要的资源。结果是Q一个进E就被终止了。当q程的IDh为系l的唯一标识的时候,q?br />会是一个很q_死锁的消息错误?


锁的cd
一个数据库pȝ在许多情况下都有可能锁数据项。其可能性包括:

Rows—数据库表中的一整行
Pages—行的集合(通常为几kbQ?
Extents—通常是几个页的集?
Table—整个数据库?
Database—被锁的整个数据库表

除非有其它的说明Q数据库Ҏ情况自己选择最好的锁方式。不q值得感谢的是QSQL Se
rver提供了一U避免默认行为的Ҏ。这是由锁提C来完成的?


提示
或许你有q许多如下的l历Q需要重设SQL Server的锁计划Qƈ且加强数据库表中锁范?br />。TansactQSQL提供了一pd不同U别的锁提示Q你可以在SELECT,INSERT, UPDATE和DEL
ETE中用它们来告诉SQL Server你需要如何通过重设M的系l或事务U别来锁表格。可
以实现的提示包括Q?

FASTFIRSTROW—选取l果集中的第一行,q将其优?
HOLDLOCK—持有一个共享锁直至事务完成
NOLOCK—不允许使用׃n锁或独n锁。这可能会造成数据重写或者没有被认p回的?br />况;因此Q就有可能用到脏数据。这个提C只能在SELECT中用?
PAGLOCK—锁表格
READCOMMITTED—只d被事务确认的数据。这是SQL Server的默认行为?
READPAST—蟩q被其它q程锁住的行Q所以返回的数据可能会忽略行的内宏V这也只能在
SELECT中用?
READUNCOMMITTED—等价于NOLOCK.
REPEATABLEREAD—在查询语句中,Ҏ有数据用锁。这可以防止其它的用h新数据,
但是新的行可能被其它的用h入到数据中,q且被最新访问该数据的用戯取?
ROWLOCK—按照行的别来Ҏ据上锁。SQL Server通常锁到|者表U别来修改行Q所?br />当开发者用单行的时候,通常要重设这个设|?
SERIALIZABLE—等价于HOLDLOCK.
TABLOCK—按照表U别上锁。在q行多个有关表别数据操作的时候,你可能需要用到q?br />个提C?
UPDLOCK—当d一个表的时候,使用更新锁来代替׃n锁,q且保持一直拥有这个锁直至
事务l束。它的好处是Q可以允怽在阅L据的时候可以不需要锁Qƈ且以最快的速度
更新数据?
XLOCK—给所有的资源都上独n锁,直至事务l束?

对于数据库死锁,通常可以通过TRACE FLAG 1204?205?206Q检查ERRORLOG里面的输?br />Q和分析SQLTRACE的执行上下文判断死锁问题的来由?
TRACEON函数的第三个参数讄?1Q表CZ单单针对当前connectionQ而是针对所有包?br />未来建立的connection。这P才够完全Q否则只是监视当前已l徏立的数据库连接了?br />


执行下面的话可以把死锁记录到Errorlog中:

dbcc traceon (1204, 3605, -1)
go
dbcc tracestatus(-1)
go

 

得到的输ZؓQ?
DBCC 执行完毕。如?DBCC 输出了错误信息,请与pȝ理员联pR?
TraceFlag Status
--------- ------
1204      1
1205      1
3605      1

Q所影响的行Cؓ 3 行)

DBCC 执行完毕。如?DBCC 输出了错误信息,请与pȝ理员联pR?


此后Q你可以查看数据库的例行日志Q每隔一D|_数据库都会检查死?
2004-01-16 18:34:38.50 spid4     ----------------------------------
2004-01-16 18:34:38.50 spid4     Starting deadlock search 1976



2004-01-16 18:34:38.50 spid4     Target Resource Owner:
2004-01-16 18:34:38.50 spid4      ResType:LockOwner Stype:'OR' Mode: U SPID:55
ECID:0 Ec:(0xAA577570) Value:0x4c25cba0
2004-01-16 18:34:38.50 spid4      Node:1  ResType:LockOwner Stype:'OR' Mode: U
SPID:55 ECID:0 Ec:(0xAA577570) Value:0x4c25cba0
2004-01-16 18:34:38.50 spid4      Node:2  ResType:LockOwner Stype:'OR' Mode: U
SPID:71 ECID:0 Ec:(0xABF07570) Value:0x9bd0ba00
2004-01-16 18:34:38.50 spid4    
2004-01-16 18:34:38.50 spid4     -- next branch --
2004-01-16 18:34:38.50 spid4      Node:2  ResType:LockOwner Stype:'OR' Mode: U
SPID:71 ECID:0 Ec:(0xABF07570) Value:0x9bd0ba00
2004-01-16 18:34:38.50 spid4    
2004-01-16 18:34:38.50 spid4    
2004-01-16 18:34:38.50 spid4     End deadlock search 1976 ... a deadlock was n
ot found.
2004-01-16 18:34:38.50 spid4     ----------------------------------

DBCC TRACEON打开Q启用)指定的跟t标记?

注释跟踪标记用于自定义某些控?Microsoft? SQL Server? 操作方式的特性。跟t标?br />在服务器中一直保持启用状态,直到通过执行 DBCC TRACEOFF 语句对其用为止。在发出
DBCC TRACEON 语句之前Q连入到服务器的新连接看不到M跟踪标记。一旦发语句
Q该q接p看到服务器中当前启用的所有跟t标讎ͼ即ɘq些标记是由其它q接启用Q?br />?
跟踪标记跟踪标记用于临时讄服务器的特定特征或关闭特定行为。如果启?Microsoft
? SQL Server 时设|了跟踪标记 3205Q将用带驱动E序的硬件压~。跟t标记经?br />用于诊断性能问题Q或调试存储q程或复杂的计算机系l?
下列跟踪标记?SQL Server 中可用。跟t标?描述 1204 q回参与死锁的锁的类型以?br />当前受媄响的命o?
实际上可以在“错?1000 -1999”中扑ֈ他们Q?
1204 19 SQL Server 此时无法获取 LOCK 资源。请在活动用h较少旉新运行您的语?br />Q或者请求系l管理员?SQL Server 锁和内存配置?
1205 13 事务Q进E?ID %1!Q与另一个进E已被死锁在资源 {%2!} 上,且该事务已被?br />作死锁牺牲品。请重新q行该事务?
1206 18 事务理器已取消了分布式事务?

需要指出的是对锁的升,完全是由pȝ自行判断?而非Zؓ.如果要避免死锁的话,其根
本还在与数据库的设计?br />



weibogao 2007-01-12 12:56 发表评论
]]>
转《数据库设计l验?/title><link>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93125.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 11 Jan 2007 04:09:00 GMT</pubDate><guid>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93125.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/93125.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93125.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/93125.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/93125.html</trackback:ping><description><![CDATA[ <h3 class="title"> </h3> <p>2004-11-24微Y技术博?</p> <p>作者: wjk.net(转蝲)</p> <p>一个成功的理pȝQ是由:[50% 的业?+ 50% 的Y件] 所l成Q?50% 的成功Y件又?[25% 的数据库 + 25%的程序] 所l成Q数据库设计的好坏是一个关键。如果把企业的数据比做生?所必需的血Ԍ那么数据库的设计是应用中最重要的一部分 。有x据库设计的材料汗牛充栋,大学学位评里也有专门的讲述 。不q,如我们反复的那P再好的老师也比不过l验的教?。所以我归纳历年来所走的弯\及体会,q在|上找了些对数据库设 计颇有造诣的专业h士给大家传授一些设计数据库的技巧和l验 。精选了其中?0 个最x巧,q把q些技巧编写成了本文,Z方便索引其内容划??5 个部分:</p> <p> <br /> </p> <p>W?1 部分 - 设计数据库之?</p> <p>q一部分|列?12 个基本技巧,包括命名规范和明业务需求等?</p> <p>W?2 部分 - 设计数据库表 </p> <p>d 24 个指南性技巧,늛表内字段设计以及应该避免的常见问题等?</p> <p>W?3 部分 - 选择?</p> <p>怎么选择键呢Q这里有 10 个技巧专门涉及系l生成的主键的正用法,q有?时以及如何烦引字D以获得最x能{?</p> <p>W?4 部分 - 保证数据完整?</p> <p>讨论如何保持数据库的清晰和健壮,如何把有x据降低到最程??</p> <p>W?5 部分 - 各种技?</p> <p>不包括在以上 4 个部分中的其他技巧,五花八门Q有了它们希望你的数据库开发工?会更L一些?</p> <p> <br />W?1 部分 - 设计数据库之?</p> <p> <br />考察现有环境 </p> <p>在设计一个新数据库时Q你不但应该仔细研究业务需求而且q要考察 现有的系l。大多数数据库项目都不是从头开始徏立的Q通常 Q机构内M存在用来满特定需求的现有pȝQ可能没有实现自?计算Q。显Ӟ现有pȝq不完美Q否则你׃必再建立新系l了 。但是对旧系l的研究可以让你发现一些可能会忽略的细微问?。一般来_考察现有pȝ对你l对有好处?</p> <p>定义标准的对象命名规?</p> <p>一定要定义数据库对象的命名规范。对数据库表来说 Q从目一开始就要确定表名是采用复数q是单数形式 。此外还要给表的别名定义单规则(比方_如果表名是一个单?Q别名就取单词的? 个字母;如果表名是两个单词,各取两个单词的前两个字母组?4 个字母长的别名;如果表的名字?3个单词组成,你不妨从头两个单词中各取一个然后从最后一个单词中 再取Z个字母,l果q是l成 4字母长的别名Q其余依ơ类推)对工作用表来_表名可以加上前缀 WORK_后面附上采用该表的应用程序的名字。表内的列[字段 ]要针寚w采用一整套设计规则。比如,如果键是数字cd Q你可以?_N作ؓ后缀Q如果是字符cd则可以采?_C后缀。对列[字段]名应该采用标准的前缀和后~。再?Q假如你的表里有好多"money"字段Q你不妨l每个列[字段 ]增加一?_M后缀。还有,日期列[字段]最好以 D_ 作ؓ名字打头?/p> <p>查表名、报表名和查询名之间的命名规范。你可能会很快就被这?不同的数据库要素的名U搞p涂了。假如你坚持l一地命名这些数?库的不同l成部分Q至你应该在这些对象名字的开头用Table、Query 或?Report {前~加以区别?/p> <p>如果采用?Microsoft AccessQ你可以?qry、rpt、tbl ?mod {符h标识对象Q比如tbl_EmployeesQ。我在和 SQL Server 打交道的时候还用过 tbl 来烦引表Q但我用 sp_company Q现在用 sp_feft_Q标识存储过E,因ؓ在有的时候如果我发现了更 好的处理办法往往会保存好几个拯。我在实?SQL Server 2000 时用udf_ Q或者类似的标记Q标识我~写的函数?</p> <p> <br />工欲善其? 必先利其?</p> <p>采用理想的数据库设计工具Q比如:SyBase 公司?PowerDesignQ她支持 PB、VB、Delphe {语aQ通过 ODBC可以q接市面上流行的 30 多个数据库,包括 dBase、FoxPro、VFP、SQL Server {,今后有机会我着重介lPowerDesign 的用?</p> <p>获取数据模式资源手册 </p> <p>正在LCZ模式的h可以阅读《数据模式资源手册》一书,该书?Len Silverston、W. H. Inmon ?Kent Graziano ~写Q是一本值得拥有的最x据徏模图书。该书包括的章节늛?U数据领域,比如人员、机构和工作效能{。其他的你还可以参考: [1]萨师煊王珊著数据库系l概?W二?高等教育出版C?1991、[2][] Steven M.Bobrowski ?Oracle 7<br />与客P服务器计技术从入门到精通刘建元{译电子工业出版C,1996、[3]周中元信息系l徏模方??电子与信息化1999q第3期,1999畅想未来Q但不可忘了q去的教训我发现询问用户如何看待未来需求变化非常有用。这样做可以辑ֈ?个目的:首先Q你可以清楚C解应用设计在哪个地方应该更具灉| 性以及如何避免性能瓉Q其ơ,你知道发生事先没有确定的需求变 更时用户和你一h到吃惊?/p> <p>一定要Cq去的经验教训!我们开发h员还应该通过分n自己的体 会和l验互相帮助。即使用戯Z们再也不需要什么支持了 Q我们也应该对他们进行这斚w的教Ԍ我们都曾l面临过q样的时 ?当初要是q么做了该多?."?</p> <p>在物理实践之前进行逻辑设计 </p> <p>在深入物理设计之前要先进行逻辑设计。随着大量?CASE工具不断涌现出来Q你的设计也可以辑ֈ相当高的逻辑水准 Q你通常可以从整体上更好C解数据库设计所需要的Ҏ面面?</p> <p>了解你的业务 </p> <p>在你癑ֈ癑֜定pȝ从客戯度满_需求之前不要在你的 ERQ实体关p)模式中加入哪怕一个数据表Q怎么Q你q没有模?Q那请你参看技?Q。了解你的企业业务可以在以后的开发阶D节U大量的旉 。一旦你明确了业务需求,你就可以自己做出许多决策了?/p> <p>一旦你认ؓ你已l明了业务内容Q你最好同客户q行一ơ系l的?。采用客L术语q且向他们解释你所惛_的和你所听到?。同时还应该用可能、将会和必须{词汇表辑ևpȝ的关pd?。这样你可以让你的客户U正你自q理解然后做好下一步的ER 设计?</p> <p>创徏数据字典?ER 图表 </p> <p>一定要q旉创徏 ER 图表和数据字典。其中至应该包含每个字D늚数据cd和在每个?内的d键。创?ER<br />图表和数据字典确实有点费时但对其他开发h员要了解整个设计却是 完全必要的。越早创能有助于避免今后面的可能؜?Q从而可以让M了解数据库的人都明确如何从数据库中获得数据?/p> <p>有一份诸?ER 图表{最新文档其重要性如何强调都不过分,q对表明表之间关pd 有用Q而数据字典则说明了每个字D늚用途以及Q何可能存在的别名 。对SQL 表达式的文档化来说这是完全必要的?</p> <p>创徏模式 </p> <p>一张图表胜q千a万语Q开发h员不仅要阅读和实现它 Q而且q要用它来帮助自己和用户对话。模式有助于提高协作效能 Q这样在先期的数据库设计中几乎不可能出现大的问题 。模式不必弄的很复杂Q甚臛_以简单到手写在一张纸上就可以?。只是要保证其上的逻辑关系今后能生效益?</p> <p>从输入输Z?</p> <p>在定义数据库表和字段需求(输入Q时Q首先应查现有的或者已l?设计出的报表、查询和视图Q输出)以决定ؓ了支持这些输出哪些是 必要的表和字DcD个简单的例子Q假如客户需要一个报表按照邮?~码排序、分D和求和Q你要保证其中包括了单独的邮政编码字D?不要把邮政编码糅q地址字段里?</p> <p>报表技?</p> <p>要了解用户通常是如何报告数据的Q批处理q是在线提交报表 Q时间间隔是每天、每周、每月、每个季度还是每q?Q如果需要的话还可以考虑创徏ȝ表。系l生成的主键在报表中?隄理。用户在hpȝ生成主键的表内用副键q行索往往会返?许多重复数据。这L索性能比较低而且Ҏ引v混ؕ?</p> <p>理解客户需?</p> <p>看v来这应该是显而易见的事,但需求就是来自客?Q这里要从内部和外部客户的角度考虑Q。不要依赖用户写下来的需 求,真正的需求在客户的脑袋里。你要让客户解释光?Q而且随着开发的l箋Q还要经常询问客户保证其需求仍然在开发的 目的之中。一个不变的真理是:"只有我看见了我才知道我想要的?什?必然会导致大量的q工Q因为数据库没有辑ֈ客户从来没有?下来的需求标准。而更p的是你对他们需求的解释只属于你自己 Q而且可能是完全错误的?</p> <p> <br />W?2 部分 - 设计表和字段 </p> <p> <br />查各U变?</p> <p>我在设计数据库的时候会考虑到哪些数据字D将来可能会发生变更 。比方说Q姓氏就是如此(注意是西方h的姓氏,比如x结婚后?夫姓{)。所以,在徏立系l存储客户信息时Q我們֐于在单独的一 个数据表里存储姓氏字D,而且q附加v始日和终止日{字D?Q这样就可以跟踪q一数据条目的变化?</p> <p>采用有意义的字段?</p> <p>有一回我参加开发过一个项目,其中有从其他E序员那里承的E序 Q那个程序员喜欢用屏q上昄数据指示用语命名字段Q这也不?Q但不幸的是Q她q喜Ƣ用一些奇怪的命名法,其命名采用了匈牙?命名和控制序Ll合形式Q比如cbo1、txt2、txt2_b {等?br />除非你在使用只面向你的羃写字D名的系l,否则请尽可能地把字段 描述的清楚些。当Ӟ也别做过头了Q比如Customer_Shipping_Address _Street_Line_1Q虽然很富有说明?Q但没h愿意键入q么长的名字Q具体尺度就在你的把握中?br />采用前缀命名。如果多个表里有好多同一cd的字D(比如 FirstNameQ,你不妨用特定表的前缀Q比?CusLastNameQ来帮助你标识字Dc?/p> <p>时效性数据应包括"最q更新日?旉"字段。时间标记对查找?据问题的原因、按日期重新处理/重蝲数据和清除旧数据特别有用?br />标准化和数据驱动数据的标准化不仅方便了自p且也方便了其他人。比方说 Q假如你的用L面要讉K外部数据源(文g、XML<br />文档、其他数据库{)Q你不妨把相应的q接和\径信息存储在用户 界面支持表里。还有,如果用户界面执行工作之cȝd Q发送邮件、打CW、修改记录状态等Q,那么产生工作的数据 也可以存攑֜数据库里。预先安排总需要付出努力,但如果这些过E?采用数据驱动而非编码的方式Q那么策略变更和l护都会方便得多 。事实上Q如果过E是数据驱动的,你就可以把相当大的责Ll用 Pqhl护自己的工作流q程?</p> <p>标准化不能过?</p> <p>寚w些不熟悉标准化一词(normalizationQ的言 Q标准化可以保证表内的字D都是最基础的要素,而这一措施有助?消除数据库中的数据冗余。标准化有好几种形式Q但Third Normal FormQ?NFQ通常被认为在性能、扩展性和数据完整性方面达 C最好^衡。简单来_3NF 规定Q?br />* 表内的每一个值都只能被表达一ơ?br />* 表内的每一行都应该被唯一的标识(有唯一键)?br />* 表内不应该存储依赖于其他键的非键信息?br />遵守 3NF 标准的数据库h以下特点Q有一l表专门存放通过键连接v来的?联数据。比方说Q某个存攑֮户及其有兛_单的 3NF<br />数据库就可能有两个表QCustomer ?Order。Order 表不包含定单兌客户的Q何信息,但表内会存放一个键?Q该键指向Customer 表里包含该客户信息的那一行?br />更高层次的标准化也有Q但更标准是否就一定更好呢Q答案是不一?。事实上Q对某些目来说Q甚臛_q?3NF 都可能给数据库引入太高的复杂性?/p> <p>Z效率的缘故,对表不进行标准化有时也是必要?Q这L例子很多。曾l有个开发餐饮分析Y件的zd是用非标准化 表把查询旉从^?40U降低到了两U左叟뀂虽然我不得不这么做Q但我绝不把数据表的?标准化当作当然的设计理念。而具体的操作不过是一U派?。所以如果表Z问题重新产生非标准化的表是完全可能的?</p> <p>Microsoft Visual FoxPro 报表技?</p> <p>如果你正在?Microsoft Visual FoxProQ你可以用对用户友好的字D名来代替编L名称 Q比如用 Customer Name 代替 txtCNaM。这P当你用向导程?[WizardsQ台湾hUCؓ'_'] 创徏表单和报表时Q其名字会让那些不是E序员的人更Ҏ阅读?</p> <p>不活跃或者不采用的指C符 </p> <p>增加一个字D表C所在记录是否在业务中不再活跃挺有用?。不是客户、员工还是其他什么hQ这样做都能有助于再q行查询 的时候过滤活跃或者不z跃状态。同时还消除了新用户在采用数据时 所面的一些问题,比如Q某些记录可能不再ؓ他们所?Q再删除的时候可以vC定的防范作用?</p> <p>使用角色实体定义属于某类别的列[字段] </p> <p>在需要对属于特定cd或者具有特定角色的事物做定义时 Q可以用角色实体来创建特定的旉兌关系Q从而可以实现自我文 档化?br />q里的含义不是让 PERSON 实体带有 Title 字段Q而是_Z么不?PERSON 实体?PERSON_TYPE实体来描qCh员呢Q比方说Q当 John Smith, Engineer 提升?John Smith, Director 乃至最后爬到John Smith, CIO 的高位,而所有你要做的不q是改变两个?PERSON ?PERSON_TYPE之间关系的键|同时增加一个日?旉字段来知道变化是何时?生的。这P你的 PERSON_TYPE 表就包含了所?PERSON的可能类型,比如 Associate、Engineer、Director 、CIO 或?CEO {?br />q有个替代办法就是改?PERSON 记录来反映新头衔的变化,不过q样一来在旉上无法跟t个人所?位置的具体时间?</p> <p>采用常用实体命名机构数据 </p> <p>l织数据的最单办法就是采用常用名字,比如QPERSON 、ORGANIZATION、ADDRESS ?PHONE{等。当你把q些常用的一般名字组合v来或者创建特定的相应副实 体时Q你得C自己用的Ҏ版本。开始的时候采用一般术语的?要原因在于所有的具体用户都能Ҏ象事物具体化?br />有了q些抽象表示Q你可以在W?2 U标识中采用自己的特D名Uͼ比如QPERSON 可能是Employee、Spouse、Patient、Client 、Customer、Vendor 或?Teacher{。同LQORGANIZATION 也可能是<br />MyCompany、MyDepartment、Competi tor、Hospital、Warehouse、Governm ent {。最后ADDRESS 可以具体?Site、Location、Home、Work、Client 、Vendor、Corporate 和FieldOffice {?br />采用一般抽象术语来标识"事物"的类别可以让你在兌数据以满?业务要求斚w获得巨大的灵zL,同时q样做还可以显著降低数据?储所需的冗余量?</p> <p>用户来自世界各地 </p> <p>在设计用到网l或者具有其他国际特性的数据库时Q一定要C大多 数国安有不同的字段格式Q比如邮政编码等Q有些国?Q比如新西兰没有邮政编码一说?</p> <p>数据重复需要采用分立的数据?</p> <p>如果你发现自己在重复输入数据Q请创徏新表和新的关pR?br />每个表中都应该添加的 3 个有用的字段<br />* dRecordCreationDateQ在 VB 下默认是 Now()Q而在 SQL Server 下默认ؓ GETDATE()<br />* sRecordCreatorQ在 SQL Server 下默认ؓ NOT NULL DEFAULT USER<br />* nRecordVersionQ记录的版本标记Q有助于准确说明 记录中出?null 数据或者丢失数据的原因<br />对地址和电话采用多个字D?br />描述街道地址q短一行记录是不够的。Address _Line1、Address_Line2 ?Address_Line3<br />可以提供更大的灵zL。还有,电话L和邮件地址最好拥有自q 数据表,光h自n的类型和标记cd?/p> <p>q分标准化可要小心,q样做可能会D性能上出现问?。虽然地址和电话表分离通常可以辑ֈ最佳状态,但是如果需要经?讉Kq类信息Q或许在其父表中存放"首?信息Q比?br />Customer {)更ؓ妥当些。非标准化和加速访问之间的妥协是有一定意义的?</p> <p>使用多个名称字段 </p> <p>我觉得很吃惊Q许多h在数据库里就l?name留一个字Dc我觉得只有刚入门的开发h员才会这么做 Q但实际上网上这U做法非常普遍。我应该把姓氏和名字当作?个字D|处理Q然后在查询的时候再把他们组合v来?/p> <p>我最常用的是在同一表中创徏一个计列[字段]Q通过它可以自?地连接标准化后的字段Q这h据变动的时候它也跟着变。不q?Q这样做在采用徏模Y件时得很机灵才行。MQ采用连接字D늚?式可以有效的隔离用户应用和开发h员界面?br />提防大小写؜用的对象名和Ҏ字符q去最令我恼火的事情之一是数据库里有大写L的对象名 Q比?CustomerData。这一问题?Access ?Oracle数据库都存在。我不喜Ƣ采用这U大写L的对象命名方?Q结果还不得不手工修改名字。想想看Q这U数据库 /应用E序能؜到采用更强大数据库的那一天吗Q采用全部大写而且 包含下划W的名字h更好的可L(CUSTOMER_DATA Q,l对不要在对象名的字W之间留I格?</p> <p>心保留?</p> <p>要保证你的字D名没有和保留词、数据库pȝ或者常用访问方法冲H?Q比如,最q我~写的一?ODBC q接E序里有个表Q其中就用了 DESC作ؓ说明字段名。后果可惌知QDESC ?DESCENDING ~写后的保留词。表里的一?SELECT *语句倒是能用Q但我得到的却是一大堆毫无用处的信息?</p> <p>保持字段名和cd的一致?</p> <p>在命名字Dƈ为其指定数据cd的时候一定要保证一致?。假如字D在某个表中叫做"agreement_number" Q你别在另一个表里把名字Ҏ"ref1"。假如数据类型在一 个表里是整数Q那在另一个表里可别变成字符型了。记?Q你q完自己的活了,其他要用你的数据库呢?</p> <p>仔细选择数字cd </p> <p>?SQL 中?smallint ?tinyint cd要特别小心,比如Q假如你想看看月销售总额Q你的总额字段c?型是smallintQ那么,如果总额过?$32,767 你就不能q行计算操作了?</p> <p>删除标记 </p> <p>在表中包含一?删除标记"字段Q这样就可以把行标记为删?。在关系数据库里不要单独删除某一行;最好采用清除数据程序而且 要仔l维护烦引整体性?</p> <p>避免使用触发?</p> <p>触发器的功能通常可以用其他方式实现。在调试E序时触发器可能?为干扰。假如你实需要采用触发器Q你最好集中对它文档化?br />包含版本机制你在数据库中引入版本控制机制来确定用中的数据库的版?。无论如何你都要实现q一要求。时间一长,用户的需求L会改?的。最l可能会要求修改数据库结构。虽然你可以通过查新字段?者烦引来定数据库结构的版本Q但我发现把版本信息直接存放到数 据库中不更ؓ方便吗? </p> <p>l文本字D늕余?</p> <p>ID cd的文本字D,比如客户 ID或定单号{等都应该设|得比一般想象更大,因ؓ旉不长你多半就 会因d额外的字W而难堪不巌Ӏ比方说Q假设你的客?ID ?10位数ѝ那你应该把数据库表字段的长度设?12 或?13 个字W长。这浪费空间吗Q是有一点,但也没你惌的那么多 Q一个字D加?3个字W在?1 百万条记录,再加上一点烦引的情况下才不过让整个数据库多占?3MB的空间。但q额外占据的I间却无需来重构整个数据库就可以实现 数据库规模的增长了。n份证的号码从 15 位变?18<br />位就是最好和最惨痛的例子?</p> <p>列[字段]命名技?</p> <p>我们发现Q假如你l每个表的列[字段]名都采用l一的前~ Q那么在~写 SQL表达式的时候会得到大大的简化。这样做也确实有~点 Q比如破坏了自动表连接工L作用Q后者把公共列[字段 ]名同某些数据库联pv来,不过pq些工具有时不也q接错误?。D个简单的例子Q假设有两个表:<br />Customer ?Order。Customer 表的前缀是cu_Q所以该表内的子D名如下Qcu_name_id、cu _surname、cu_initials 和cu_address {。Order表的前缀?or_Q所以子D名是:<br />or_order_id、or_cust_name_id、or _quantity ?or_denoscription {?br />q样从数据库中选出全部数据?SQL 语句可以写成如下所C:<br />Select * From Customer, Order Where cu_surname = "MYNAME" ;<br />and cu_name_id = or_cust_name_id and or_quantity = 1<br />在没有这些前~的情况下则写成这个样子(用别名来区分Q:<br />Select * From Customer, Order Where Customer.surname = "MYNAME" ;<br />and Customer.name_id = Order.cust_name_id and Order.quantity = 1<br />W?1 ?SQL 语句没少键入多少字符。但如果查询涉及?5 个表乃至更多的列[字段]你就知道q个技巧多有用了?</p> <p>W?3 部分 - 选择键和索引 </p> <p> <br />数据采掘要预先计?</p> <p>我所在的某一客户部门一度要处理 8万多份联pL式,同时填写每个客户的必要数据(q绝对不是小z) 。我从中q要定Zl客户作为市场目标。当我从最开始设计表?字段的时候,我试图不在主索引里增加太多的字段以便加快数据库的 q行速度。然后我意识到特定的l查询和信息采掘既不准确速度也不 快。结果只好在ȝ引中重徏而且合ƈ了数据字Dc我发现有一个指 C划相当关键——当我想创徏pȝcd查找时ؓ什么要采用L?Z索引字段呢?我可以用传真Lq行索,但是它几乎就象系l?cd一样对我来说ƈ不重要。采用后者作Z字段Q数据库更新后重 新烦引和索就快多了?/p> <p>可操作数据仓库(ODSQ和数据仓库QDWQ这两种环境下的数据 索引是有差别的。在 DW环境下,你要考虑销售部门是如何l织销售活动的。他们ƈ不是数据 库管理员Q但是他们确定表内的键信息。这里设计h员或者数据库?作h员应该分析数据库l构从而确定出性能和正输Z间的最x 件?</p> <p>使用pȝ生成的主?</p> <p>q类同技?1Q但我觉得有必要在这里重复提醒大家。假如你L在设计数据库 的时候采用系l生成的键作Z键,那么你实际控制了数据库的索引 完整性。这P数据库和非h工机制就有效地控制了对存储数据中?一行的讉K?br />采用pȝ生成键作Z键还有一个优点:当你拥有一致的键结构时 Q找到逻辑~陷很容易?</p> <p>分解字段用于索引 </p> <p>Z分离命名字段和包含字D以支持用户定义的报?Q请考虑分解其他字段Q甚至主键)为其l成要素以便用户可以对其 q行索引。烦引将加快 SQL和报表生成器脚本的执行速度。比方说Q我通常在必M?SQL LIKE 表达式的情况下创建报表,因ؓ case number 字段无法分解为year、serial number、case type ?defendant code{要素。性能也会变坏。假如年度和cd字段可以分解为烦引字D那 么这些报表运行v来就会快多了?</p> <p>键设?4 原则 </p> <p>* 为关联字D创建外键?br />* 所有的键都必须唯一?br />* 避免使用复合键?br />* 外键L兌唯一的键字段?</p> <p>别忘了烦?</p> <p>索引是从数据库中获取数据的最高效方式之一?5%的数据库性能问题都可以采用烦引技术得到解冟뀂作Z条规?Q我通常寚w辑主键使用唯一的成l烦引,对系l键Q作为存储过E?Q采用唯一的非成组索引Q对M外键列[字段]采用非成l烦?。不q,索引p是盐Q太多了菜就怺。你得考虑数据库的I间?多大Q表如何q行讉KQ还有这些访问是否主要用作读写?/p> <p>大多数数据库都烦引自动创建的主键字段Q但是可别忘了烦引外?Q它们也是经怋用的键,比如q行查询昄主表和所有关联表的某 条记录就用得上。还有,不要索引memo/note 字段Q不要烦引大型字D(有很多字W)Q这样作会让索引占用太多 的存储空间?br />不要索引常用的小型表不要为小型数据表讄M键,假如它们l常有插入和删除操作更 别这样作了。对q些插入和删除操作的索引l护可能比扫描表I间?耗更多的旉?br />不要把社会保障号码(SSNQ或w䆾证号码(IDQ选作键?br />永远都不要?SSN ?ID 作ؓ数据库的键。除了隐U原因以外,ȝ政府来趋向于不准??SSN ?ID<br />用作除收入相关以外的其他目的QSSN ?ID需要手工输入。永q不要用手工输入的键作Z?Q因Z旦你输入错误Q你唯一能做的就是删除整个记录然后从头开 始?/p> <p>我在破解他h的程序时候,我看到很多h?SSN ?IDq曾被用做系列号Q当然尽这么做是非法的。而且Z也都知道q?是非法的Q但他们已经习惯了。后来,随着盗取w䆾犯罪案g的增?Q我现在的同行正痛苦C一大摊子数据中?SSN ?ID 删除?</p> <p>不要用用L?</p> <p>在确定采用什么字D作的键的时候,可一定要心用户要~辑 的字Dc通常的情况下不要选择用户可编辑的字段作ؓ?。这样做会迫使你采取以下两个措施Q?br />* 在创录之后对用户~辑字段的行为施加限制。假如你q么做了 Q你可能会发C的应用程序在商务需求突然发生变?Q而用户需要编辑那些不可编辑的字段时缺乏够的灉|?。当用户在输入数据之后直C存记录才发现pȝZ问题他们该?么想Q删除重建?假如记录不可重徏是否让用戯开Q?br />* 提出一些检和U正键冲H的Ҏ。通常Q费点精力也搞定了 Q但是从性能上来看这样做的代价就比较大了。还?Q键的纠正可能会q你突破你的数据和商业/用户界面层之间的?R?br />所以还是重提一句老话Q你的设计要适应用户而不是让用户来适应?的设计?/p> <p>不让主键h可更新性的原因是在关系模式下,主键实现了不同表?间的兌。比如,Customer 表有一个主键CustomerIDQ而客L定单则存攑֜另一个表?。Order 表的主键可能?OrderNo 或?OrderNo、CustomerID和日期的l合。不你选择哪种键设|,你都需要在 Order 表中存放 CustomerID 来保证你可以l下定单的用h到其定单记录?br />假如你在 Customer 表里修改?CustomerIDQ那么你必须扑և Order表中的所有相兌录对其进行修攏V否则,有些定单׃不属于Q?客户——数据库的完整性就完蛋了?br />如果索引完整性规则施加到表一U,那么在不~写大量代码和附加删 除记录的情况下几乎不可能改变某一条记录的键和数据库内所有关?的记录。而这一q程往往错误丛生所以应该尽量避免?</p> <p>可选键(候选键)有时可做主键 </p> <p>CQ查询数据的不是机器而是人?br />假如你有可选键Q你可能q一步把它用做主键。那L?Q你拥有了建立强大索引的能力。这样可以阻止用数据库的h?得不q接数据库从而恰当的qo数据。在严格控制域表的数据库?Q这U负载是比较醒目的。如果可选键真正有用Q那是辑ֈ了主?的水准?br />我的看法是,假如你有可选键Q比如国家表内的state_codeQ你不要在现有不能变动的唯一键上创徏后箋 的键。你要做的无非是创徏毫无价值的数据。如你因度用表?后箋键[别名]建立q种表的兌Q操作负载真得需要考虑一下了?</p> <p>别忘了外?</p> <p>大多数数据库索引自动创徏的主键字Dc但别忘了烦引外键字D?Q它们在你想查询主表中的记录及其兌记录时每ơ都会用到。还?Q不要烦引memo/notes 字段而且不要索引大型文本字段Q许多字W)Q这样做会让你的索引 占据大量的数据库I间?</p> <p>W?4 部分 - 保证数据的完整?</p> <p>用约束而非商务规则强制数据完整?</p> <p>如果你按照商务规则来处理需求,那么你应当检查商务层?/用户界面Q如果商务规则以后发生变化,那么只需要进行更新即?。假如需求源于维护数据完整性的需要,那么在数据库层面上需要施 加限制条件。如果你在数据层实采用了约束,你要保证有办法把?C能通过U束查的原因采用用户理解的语a通知用户界面 。除非你的字D命名很冗长Q否则字D名本nq不够?/p> <p>只要有可能,请采用数据库pȝ实现数据的完整性。这不但包括通过 标准化实现的完整性而且q包括数据的功能性。在写数据的时候还?以增加触发器来保证数据的正确性。不要依赖于商务层保证数据完?性;它不能保证表之间Q外键)的完整性所以不能强加于其他完整?规则之上?</p> <p>分布式数据系l?</p> <p>对分布式pȝ而言Q在你决定是否在各个站点复制所有数据还是把?据保存在一个地方之前应该估计一下未?5 q或?10<br />q的数据量。当你把数据传送到其他站点的时候,最好在数据库字D?中设|一些标记。在目的站点收到你的数据之后更新你的标记 。ؓ了进行这U数据传输,请写下你自己的批处理或者调度程序以?定时间间隔运行而不要让用户在每天的工作后传输数?。本地拷贝你的维护数据,比如计算常数和利息率{?Q设|版本号保证数据在每个站炚w完全一致?</p> <p>强制指示完整?参照完整?) </p> <p>没有好办法能在有x据进入数据库之后消除它,所以你应该在它q?入数据库之前其剔除。激zL据库pȝ的指C完整性特?。这样可以保持数据的清洁而能q开发h员投入更多的旉处理错误条g?</p> <p>关系 </p> <p>如果两个实体之间存在多对一关系Q而且q有可能转化为多对多关系 Q那么你最好一开始就讄成多对多关系。从现有的多对一关系转变 为多对多关系比一开始就是多对多关系要难得多?</p> <p>采用视图 </p> <p>Z在你的数据库和你的应用程序代码之间提供另一层抽?Q你可以Z的应用程序徏立专门的视图而不必非要应用程序直接访 问数据表。这样做q等于在处理数据库变更时l你提供了更多的自由 ?</p> <p>l数据保有和恢复制定计划 </p> <p>考虑数据保有{略q包含在设计q程中,预先设计你的数据恢复q程 。采用可以发布给用户/开发h员的数据字典实现方便的数据识别同 时保证对数据源文档化。编写在U更新来"更新查询 "供以后万一数据丢失可以重新处理更新?br />用存储过E让pȝ做重z解决了许多ȝ来生一个具有高度完整性的数据库解x案之?Q我军_装一些关联表的功能组Q提供一整套常规的存储过E来?问各l以便加快速度和简化客L序代码的开发。数据库不只是一?存放数据的地方,它也是简化编码之地?</p> <p>使用查找 </p> <p>控制数据完整性的最x式就是限制用L选择。只要有可能都应?提供l用户一个清晰的价值列表供光择。这样将减少键入代码的错 误和误解同时提供数据的一致性。某些公共数据特别适合查找 Q国家代码、状态代码等?</p> <p> <br />W?5 部分 - 各种技?</p> <p>文档、文档、文?</p> <p>Ҏ有的快捷方式、命名规范、限制和函数都要~制文档?/p> <p>采用l表、列[字段]、触发器{加注释的数据库工具。是?Q这有点费事Q但从长q来看,q样做对开发、支持和跟踪修改非常 有用?/p> <p>取决于你使用的数据库pȝQ可能有一些Y件会l你一些供你很快上 手的文档。你可能希望先开始在_然后获得来多的细?。或者你可能希望周期性的预排Q在输入新数据同旉着你的q展?每一部分l节化。不你选择哪种方式Q总要对你的数据库文档?Q或者在数据库自w的内部或者单独徏立文档。这?Q当你过了一q多旉后再回过头来做第2 个版本,你犯错的Z大大减?</p> <p>使用常用pQ或者其他Q何语aQ而不要用编?</p> <p>Z么我们经帔R用编码(比如 9935A 可能?青岛啤酒'的供应代码,4XF788-Q可能是帐目编码)Q理由很多。但是用户通常都用pq行思考而不 是编码。工?5 q的会计或许知道 4XF788-Q是什么东西,但新来的可就不一定了。在创徏下拉菜单、列?、报表时最好按照英语名排序。假如你需要编码,那你可以在编码旁 附上用户知道的英语?</p> <p>保存常用信息 </p> <p>让一个表专门存放一般数据库信息非常有用。我常在q个表里存放?据库当前版本、最q检?修复Q对FoxProQ、关联设计文档的名称、客L信息 。这样可以实CU简单机制跟t数据库Q当客户抱怨他们的数据?没有辑ֈ希望的要求而与你联pLQ这样做寚w客户?/服务器环境特别有用?</p> <p>试、测试、反复测?</p> <p>建立或者修订数据库之后Q必ȝ用户新输入的数据试数据字段 。最重要的是Q让用户q行试q且同用户一道保证你选择的数据类 型满_业要求。测试需要在把新数据库投入实际服务之前完成?</p> <p>查设?</p> <p>在开发期间检查数据库设计的常用技术是通过其所支持的应用程序原 型检查数据库。换句话_针对每一U最l表达数据的原型应用 Q保证你查了数据模型q且查看如何取出数据?</p> <p>Microsoft Visual FoxPro 设计技?</p> <p>对复杂的 Microsoft Visual FoxPro数据库应用程序而言Q可以把所有的主表攑֜一个数据库容器文g?Q然后增加其他数据库表文件和装蝲同原有数据库有关的特D文?。根据需要用q些文gq接C文g中的主表。比如数据输?、数据烦引、统计分析、向理层或者政府部门提供报表以及各cd L询等。这一措施化了用户和组权限的分配,而且有利于应用程 序函敎ͼ存储q程Q的分组和划分,从而在E序必须修改的时候易?理?</p> <img src ="http://www.aygfsteel.com/weibogao/aggbug/93125.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2007-01-11 12:09 <a href="http://www.aygfsteel.com/weibogao/archive/2007/01/11/93125.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转《“数据徏模”读书笔??/title><link>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93122.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 11 Jan 2007 04:01:00 GMT</pubDate><guid>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93122.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/93122.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/93122.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/93122.html</trackback:ping><description><![CDATA[ <h3 class="title"> </h3> <p>         最q逛书店发C本数据徏模的好书——《数据徏模:分析与设计的工具和技巧?Data Modeler's WorkbenchQTools and Techniques for Analysis and Design)Q作者Steve Hoberman。粗d一遍后Q感觉这本书的确无愧于译者和国外专家们的盛赞Q“这本书充满了对改进数据模型和设计有益的技术和技巧,q且它还极富阅读乐趣——一个了不v的结合!M一个数据徏模者都应该拥有一本Steve Hoberman的关于数据徏模工具和技术的书。?/p> <p>  管我对自己所掌握的数据徏模知识有一定的自负Q读完该书后Q还是获益良多。本着好书大家一起分享的xQ我把该书的每个章节的ȝ和技巧徏议列出来Q以方便手头暂时没有该书的朋友在数据建模时参考。该书所介绍的工具和模版可在作者的Web站点下蝲Q地址是:<br />  www.wiley.com/compbooks/hoberman</p> <p>  W一章:使用闻、类比和演示文稿来阐明数据徏模的概念</p> <p>  在一般的日常沟通中。我们可能会说出q听到许多故事、或者趣闻这些故事涉及的论题范围很大。有些例子是周末发生在我们自pn边的事情Q或者是与我们的工作目有关的经历。这些趣L助于加强我们和周围h们的关系Q增q我们的愉悦情AQ而且Ҏ们有教育作用。我们能够把pa表达出来的东西Ş象化。有Ӟ当故事结束时Q给我们留下的是以前未曾惛_的信息或更多的认识。在解释数据建模概念Ӟ闻是极其有效的。原因有如下几个Q?br />  它们建立h久的形象?br />  它们引h入胜、人愉悦?br />  它们增经Z之间的关pR?br />  它们减缓压力?/p> <p>  成功~造ƈ讲述一个数据徏模方面的闻有下面三个简单的步骤Q?br />  1)定义一个论题。要在心中保证,你讲q的q个闻有一个特定的目标或论题,也就是说Q这个故事是Z解释一个数据徏模的概念或术语?br />  2)选择你的故事。我们可以选择的故事类型多U多栗我们要考虑选择一个有ƈ有益Q而且能够明白无误C达主题意囄短的故事?br />  3)演练你的故事。一旦找C合适的故事Q你要好好演l一番,直到你自信它能够在两分钟的时间内充分表达你的论题。要避免讲述拖拖拉拉的故事?/p> <p>  数据模型cL<br />  cL是把两个或多个概念q行怺比较Q以它们之间的相似或差异。类比是介绍外来事物或新鲜事物的一个很好的技巧,其是向非计机专业的h士介l计机的专业知识时。Hoberman在数据徏模中最常见的几个类比如下(他用q些cLL的打动管理层l他涨了一倍的工资^_^Q:<br />  M域模型是一个居高下的视点?br />  数据模型是一个设计图?br />  企业模型是一个世界地图?br />  标准是城市规划?br />  元数据仓储库是一个图书馆?br />  数据仓库是“心脏”?/p> <p>  W二章:元数据宾果游?br />  单来_即通过宾果卡片游戏的方式,调动目团队成员的积极性,来确定数据模型,q确定元数据的有效性。元数据宾果游戏“共赢”,如果q气好,游戏l束时每个h都能赢?/p> <p>  W三章:保高质量的定义<br />  本章集中讨论一个被UCؓ“定义检查单?Definition Checklist)的工P它包含了保定义的质量处于最高水q的准则?/p> <p>  W四章:数据建模者的目计划<br />  本章重点介绍定数据建模阶段、Q务、工具和旉的四个工P<br />  ·数据建模阶段的工P用来定最高层ơ上的数据徏模步骤?br />  ·阶段—Q务—工P提取出“数据徏模阶D”的各个阶段q把他们分解成数据徏模Q务?br />  ·优先U三角ŞQ你可以从以下三中取两Ҏ|很高的质量、最短的旉与最低的成本Q但你永q也别想三者兼得?br />  ·可靠的估工P“主体域工作量时限”根据应用程序的cdQ确定每个数据徏模阶D应占整个项目的癑ֈ比。“Q务工作量工具”提取在“阶D—Q务—工具”中定的每Q务,q列出它们应占整个数据徏模工作品的癑ֈ比。这两个工具的组合可使你向项目经理提供一份具有一定精度的合理估?/p> <p>  W五章:M域分?br />  本章主要探讨五个关键的工Pq五个工具对数据建模工作的主体域分析阶段有帮l作用。它们应该按照下面的序被逐个完成Q?br />  1)M域检查单Q新应用E序中的M域的完整列表Q还有各个主体域的定义和同义词(或别名)?br />  2)M域CRUD(Create Read Update Delete)矩阵Q包含新应用E序和现有应用程序之间的M域方面的差别和重复之处,定应用E序的范围?br />  3)In-the-Know模版Q确定完成这个新应用E序的数据间模工作品所需要的、被用作资源的h员和文档?br />  4)M域家族树Q包含每一个主体域的源应用E序和若q其他的关键信息Q阐明主体域数据来自哪里?br />  5)M域力度矩阵:使用一个电子表格的格式Q记录每一个度量和事实M域的发布层次?/p> <p>  W六章:M域徏?br />  本章阐述三个队主体域信息q行建模的强大工P<br />  ·“业务清理板”模型?br />  ·“应用程序清理板”模型?br />  ·“早期现实性检查”模型?/p> <p>  W七章:逻辑数据分析<br />  本章x四个逻辑数据分析工具Q它们应该按照下面的ơ序被用:<br />  1)数据元素家族树:包含应用E序的数据元素的完整列表Q以及每个数据元素的来源和变换信息,q有其他几个关键的数据元素元数据?br />  2)数据元素_度矩阵Q用一个电子表格的格式Q来记录每个度量和事实的发布层次?br />  3)数据质量记录模板Q展C每个数据元素的员数据和一些实际数据的Ҏ?br />  4)数据质量认模板Q记录每个数据元素的元数据和一些实际数据的Ҏ的结果?/p> <p>  W八章:规范化之旅和反向规范化生存指南(强烈推荐Q是我目前所读过最好的关系型数据库的规范化技术文档)<br />  规范化是一个剔除冗余ƈ应用规则的过E,它的目的是ؓ了更好的理解和表辑֭在于数据元素之间的依赖性和参与性。规范化包含6个层ơ,最高层是第五范?5NF)。一般的技术文档上都认?NF卛_QSteve Hobermanl我们指明了更高的目标:5NF。Graeme Simsion写过一本名为《Data Modeling Essentials》的书,在这本书中,他写道:“较高层ơ的范式常被从业者误解ƈ因此而被忽视Q或Z支持不可靠的建模旉而被引用。”但是,我们需要理解这些较高层ơ的规范化,因ؓ它们体现了额外的规范化机会,q帮l我们进一步减冗余信息、改q设计的灉|性。尽余下的三个规范化层ơ有可能仅仅产生ơ数很少的变化,但它们仍然具有一些提高灵zL和效率的机会。下面是BCNF&4NF&5NF的定?比国内教材上|列的数学公式容易理解得多^_^)Q?br />  BCNF=3NFQ下面的规则Q?br />  每一个数据元素都完全依赖于键、整个键Q而且除依赖于q个键以外,不依赖于M其他数据元素?br />  4NF=3NF+下面的规则:<br />  要把主键中拥有三个或更多外徏数据元素、切割格外键之间不存在约束的那些实体分解成两个或更多个实体?br />  5NF=4NF+下面的规则:<br />  把主键中拥有三个或更多的外键数据元素Q且q些外键数据元素之间存在着U束的实体分解成为所有的U束都需要的多对多的关系?/p> <p>  当我们攀?NF的顶峰后Q再Ҏ实际需求情冉|q行“反向规范化”增加数据冗余,从而简化开发,提高查询速度。反向规范化是这样一个过E:在定义了一个可靠的、完全规范化了的数据l构之后Q你借助q个q程Q有选择地引入一些重复的数据Q以促进Ҏ性能需求的实现。Steve Hoberman的“反向规范化生存指南”给如何适当增加冗余提供了一套可计算的评分标准。通过考察每个关系?个问题,累加各个问题的得分之后,当得分大于等?0Ӟ我们对该关p进行反向规范化?/p> <p>  “反向规范化生存指南”的计分规则Q?br />  1.关系是什么类型的Q该问题定我们所分析的关pȝcd。父实体对于子实体具有什么样的关p?<br />  层次关系(20?<br />  同等关系(-10?<br />  定关系(-20?<br />  2.参与率是多少Q该问题定一个关pM的每个实体的参与性。换句话_对于一个给定的父实体数|大概会有几个子实体数|父与子的关系接q“一对一”,我们对它q行反向规范化的Zp大?br />  多达“一对五”的比率(20?<br />  多达“一对一䏀的比率(-10?<br />  过“一对一䏀的比率(-20?<br />  3.父实体中有多个数据元素<br />  于10个数据元?20?<br />  数据元素的数量介?0?0之间(-10?<br />  多于20个数据元?-20?<br />  4.使用率是多少Q当用户需要来自子的信息时Q通常情况下,它们是否q需要来自父的信息呢Q换句话_q两个实体的耦合或相关程度如何?<br />  怺之间的关联很?30?<br />  怺之间的关联较弱或者没有关?-30?<br />  5.父实体时一个占位符吗:在不q的来Q我们是否还打算向父实体加入更多的数据元素或关系Q如果答案是“不”,那么q行反向规范化的可行性就更强?br />  ?20?<br />  ?-20?<br />  6.变动Ҏ率是多少Q该问题是ؓ了确定,在同一旉周期内,两个实体的插入和更新的频度是否相q。如果其中一个实体很变化,而另一个实体却变动频繁Q那么,我们非常們֐于保持它们的规范化状态,把它们放在各自的表中?br />  相同(20?<br />  不同(-20?</p> <p>  “反向规范化生存指南”的使用ҎQ?br />  1)把模型中的关pL照优先排序<br />  2)选择一个关p?br />  3)对这个关pd{提?br />  4)如果得分{于或大?0Q就q行反向规范?br />  5)q回步骤二,直到完成所有的关系?/p> <p>  W九章:抽象化安全指南和lg<br />  看过我的“浅谈数据库设计技?? ”的朋友应该q记得我丄W二个例子:|上电子商务q_上的商品信息表的设计。本章将我在上面例子中所用的Ҏ上升C理论阶段Q采用了面向对象的设计,所有商品的共有属性提取出来,抽象成一个超c,再加入一个表来记录各个不同实体之间的l节来实现超cȝzQ从而实现设计的灉|性。当出现下面两种条g的Q何场合,抽象化都是极其有用的Q?br />  设计需要永久维持下去:要求以后可能的不修Ҏ据库设计<br />  需求可能发生变化:应用E序的需求发生变化,而要求业务流E重l或q行功能升<br />  数据仓库Q当新的分类cd从源应用E序中传q来Ӟ我们无须Ҏ据仓库的设计q行M改动Q而只需在分cȝ型实体加入一个新行即?br />  元数据仓储库Q和数据仓库的要求类?/p> <p>  当然Q抽象化会大大增加工作量和开发的复杂度,而h们通常x的是非常短期的应用和眼前的成本,而不兛_来的高得多的成本。所以,我非常赞同敏捯Y件开发这个观点:在最初几乎不q行预先设计Q但是一旦需求发生变化,此时作ؓ一名追求卓的E序员,应该从头审查整个架构设计Q在此次修改中设计出能够满日后cM修改的系l架构?/p> <p>  “抽象组件”就是小型的抽象模型片段Q在许多的徏模场?无论是什么行业、组l,甚至什么主体域的徏模场?中,它们都可被反复用。在键模阶段多次使用抽象化之后,你将开始看到出现的抽象化结构的势。这些“抽象组件”有如下的目的:<br />  加快设计速度<br />  加快开发速度<br />  提供通用且有用的机构</p> <p>  W十章:数据模型化技?br />  本章通过x如何改进逻辑和物理数据模型的视觉外观Q我们的设计超直接的应用E序需求。本章中讨论了五个类别的化技巧:<br />  逻辑数据元素排列技巧:q些技巧是一个推荐的、对你的逻辑数据模型中的每一个实体的数据元素q行排序的方法?br />  物理数据元素排序技巧:q些技巧关注数据模型中每一个实体的最佛_局?br />  实体布局技巧:q些技巧关注数据模型中的每一个实体的最佛_局<br />  关系布局技巧:q些技巧关注如何调整重叠的关系U条以及看v来穿(而不是绕q)无关实体的关p?br />  吸引注意力的技巧:q些技巧关注如何在我们的涉及中H出的某些元素、实体或关系?/p> <p>  W十一章:规划一个长盛不衰的数据建模生<br />  Ҏ据徏模者的十大忠告清单Q?br />  1)CQ灵zL、准性和背景<br />  2)建模只是你的工作的一部?br />  3)试其他角色<br />  4)了解95/5规则Q?5%的时间将p?%的数据元素上<br />  5)数据建模从不令h厌烦Q如果你一直在做数据徏模工作,而且发现自己l常感到厌烦Q那么,你的该改变一下了。这可能不是数据建模领域本n令h厌烦Q而是你所在的特定的Q务、公司或行业不再令h兴奋。冒险一下,试着道一个不同的目或行业中q行数据建模工作吧!<br />  6)站在技术前?br />  7)量不要在模型上牉|感情因素Q徏模者必ȝ解,Z在评审过E中的意见ƈ不是针对模型的创,而是针对q个模型的内宏V即那句老话Q对事不对h?br />  8)让你的创造力展开膀Q在考虑记录数据需求和改进设计的新ҎӞ要紧可能有创造性。有创造性也许就意味着修改本书中的某些工具。这q可能意味着提出你自q电子表格或其他工兗?br />  9)单纯的理论太昂贵了:在设计活动过E中Q你要确保把q个观点牢记在心。ؓq个应用E序掏腰包的部门和组l期望看到的是能看得着的实用结果?br />  10)成ؓ一个了不v的会讲故事的人:作ؓ一名数据徏模者,讲故事是工作的一个很重要的部分。ؓ了帮l教化和影响目l理以及Ҏ们行业缺乏理解的其他人,我们需要讲故事或趣闅R?/p> <p>  最后,我个得,Steve Hoberman所提出的“抽象组件”的观念和面向对象设计中的的“设计模式”非常类伹{即数据库专家在多次的数据徏模后Q将各个目中的cM部分抽象化,提取出特定的建模模型片段Q以后只需在新的项目中对这些模型片D늻化派生,卛_快速构建出适合于该目的数据库架构。不q,q些建模模型片段q没有统一QŞ成标准,目前也没有出版这cȝ书籍。本人正在陆lȝ自己在这斚w的经验,但是自知水^有限Q不敢在高h面前班门弄斧Q只希望自己日后陆箋发布的相x章能起到抛{引玉的作用,争取׃国的E序员率先统一出数据徏模领域的“设计模式”?/p> <img src ="http://www.aygfsteel.com/weibogao/aggbug/93122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2007-01-11 12:01 <a href="http://www.aygfsteel.com/weibogao/archive/2007/01/11/93122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转《浅谈数据库设计技巧?/title><link>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93121.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 11 Jan 2007 04:00:00 GMT</pubDate><guid>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93121.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/93121.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2007/01/11/93121.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/93121.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/93121.html</trackback:ping><description><![CDATA[ <h3 class="title"> </h3> <p>  说到数据库,我认Z能不先谈数据l构?996q_在我初入大学学习计算机编E时Q当时的老师告诉我们说Q计机E序Q数据结构+法。尽现在的E序开发已由面向过Eؓ主逐步q渡到面向对象ؓ主,但我q是深深赞同8q前老师的告诉我们的公式Q计机E序Q数据结构+法。面向对象的E序开发,要做的第一件事是Q先分析整个E序中需处理的数据,从中提取出抽象模板,以这个抽象模板设计类Q再在其中逐步d处理其数据的函数(即算?Q最后,再给cM的数据成员和函数划分讉K权限Q从而实现封装?/p> <p>  数据库的最初雏形据说源自美国一个奶牛场的记账薄(U质的,由此可见Q数据库q不一定是存储在电脑里的数据^_^)Q里面记录的是该奶牛场的收支账目Q程序员在将其整理、录入到电脑中时从中受到启发。当按照规定好的数据l构所采集到的数据量大C定程度后Q出于程序执行效率的考虑Q程序员其中的索、更新维护等功能分离出来Q做成单独调用的模块Q这个模块后来就慢慢发展、演变成现在我们所接触到的数据库管理系l?DBMS)——程序开发中的一个重要分支?/p> <p>  下面q入正题Q首先按我个人所接触q的E序l数据库设计人员的功底分一下类Q?br />  Q、没有系l学习过数据l构的程序员。这cȝ序员的作品往往只是他们的即兴玩P他们往往习惯只设计有限的几个表,实现某类功能的数据全部塞在一个表中,各表之间几乎毫无兌。网上不的免费理软g都是q样的东西,当程序功能有限,数据量不多的时候,其程序运行v来没有什么问题,但是如果用其理比较重要的数据,风险性非常大?br />  Q、系l学习过数据l构Q但是还没有开发过对程序效率要求比较高的管理Y件的E序员。这cMh多半刚从学校毕业不久Q他们在设计数据库表l构Ӟ严格按照教科书上的规定,LE-R囑֒3NF(别灰心,所有的数据库设计高手都是从q一步开始的)。他们的作品Q对于一般的access型轻量的管理YӞ已经够用。但是一旦该pȝ需要添加新功能Q原有的数据库表差不多得q行大换血?br />  Q、第二类E序员,在经历过数次E序效率的提升,以及功能升的折腑֐Q终于升U成为数据库设计的老鸟Q第一cȝ序员g的高人。这cȝ序员可以胜Q二十个表以上的中型商业数据管理系l的开发工作。他们知道该在什么样的情况下保留一定的冗余数据来提高程序效率,而且其设计的数据库可拓展性较好,当用户需要添加新功能Ӟ原有数据库表只需做少量修改即可?br />  Q、在l历q上十个cM数据库管理Y件的重复设计后,W三cȝ序员中坚持下来没有{行,而是希望从中扑և“偷懒”窍门的有心Z慢慢觉悟Q从而完成量变到质变的{换。他们所设计的数据库表结构有一定的q见Q能够预到未来功能升所需要的数据Q从而预先留下伏W。这cȝ序员目前大多晋成数据挖掘方面的高软g开发h员?br />  Q、第三类E序员或W四cȝ序员Q在对现有的各家数据库管理系l的原理和开发都有一定的ȝ后,要么在其基础上进行二ơ开发,要么自行开发一套有自主版权的通用数据库管理系l?/p> <p>  我个人正处于W三cȝ末期Q所以下面所列出的一些设计技巧只适合W二cd部分W三cL据库设计人员。同Ӟ׃我很碰到有兴趣在这斚w深钻下去的同行,所以文中难免出现错误和遗漏Q在此先行声明,Ƣ迎大家指正Q不要藏U哦8)</p> <p>  一、树型关pȝ数据?br />  不少E序员在q行数据库设计的时候都遇到q树型关pȝ数据Q例如常见的cd表,即一个大c,下面有若q个子类Q某些子cd有子c这L情况。当cd不确定,用户希望可以在Q意类别下d新的子类Q或者删除某个类别和其下的所有子c,而且预计以后其数量会逐步增长Q此时我们就会考虑用一个数据表来保存这些数据。按照教U书上的教导Q第二类E序员大概会设计出类DL数据表结构:</p> <p>cd表_1(Type_table_1)<br />名称     cd    U束条g   说明<br />type_id   int   无重复   cd标识Q主?br />type_name   char(50) 不允ؓI?cd名称Q不允许重复<br />type_father int 不允ؓI?该类别的父类别标识,如果是顶节点的话讑֮为某个唯一?/p> <p>  q样的设计短精悍,完全满3NFQ而且可以满用户的所有要求。是不是q样p呢?{案是NOQWhyQ?/p> <p>  我们来估计一下用户希望如何罗列出q个表的数据的。对用户而言Q他当然期望按他所讑֮的层ơ关pMơ罗列出所有的cdQ例如这P<br />ȝ?br />  cd1<br />    cd1.1<br />      cd1.1.1<br />    cd1.2<br />  cd2<br />    cd2.1<br />  cd3<br />    cd3.1<br />    cd3.2<br />  …?/p> <p>  看看Z实现q样的列表显C?树的先序遍历)Q要对上面的表进行多次索?注意Q尽类?.1.1可能是在cd3.2之后d的记录,{案仍然是Nơ。这L效率对于量的数据没什么媄响,但是日后cd扩充到数十条甚至上百条记录后Q单单列一ơ类型就要检索数十次该表Q整个程序的q行效率׃敢恭l了。或许第二类E序员会_那我再徏一个时数l或临时表,专门保存cd表的先序遍历l果Q这样只在第一ơ运行时索数十次Q再ơ罗列所有的cd关系时就直接读那个时数l或临时表就行了。其实,用不着再去分配一块新的内存来保存q些数据Q只要对数据表进行一定的扩充Q再Ҏ加类型的数量q行一下约束就行了Q要完成上面的列表只需一ơ检索就行了。下面是扩充后的数据表结构:</p> <p>cd表_2(Type_table_2)<br />名称     cd    U束条g    说明<br />type_id   int   无重复   cd标识Q主?br />type_name   char(50) 不允ؓI?cd名称Q不允许重复<br />type_father int 不允ؓI?该类别的父类别标识,如果是顶节点的话讑֮为某个唯一?br />type_layer char(6) 限定3?初始gؓ000000 cd的先序遍历,主要为减检索数据库的次?/p> <p>  按照q样的表l构Q我们来看看上面例子记录在表中的数据是怎样的:</p> <p>type_id type_name type_father type_layer<br />1 ȝ?0 000000<br />2 cd1 1 010000<br />3 cd1.1 2 010100<br />4 cd1.2 2 010200<br />5 cd2 1 020000<br />6 cd2.1 5 020100<br />7 cd3 1 030000<br />8 cd3.1 7 030100<br />9 cd3.2 7 030200<br />10 cd1.1.1 3 010101<br />…?/p> <p>  现在按type_layer的大来索一下:SELECT * FROM Type_table_2 ORDER BY type_layer</p> <p>列出记录集如下:</p> <p>type_id type_name type_father type_layer<br />1 ȝ?0 000000<br />2 cd1 1 010000<br />3 cd1.1 2 010100<br />10 cd1.1.1 3 010101<br />4 cd1.2 2 010200<br />5 cd2 1 020000<br />6 cd2.1 5 020100<br />7 cd3 1 030000<br />8 cd3.1 7 030100<br />9 cd3.2 7 030200<br />…?/p> <p>  现在列出的记录顺序正好是先序遍历的结果。在控制昄cd的层ơ时Q只要对type_layer字段中的数D行判断,?位一l,如大?则向右移2个空根{当Ӟ我这个例子中讑֮的限制条件是最?层,每层最多可?9个子cdQ只要按用户的需求情况修改一下type_layer的长度和位数Q即可更攚w制层数和子类别数。其实,上面的设计不单单只在cd表中用到Q网上某些可按树型列表显C的论坛E序大多采用cM的设计?/p> <p>  或许有h认ؓQType_table_2中的type_father字段是冗余数据,可以除去。如果这P在插入、删除某个类别的时候,得对type_layer 的内容进行比较繁琐的判定Q所以我q没有消去type_father字段Q这也正W合数据库设计中适当保留冗余数据的来降低E序复杂度的原则Q后面我会D一个故意增加数据冗余的案例?/p> <p>  <br />  二、商品信息表的设?br />  假设你是一家百货公司电脑部的开发h员,某天老板要求你ؓ公司开发一套网上电子商务^収ͼ该百货公司有数千U商品出售,不过目前仅打先在网上销售数十种方便q输的商品,当然Q以后可能会陆箋在该电子商务q_上增加新的商品出售。现在开始进行该q_数据库的商品信息表的设计。每U出售的商品都会有相同的属性,如商品编P商品名称Q商品所属类别,相关信息Q供货厂商,内含件数Q库存,q货P销售hQ优惠h。你很快p计出4个表Q商品类型表(Wares_type)Q供货厂商表(Wares_provider)Q商品信息表(Wares_info)Q?/p> <p>商品cd?Wares_type)<br />名称     cd    U束条g    说明<br />type_id   int   无重复   cd标识Q主?br />type_name   char(50) 不允ؓI?cd名称Q不允许重复<br />type_father int 不允ؓI?该类别的父类别标识,如果是顶节点的话讑֮为某个唯一?br />type_layer char(6) 限定3?初始gؓ000000 cd的先序遍历,主要为减检索数据库的次?/p> <p>供货厂商?Wares_provider)<br />名称     cd    U束条g    说明<br />provider_id int   无重复   供货商标识,主键<br />provider_name char(100) 不允ؓI?供货商名U?/p> <p>商品信息?Wares_info)<br />名称     cd    U束条g    说明<br />wares_id int   无重复   商品标识Q主?br />wares_name char(100) 不允ؓI?商品名称<br />wares_type   int 不允ؓI           商品cd标识Q和Wares_type.type_id兌<br />wares_info char(200) 允许为空 相关信息<br />provider int 不允ؓI?供货厂商标识Q和Wares_provider.provider_id兌<br />setnum int 初始gؓ1 内含件数Q默认ؓ1<br />stock int 初始gؓ0 库存Q默认ؓ0<br />buy_price money 不允ؓI?q货?br />sell_price money 不允ؓI?销售h<br />discount money 不允ؓI?优惠?/p> <p>  你拿着q?个表l老板查,老板希望能够再添加一个商品图片的字段Q不q只有一部分商品有图片。OKQ你在商品信息表(Wares_info)中增加了一个haspic的BOOL型字D,然后再徏了一个新表——商品图片表(Wares_pic)Q?/p> <p>商品囄?Wares_pic)<br />名称     cd    U束条g    说明<br />pic_id int   无重复   商品囄标识Q主?br />wares_id int 不允ؓI?所属商品标识,和Wares_info.wares_id兌<br />pic_address  char(200) 不允ؓI           囄存放路径</p> <p>  E序开发完成后Q完全满板目前的要求,于是正式启用。一D|间后Q老板打算在这套^C推出新的商品销售,其中Q某cd品全部都需d“长度”的属性。第一轮折腾来了……当Ӟ你按照添加商品图片表的老方法,在商品信息表(Wares_info)中增加了一个haslength的BOOL型字D,又徏了一个新表——商品长度表(Wares_length)Q?/p> <p>商品长度?Wares_length)<br />名称     cd    U束条g    说明<br />length_id int   无重复   商品囄标识Q主?br />wares_id int 不允ؓI?所属商品标识,和Wares_info.wares_id兌<br />length  char(20) 不允ؓI           商品长度说明</p> <p>  刚刚改完没多久,老板又打上一Ҏ的商品,q次某类商品全部需要添加“宽度”的属性。你咬了咬牙Q又照方抓药Q添加了商品宽度?Wares_width)。又q了一D|_老板C的商品中有一些需要添加“高度”的属性,你是不是开始觉得你所设计的数据库按照q种方式增长下去Q很快就能变成一个迷宫呢Q那么,有没有什么办法遏制这U不可预见性,但却cM重复的数据库膨胀呢?我在阅读《敏捯Y件开发:原则、模式与实践》中发现作者Dq类似的例子Q?.3 “Copy”程序。其中,我非常赞同敏捯Y件开发这个观点:在最初几乎不q行预先设计Q但是一旦需求发生变化,此时作ؓ一名追求卓的E序员,应该从头审查整个架构设计Q在此次修改中设计出能够满日后cM修改的系l架构。下面是我在需要添加“长度”的属性时所提供的修Ҏ案:</p> <p>  L商品信息?Wares_info)中的haspic字段Q添加商品额外属性表(Wares_ex_property)和商品额外信息表(Wares_ex_info)2个表来完成添加新属性的功能?/p> <p>商品额外属性表(Wares_ex_property)<br />名称     cd    U束条g    说明<br />ex_pid int   无重复   商品额外属性标识,主键<br />p_name char(20) 不允ؓI?额外属性名U?/p> <p>商品额外信息?Wares_ex_info)<br />名称     cd    U束条g    说明<br />ex_iid int   无重复   商品额外信息标识Q主?br />wares_id int 不允ؓI?所属商品标识,和Wares_info.wares_id兌<br />property_id  int 不允ؓI           商品额外属性标识,和Wares_ex_property.ex_pid兌<br />property_value char(200) 不允ؓI?商品额外属性?/p> <p>  在商品额外属性表(Wares_ex_property)中添?条记录:<br />ex_pid p_name<br />1 商品囄<br />2 商品长度</p> <p>  再在整个电子商务q_的后台管理功能中q加一商品额外属性管理的功能Q以后添加新的商品时出现新的属性,只需利用该功能往商品额外属性表(Wares_ex_property)中添加一条记录即可。不要害怕变化,被第一颗子弹击中ƈ不是坏事Q坏的是被相同轨道飞来的W二颗、第三颗子弹M。第一颗子Ҏ得越早,所受的伤越重,之后的抵抗力也越?)</p> <p> <br />  三、多用户及其权限理的设?br />  开发数据库理cȝ软gQ不可能不考虑多用户和用户权限讄的问题。尽目前市面上的大、中型的后台数据库系lY仉提供了多用户Q以及细x个数据库内某张表的权限设|的功能Q我个hQ一套成熟的数据库管理YӞq是应该自行设计用户理q块功能Q原因有二:<br />  1.那些大、中型后台数据库pȝ软g所提供的多用户及其权限讄都是针对数据库的共有属性,q不一定能完全满某些特例的需求;<br />  2.不要q多的依赖后台数据库pȝ软g的某些特D功能,多种大、中型后台数据库pȝ软g之间q不完全兼容。否则一旦日后需要{换数据库q_或后台数据库pȝ软g版本升Q之前的架构设计很可能无法重用?/p> <p>  下面看看如何自行设计一套比较灵zȝ多用L理模块,卌数据库管理Y件的pȝ理员可以自行添加新用户Q修改已有用L权限Q删除已有用戗首先,分析用户需求,列出该数据库理软g所有需要实现的功能Q然后,Ҏ一定的联系对这些功能进行分c,x某类用户需使用的功能归Zc;最后开始徏表:<br />  <br />功能?Function_table)<br />名称  cd  U束条g   说明<br />f_id int   无重复   功能标识Q主?br />f_name char(20) 不允ؓI?功能名称Q不允许重复<br />f_desc char(50) 允许为空 功能描述</p> <p>用户l表(User_group)<br />名称   cd  U束条g   说明<br />group_id int 无重?用户l标识,主键<br />group_name char(20) 不允ؓI?用户l名U?br />group_power char(100) 允许为空 用户l权限表Q内容ؓ功能表f_id的集?/p> <p>用户?User_table)<br />名称    cd    U束条g   说明<br />user_id int 无重?用户标识Q主?br />user_name char(20) 无重?用户?br />user_pwd char(20) 不允ؓI?用户密码<br />user_type int 不允ؓI?所属用L标识Q和User_group.group_id兌</p> <p>  采用q种用户l的架构设计Q当需要添加新用户Ӟ只需指定新用h属的用户l;当以后系l需要添加新功能或对旧有功能权限q行修改Ӟ只用操作功能表和用户l表的记录,原有用户的功能即可相应随之变化。当Ӟq种架构设计把数据库理软g的功能判定移C前台Q得前台开发相对复杂一些。但是,当用h较大(10Z?Q或日后软g升的概率较大时Q这个代h值得的?/p> <p> <br />  四、简z的扚wm:n设计<br />  到m:n的关p,一般都是徏?个表Qm一个,n一个,m:n一个。但是,m:n有时会遇到批量处理的情况Q例如到图书馆借书Q一般都是允许用户同时借阅n本书Q如果要求按Ҏ询借阅记录Q即列出某个用户某次借阅的所有书c,该如何设计呢Q让我们建好必须?个表先:</p> <p>书籍?Book_table)<br />名称   cd    U束条g   说明<br />book_id int 无重?书籍标识Q主?br />book_no char(20) 无重?书籍~号<br />book_name char(100) 不允ؓI?书籍名称<br />…?/p> <p>借阅用户?Renter_table)<br />名称    cd    U束条g   说明<br />renter_id int 无重?用户标识Q主?br />renter_name char(20) 不允ؓI?用户姓名<br />…?/p> <p>借阅记录?Rent_log)<br />名称   cd    U束条g   说明<br />rent_id int 无重?借阅记录标识Q主?br />r_id int 不允ؓI?用户标识Q和Renter_table.renter_id兌<br />b_id int 不允ؓI?书籍标识Q和Book_table.book_id兌<br />rent_date datetime 不允ؓI?借阅旉<br />…?/p> <p>  Z实现按批查询借阅记录Q我们可以再Z个表来保存批量借阅的信息,例如Q?/p> <p>扚w借阅?Batch_rent)<br />名称   cd   U束条g   说明<br />batch_id int 无重?扚w借阅标识Q主?br />batch_no int 不允ؓI?扚w借阅~号Q同一批借阅的batch_no相同<br />rent_id int 不允ؓI?借阅记录标识Q和Rent_log.rent_id兌<br />batch_date datetime 不允ؓI?扚w借阅旉</p> <p>  q样的设计好吗?我们来看看ؓ了列出某个用hơ借阅的所有书c,需要如何查询?首先索批量借阅?Batch_rent)Q把W合条g的的所有记录的rent_id字段的数据保存v来,再用q些数据作ؓ查询条g带入到借阅记录?Rent_log)中去查询。那么,有没有什么办法改q呢Q下面给ZU简z的扚w设计ҎQ不需d新表Q只需修改一下借阅记录?Rent_log)卛_。修改后的记录表(Rent_log)如下Q?/p> <p>借阅记录?Rent_log)<br />名称   cd   U束条g   说明<br />rent_id int 无重?借阅记录标识Q主?br />r_id int 不允ؓI?用户标识Q和Renter_table.renter_id兌<br />b_id int 不允ؓI?书籍标识Q和Book_table.book_id兌<br />batch_no int 不允ؓI?扚w借阅~号Q同一批借阅的batch_no相同<br />rent_date datetime 不允ؓI?借阅旉<br />…?/p> <p>  其中Q同一ơ借阅的batch_no和该批第一条入库的rent_id相同。D例:假设当前最大rent_id?4Q接着某用户一ơ借阅?本书Q则扚w插入?条借阅记录的batch_no都是65。之后另外一个用L了一套碟Q再插入出租记录的rent_id?8。采用这U设计,查询扚w借阅的信息时Q只需使用一条标准T_SQL的嵌套查询即可。当Ӟq种设计不符?NFQ但是和上面标准?NF设计比v来,哪一U更好呢Q答案就不用我说了吧?/p> <p> <br />  五、冗余数据的取舍<br />  上篇的“树型关pȝ数据表”中保留了一个冗余字D,q里的例子更q一步——添加了一个冗余表。先看看例子Q我原先所在的公司Z解决员工的工作餐Q和附近的一家小馆联系Q每天吃饭记账,费用按h数^摊,月底由公司现金结,每个人每个月的工作餐费从工资中扣除。当Ӟ每天吃饭的h员和人数都不是固定的Q而且Q由于每工作餐的所点的菜色不同Q每的p也不相同。例如,星期一中餐5?0元,晚餐2?0Q星期二中餐6?6元,晚餐3?8元。ؓ了方便计每个h每个月的工作费Q我写了一个简陋的餐记̎理E序Q数据库里有3个表Q?/p> <p>员工?Clerk_table)<br />名称    cd    U束条g   说明<br />clerk_id int 无重?员工标识Q主?br />clerk_name char(10) 不允ؓI?员工姓名</p> <p>每餐总表(Eatdata1)<br />名称    cd    U束条g   说明<br />totle_id int 无重?每餐总表标识Q主?br />persons char(100) 不允ؓI?餐员工的员工标识集?br />eat_date datetime 不允ؓI?餐日期<br />eat_type char(1) 不允ؓI?餐cdQ用来区分中、晚?br />totle_price money 不允ؓI?每餐总花?br />persons_num int 不允ؓI?餐人数</p> <p>餐计费l表(Eatdata2)<br />名称  cd  U束条g   说明<br />id int 无重?餐计费l表标识Q主?br />t_id int 不允ؓI?每餐总表标识Q和Eatdata1.totle_id兌<br />c_id int 不允ؓI?员工标识标识Q和Clerk_table.clerk_id兌<br />price money 不允ؓI?每h每餐p</p> <p>  其中Q就计费细?Eatdata2)的记录就是把每餐总表(Eatdata1)的一条记录按餐员工qx拆开Q是个不折不扣的冗余表。当Ӟ也可以把每餐总表(Eatdata1)的部分字D合q到餐计费l表(Eatdata2)中,q样每餐总表(Eatdata1)成了冗余表Q不q这h设计出来的就计费细表重复数据更多,相比来说q是上面的方案好些。但是,是餐计费l表(Eatdata2)q个冗余表,在做每月每h费l计的时候,大大化了~程的复杂度Q只用类D么一条查询语句即可统计出每h每月的寄次数和费dQ?/p> <p>SELECT clerk_name AS personname,COUNT(c_id) as eattimes,SUM(price) AS ptprice FROM Eatdata2 JOIN Clerk_tabsle ON (c_id=clerk_id) JOIN eatdata1 ON (totleid=tid) WHERE eat_date>=CONVERT(datetime,'"&the_date&"') AND eat_date </p> <p>  惌一下,如果不用q个冗余表,每次l计每h每月的餐Ҏd时会多麻烦,E序效率也够呛。那么,到底什么时候可以增加一定的冗余数据呢?我认为有2个原则:</p> <p>  Q、用L整体需求。当用户更多的关注于Q对数据库的规范记录按一定的法q行处理后,再列出的数据。如果该法可以直接利用后台数据库系l的内嵌函数来完成,此时可以适当的增加冗余字D,甚至冗余表来保存q些l过法处理后的数据。要知道Q对于大扚w数据的查询,修改或删除,后台数据库系l的效率q远高于我们自己~写的代码?br />  Q、简化开发的复杂度。现代Y件开发,实现同样的功能,Ҏ有很多。尽不必要求程序员_N绝大部分的开发工具和q_Q但是还是需要了解哪U方法搭配哪U开发工LE序更简z,效率更高一些。冗余数据的本质是用空间换旉Q尤其是目前g的发展远q高于YӞ所以适当的冗余是可以接受的。不q我q是在最后再一下:不要q多的依赖^台和开发工LҎ来化开发,q个度要是没把握好的话,后期l护升会栽大跟头的?/p> <img src ="http://www.aygfsteel.com/weibogao/aggbug/93121.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2007-01-11 12:00 <a href="http://www.aygfsteel.com/weibogao/archive/2007/01/11/93121.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ȩ</a>| <a href="http://" target="_blank">ͤ</a>| <a href="http://" target="_blank">ױ</a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ַ</a>| <a href="http://" target="_blank">۩</a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽԶ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank">ɽʡ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">կ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ӣ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ĩ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ҵ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ٳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>