??xml version="1.0" encoding="utf-8" standalone="yes"?>
׃ MySQL 本n的读写及(qing)锁定机制{方面的原因Q与一些其他数据库软g一P在特D情况下的极为频J读写时Q或在服务器掉电(sh)、死机等情况下,相关的数据文件可能会(x)发生被损坏的情况Q通常可以采用以下的方式加以解冟?
一:repair.php 修复工具
Discuz! 自带了一个?PHP ~写的数据表修复工具 repair.phpQ虚拟主机用户也可用。该工具位于软g包的 ./utilities 目录中,使用旉要上传到服务器上论坛目录Q注意不要连 ./utilities 目录一起上传,否则无法q行Q,
upload.jpg
在浏览器q行后点M面的链接卛_
run.jpg
修复以后如果出现下面的画面表CZ复成?!!
result.jpg
q个工具能修复大多数常见的数据库错误Q尤其是错误号ؓ(f) 126?27 的错误,?145 错误也可修复Q同时能Ҏ(gu)据表在修复之后进行优化。如果一ơ修复不成功Q可以尝试多ơ,或将数据库重启后再试?
?:myisamchk 修复工具
MySQL 自带了专门用h据表查和修复的工具——myisamchkQ当 repair.php 多次修复均无法成功时Q可以在服务器终端?myisamchk q行修复。在 MySQL 的程序文件目录(见《数据备份与恢复》中的说明)可以扑ֈq个工具?
常用的修复命令ؓ(f) myisamchk -r 数据文g目录/数据表名.MYIQ如?-r 参数不能奏效Q可以先把数据文件备份(备䆾可用直接文件复制的方式Q详见《数据备份与恢复》中的说明)后?-o 参数,如果-oq不可以的话,׃?f参数,如果q是无法修复,只有使用你的备䆾文g来恢复数据了!什??你没有备份文?img title="点击囄可在新窗口打开" style="cursor: pointer" src="http://www.discuz.net/images/smilies/shocked.gif" align="absMiddle" border="0" alt="" />那你坐到那里哭?!开个玩W?但是|站?qing)时的做备䆾实是很重要?其当有一定的规模以后,每天都做备䆾!!
下面说一下具体的步骤:
1.
cmd.jpg
2.更改当前目录到mysql/bin下面,一般情况下只有在这个下面才能运行myisamchk命o(h)
myisamchk.jpg
3.修复的结?如果修复后的情况都如下图所C的?你就可以?成功?l箋开启你的网?q行?!
theresult.jpg
4.别忘了启动你的mysql,要不你的|站q是q行不v?
startmysql.jpg
ps:下面l的一个是linux下面的修复方?和上面的基本相同.只是linux下面关闭和启动mysql的方法和windows的不?一般情况下linux?br />
linux.jpg
另外 MySQL 官方文档中还提供了针对上面操作均无法奏效时的Ҏ(gu)办法Q如先清I重建数据表Q然后再用备份的数据文g覆盖{,q种特别复杂的情는户通常不会(x)到Q因此这里不再做q于深入的研I?
?数据表经常性损坏的解决Ҏ(gu)
--------------------------------------------------------------------------------
首先L(fng)认在服务器硬件不存在问题Q如内存工作不稳定、散热条件不好等Q,且用中的操作系l版本也没有相关?BUG 报告或升U补丁。这U情况下Q如果数据库仍出现经常性的损坏Q请查是?MySQL 的编译方式或参数存在问题。通常情况下用官Ҏ(gu)供的~译好的版本是比较稳定的Q可以长期用。如果?zhn)钟爱自行~译相关E序Q请认(zhn)的语言~译器(?gccQ和配置的相兛_数没有导致不E_的因素。同Ӟ盘分区满也可能是导致数据表l常性损坏的原因。网上提供了一些问题的处理Ҏ(gu)Q英文)Q需要时可多参考,qҎ(gu)的具体服务器环境制定解决Ҏ(gu)?/font>
]]>
?/font>于断甉|非正常关导致MySQL数据库出现错误是非常常见的问题。有两种Ҏ(gu)Q一U方法用mysql的check table和repair table 的sql语句Q另一U方法是使用MySQL提供的多个myisamchk, isamchk数据恢复工兗前者用v来比较简ѝ推荐用?br />
1. check table ?nbsp;repair table
登陆mysql l端Q?br />
mysql -uxxxxx -p dbname
> check table tabTest;
如果出现的结果说Status是OKQ则不用修复Q如果有ErrorQ可以用Q?br />
> repair table tabTest;
q行修复Q修复之后可以在用check table命o(h)来进行检查。在新版本的phpMyAdmin里面也可以用check/repair的功能?br />
2. myisamchk, isamchk
其中myisamchk适用于MYISAMcd的数据表Q而isamchk适用于ISAMcd的数据表。这两条命o(h)的主要参数相同,一般新的系l都使用MYISAM作ؓ(f)~省的数据表cdQ这里以myisamchkZ子进行说明。当发现某个数据表出现问题时可以使用Q?br />
myisamchk tablename.MYI
q行,如果需要修复的话,可以使用Q?br />
myisamchk -of tablename.MYI
关于myisamchk的详l参数说明,可以参见它的使用帮助。需要注意的时在q行修改时必ȝ保MySQL服务器没有访问这个数据表Q保险的情况下是最好在q行时把MySQL服务器Shutdown掉?br />
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?br />
另外可以把下面的命o(h)攑֜你的rc.local里面启动MySQL服务器前Q?br />
[ -x /tmp/mysql.sock ] && /pathtochk/myisamchk -of /DATA_DIR/*/*.MYI
其中?tmp/mysql.sock是MySQL监听的Sock文g位置Q对于用RPM安装的用户应该是/var/lib/mysql/mysql.sockQ对于用源码安装则?tmp/mysql.sock可以Ҏ(gu)自己的实际情况进行变_(d)而pathtochk则是myisamchk所在的位置QDATA_DIR是你的MySQL数据库存攄位置?br />
需要注意的Ӟ如果你打把q条命o(h)攑֜你的rc.local里面Q必ȝ认在执行q条指o(h)时MySQL服务器必L有启动!
修复所有数据库(?
mysqlcheck -A -o -r -p
---------------------------------------------------------------------------------
CZ:
mysql> check table tabFTPAccountInstances;
一、数据量q大Q数据中什么情况都可能存在。如果说?0条数据,那么大不了每条去逐一查,Zؓ(f)处理Q如果有上百条数据,也可以考虑Q如果数据上到千万别,甚至q亿Q那不是手工能解决的了,必须通过工具或者程序进行处理,其量的数据中Q什么情况都可能存在Q例如,数据中某处格式出了问题,其在程序处理时Q前面还能正常处理,H然C某个地方问题出现了,E序l止了。httpwww.itokit.com
二、Yg要求高,pȝ资源占用率高。对量的数据进行处理,除了好的Ҏ(gu)Q最重要的就是合理用工P合理分配pȝ资源。一般情况,如果处理的数据过TBU,型机是要考虑的,普通的机子如果有好的方法可以考虑Q不q也必须加大CPU和内存,p面对着千军万马Q光有勇气没有一兵一卒是很难取胜的?/p>
三、要求很高的处理Ҏ(gu)和技巧。这也是本文的写作目的所在,好的处理Ҏ(gu)是一位工E师长期工作l验的积累,也是个h的经验的ȝ。没有通用的处理方法,但有通用的原理和规则?/p>
那么处理量数据有哪些经验和技巧呢Q我把我所知道的罗列一下,以供大家参考:(x)
一、选用优秀的数据库工具httpwww.itokit.com
现在的数据库工具厂家比较多,Ҏ(gu)v量数据的处理Ҏ(gu)使用的数据库工具要求比较高,一般用Oracle或者DB2Q微软公司最q发布的SQL Server 2005性能也不错。另外在BI领域Q数据库Q数据仓库,多维数据库,数据挖掘{相兛_具也要进行选择Q象好的ETL工具和好的OLAP工具都十分必要,例如InformaticQEassbase{。笔者在实际数据分析目中,Ҏ(gu)?000万条的日志数据进行处理,使用SQL Server 2000需要花?时Q而用SQL Server 2005则只需要花?时?/p>
二、编写优良的E序代码
处理数据M开优秀的程序代码,其在进行复杂数据处理时Q必M用程序。好的程序代码对数据的处理至关重要,q不仅仅是数据处理准度的问题,更是数据处理效率的问题。良好的E序代码应该包含好的法Q包含好的处理流E,包含好的效率Q包含好的异常处理机制等?/p>
三、对量数据q行分区操作
Ҏ(gu)v量数据进行分区操作十分必要,例如针对按年份存取的数据Q我们可以按q进行分区,不同的数据库有不同的分区方式Q不q处理机制大体相同。例如SQL Server的数据库分区是将不同的数据存于不同的文gl下Q而不同的文gl存于不同的盘分区下,q样数据分散开Q减磁盘I(y)OQ减了pȝ负荷Q而且q可以将日志Q烦引等放于不同的分Z?/p>
四、徏立广泛的索引
Ҏ(gu)v量的数据处理Q对大表建立索引是必行的Q徏立烦引要考虑到具体情况,例如针对大表的分l、排序等字段Q都要徏立相应烦引,一般还可以建立复合索引Q对l常插入的表则徏立烦引时要小心,W者在处理数据Ӟ曄在一个ETL程中,当插入表Ӟ首先删除索引Q然后插入完毕,建立索引Qƈ实施聚合操作Q聚合完成后Q再ơ插入前q是删除索引Q所以烦引要用到好的时机Q烦引的填充因子和聚集、非聚集索引都要考虑?/p>
五、徏立缓存机制httpwww.itokit.com
当数据量增加Ӟ一般的处理工具都要考虑到缓存问题。缓存大设|的好差也关pd数据处理的成败,例如Q笔者在处理2亿条数据聚合操作Ӟ~存讄?00000条BufferQ这对于q个U别的数据量是可行的?/p>
六、加大虚拟内?br /> 如果pȝ资源有限Q内存提CZI则可以靠增加虚拟内存来解冟뀂笔者在实际目中曾l遇到针?8亿条的数据进行处理,内存?GBQ?个P4 2.4G的CPUQ对q么大的数据量进行聚合操作是有问题的Q提C内存不I那么采用了加大虚拟内存的Ҏ(gu)来解冻I?块磁盘分Z分别建立??096M的磁盘分区,用于虚拟内存Q这栯拟的内存则增加ؓ(f) 40966 + 1024 = 25600 MQ解决了数据处理中的内存不问题?/p>
七、分批处?
量数据处理隑֛为数据量大,那么解决量数据处理隄问题其中一个技巧是减少数据量。可以对量数据分批处理Q然后处理后的数据再q行合ƈ操作Q这样逐个ȝQ有利于数据量的处理,不至于面对大数据量带来的问题Q不q这U方法也要因时因势进行,如果不允许拆分数据,q需要另惛_法。不q一般的数据按天、按月、按q等存储的,都可以采用先分后合的Ҏ(gu)Q对数据q行分开处理?/p>
八、用(f)时表和中间表
数据量增加时Q处理中要考虑提前汇怅R这样做的目的是化整为零Q大表变表Q分块处理完成后Q再利用一定的规则q行合ƈQ处理过E中的(f)时表的用和中间l果的保存都非常重要Q如果对于超量的数据,大表处理不了Q只能拆分ؓ(f)多个表。如果处理过E中需要多步汇L作,可按汇L骤一步步来,不要一条语句完成,一口气吃掉一个胖子?/p>
?ji)、优化查询SQL语句httpwww.itokit.com
在对量数据q行查询处理q程中,查询的SQL语句的性能Ҏ(gu)询效率的影响是非常大的,~写高效优良的SQL脚本和存储过E是数据库工作h员的职责Q也是检验数据库工作人员水^的一个标准,在对SQL语句的编写过E中Q例如减关联,用或不用游标,设计好高效的数据库表l构{都十分必要。笔者在工作中试着?亿行的数据用游标,q行3个小时没有出l果Q这是一定要改用E序处理了?/p>
十、用文本格式进行处?br /> 对一般的数据处理可以使用数据库,如果对复杂的数据处理Q必d助E序Q那么在E序操作数据库和E序操作文本之间选择Q是一定要选择E序操作文本的,原因为:(x)E序操作文本速度快;Ҏ(gu)本进行处理不Ҏ(gu)出错Q文本的存储不受限制{。例如一般的量的网l日志都是文本格式或者csv格式Q文本格式)Q对它进行处理牵扯到数据清洗Q是要利用程序进行处理的Q而不导入数据库再做清z?/p>
十一?nbsp; 定制强大的清z规则和出错处理机制
量数据中存在着不一致性,极有可能出现某处的瑕c(din)例如,同样的数据中的时间字D,有的可能为非标准的时_(d)出现的原因可能ؓ(f)应用E序的错误,pȝ的错误等Q这是在q行数据处理Ӟ必须制定强大的数据清z规则和出错处理机制?/p>
十二?nbsp; 建立视图或者物化视?br /> 视图中的数据来源于基表,Ҏ(gu)v量数据的处理Q可以将数据按一定的规则分散到各个基表中Q查询或处理q程中可以基于视图进行,q样分散了磁盘I(y)OQ正?0根子吊着一Ҏ(gu)子和一根吊着一Ҏ(gu)子的区别?/p>
十三?nbsp; 避免使用32位机子(极端情况Q?br /> 目前的计机很多都是32位的Q那么编写的E序对内存的需要便受限Ӟ而很多的量数据处理是必d量消耗内存的Q这便要求更好性能的机子,其中对位数的限制也十分重要?/p>
十四?nbsp; 考虑操作pȝ问题
量数据处理q程中,除了Ҏ(gu)据库Q处理程序等要求比较高以外,Ҏ(gu)作系l的要求也放C重要的位|,一般是必须使用服务器的Q而且对系l的安全性和E_性等要求也比较高。尤其对操作pȝ自n的缓存机Ӟ临时I间的处理等问题都需要综合考虑?/p>
十五?nbsp; 使用数据仓库和多l数据库存储
数据量加大是一定要考虑OLAP的,传统的报表可??个小时出来结果,而基于Cube的查询可能只需要几分钟Q因此处理v量数据的利器是OLAP多维分析Q即建立数据仓库Q徏立多l数据集Q基于多l数据集q行报表展现和数据挖掘等?/p>
十六?nbsp; 使用采样数据Q进行数据挖?br /> Z量数据的数据挖掘正在逐步兴vQ面对着v量的数据Q一般的挖掘软g或算法往往采用数据抽样的方式进行处理,q样的误差不?x)很高,大大提高了处理效率和处理的成功率。一般采h要注意数据的完整性和Q防止过大的偏差。笔者曾l对1?千万行的表数据进行采P抽取?00万行Q经试软g试处理的误差ؓ(f)千分之五Q客户可以接受?/p>
q有一些方法,需要在不同的情况和场合下运用,例如使用代理键等操作Q这L(fng)好处是加快了聚合旉Q因为对数值型的聚合比对字W型的聚合快得多。类似的情况需要针对不同的需求进行处理?br /> 量数据是发展趋势,Ҏ(gu)据分析和挖掘也越来越重要Q从量数据中提取有用信息重要而紧q,q便要求处理要准,_ֺ要高Q而且处理旉要短Q得到有价g息要快,所以,Ҏ(gu)v量数据的研究很有前途,也很值得q行q泛深入的研I?/p>
原文地址是:(x)http://www.itokit.combbsviewthread.phptid=1876
1)不应该针Ҏ(gu)个系l进行数据库设计Q而应该根据系l架构中的组件划分,针对每个lg所处理的业务进行组件单元的数据库设计;不同lg间所对应的数据库表之间的兌应尽可能减少Q如果不同组仉的表需要外键关联也量不要创徏外键兌Q而只是记录关联表的一个主键,保lg对应的表之间的独立性,为系l或表结构的重构提供可能性?/p>
2)采用领域模型驱动的方式和自顶向下的思\q行数据库设计,首先分析pȝ业务Q根据职责定义对象。对象要W合装的特性,保与职责相关的数据被定义在一个对象之内,q些数据能够完整描q该职责Q不?x)出现职责描q缺失。ƈ且一个对象有且只有一职责,如果一个对象要负责两个或两个以上的职责Q应q行分拆?/p>
3)Ҏ(gu)建立的领域模型进行数据库表的映射Q此时应参考数据库设计W二范式Q一个表中的所有非关键字属性都依赖于整个关键字。关键字可以是一个属性,也可以是多个属性的集合Q不论那U方式,都应保关键字能够保证唯一性。在定关键字时Q应保证关键字不?x)参与业务且不?x)出现更新异常Q这Ӟ最优解x案ؓ(f)采用一个自增数值型属性或一个随机字W串作ؓ(f)表的关键字?/p>
4)׃W一Ҏ(gu)q的领域模型驱动的方式设计数据库表结构,领域模型中的每一个对象只有一职责,所以对象中的数据项不存在传递依赖,所以,q种思\的数据库表结构设计从一开始即满W三范式Q一个表应满第二范式,且属性间不存在传递依赖?/p>
5)同样Q由于对象职责的单一性以?qing)对象之间的关系反映的是业务逻辑之间的关p,所以在领域模型中的对象存在d象和从对象之分,从对象是?QN或NQN的角度进一步主对象的业务逻辑Q所以从对象?qing)对象关pLؓ(f)的表?qing)表兌关系不存在删除和插入异常?/p>
6)在映后得出的数据库表结构中Q应再根据第四范式进行进一步修改,保不存在多g赖。这Ӟ应根据反向工E的思\反馈l领域模型。如果表l构中存在多g赖,则证明领域模型中的对象具有至两个以上的职责Q应Ҏ(gu)W一条进行设计修正。第四范式:(x)一个表如果满BCNFQ不应存在多g赖?/p>
7)在经q分析后认所有的表都满二、三、四范式的情况下Q表和表之间的关联尽量采用弱兌以便于对表字D和表结构的调整和重构。ƈ且,我认为数据库中的表是用来持久化一个对象实例在特定旉?qing)特定条件下的状态的Q只是一个存储介质,所以,表和表之间也不应用强兌来表qC务(数据间的一致性)Q这一职责应由pȝ的逻辑层来保证Q这U方式也保了系l对于不正确数据Q脏数据Q的兼容性。当Ӟ从整个系l的角度来说我们q是要尽最大努力确保系l不?x)生脏数据Q单从另一个角度来_(d)脏数据的产生在一定程度上也是不可避免的,我们也要保证pȝ对这U情늚定w性。这是一个折中的Ҏ(gu)?/p>
8)应针Ҏ(gu)有表的主键和外键建立索引Q有针对性的Q针对一些大数据量和常用索方式)建立l合属性的索引Q提高检索效率。虽然徏立烦引会(x)消耗部分系l资源,但比较v在检索时搜烦整张表中的数据尤其时表中的数据量较大时所带来的性能影响Q以?qing)无索引时的排序操作所带来的性能影响Q这U方式仍然是值得提倡的?/p>
9)量采用存储过E,目前已经有很多技术可以替代存储过E的功能?#8220;对象/关系映射”{,数据一致性的保证攑֜数据库中Q无论对于版本控制、开发和部v、以?qing)数据库的迁U都?x)带来很大的影响。但不可否认Q存储过E具有性能上的优势Q所以,当系l可使用的硬件不?x)得到提升而性能又是非常重要的质量属性时Q可l过q考虑选用存储q程?/p>
10)当处理表间的兌U束所付出的代P常常是用性上的代P过了保证不?x)出C攏V删除、更改异常所付出的代Pq且数据冗余也不是主要的问题Ӟ表设计可以不W合四个范式。四个范式确保了不会(x)出现异常Q但也可能由此导致过于纯z的设计Q得表l构难于使用Q所以在设计旉要进行综合判断,但首先确保符合四个范式,然后再进行精化修正是刚刚q入数据库设计领域时可以采用的最好办法?/p>
11)设计出的表要h较好的用性,主要体现在查询时是否需要关联多张表且还需使用复杂的SQL技巧?/p>
12)设计出的表要可能减数据冗余,保数据的准性,有效的控制冗余有助于提高数据库的性能?/p>
一?nbsp; 数据库设计的几个原则
一个好的数据库产品不等于就是一个好的应用系l,如果不能设计一个合理的数据库模型,不仅?x)增加客L(fng)与服务器端的~程和维护难度,而且?x)媄响系l实际运行的性能。因此,要想开发出一Ƅ想的数据库品应遵@以下设计准则Q?/p>
Q?Q?nbsp; 命名规范?/p>
不同的数据库产品对对象的命名有不同的要求。数据库中的各种对象的命名以?qing)后台程序的代码~写应采用大写敏感的字母Ş式,各种对象命名长度不要过30个字W,q样便于应用pȝ适应不同的数据库?/p>
Q?Q?nbsp; 慎用游标(Cursor)
对多表和大表定义的游标(大的数据集合Q而言Q用游标逐行遍历数据很容易ɽE序q入漫长的等待甚x机,因此在用游标时Q可以考虑建立一个(f)时表Q将W合条g的数据行转入临时表中Q再对(f)时表定义游标q行操作Q这时性能?x)得到明显提高?/p>
Q?Q?nbsp; 索引(Index)的?/p>
索引一般用于快速访问表中的数据。大型数据库有两U烦引,即簇索引和非烦引。添加Q何一U烦引均能提高按索引列查询的速度Q但?x)降低插入、更新、删除操作的性能Q尤其是当填充因?Fill Factor)较大时。所以,如果要对索引较多的表q行频繁的插入、更新、删除操作,建立表和索引时应该设|较?yu)的填充因子Q以便在各项数据中留下较多的自q_(d)减少分割及(qing)重新重新l织的工作,q样才能够提高性能?/p>
Q?Q?nbsp; 数据的一致性和完整?/p>
Z保证数据库的一致性和完整性,设计人员往往?x)设计过多的表间兌Q尽可能地降低数据的冗余。但是,表间兌是一U强制性措施,建立后,对父表和子表的插入、更新、删除操作均要占用系l的开销。此外,最好不要用Identify属性字D作Z键与子表兌。如果数据冗余低Q数据的完整性容易得C证,但增加了表间q接查询的操作,因此Qؓ(f)了提高系l的响应旉Q合理的数据冗余也是必要的?/p>
Q?Q?nbsp; 事务的?/p>
事务是必Mơ性完成的一l操作。虽然这些操作是单个的操作,但数据库pȝ能够保证q组操作要么全部都完成,要么一炚w不做。正是大型数据库的这一Ҏ(gu),使得数据的完整性得C极大的保证?/p>
Q?Q?nbsp; 数据库性能调整
在计机g配置和网l设计确定的情况下,影响到应用系l性能的因素主要是数据库性能和客L(fng)E序设计。大多数数据库设计员采用两步法进行数据库设计Q首先进行逻辑设计Q而后q行物理设计。数据库逻辑设计去除了所有冗余数据,提高了数据吞吐速度Q保证了数据的完整性,清楚地表达数据元素之间的关系。而对于多表之间的兌查询Q尤其是大数据表Q时Q其性能会(x)降低Q同时也提高了客L(fng)E序的编E难度,因此Q物理设计需折中考虑Q根据业务规则,定兌表的数据量大、数据项的访问频度,Ҏ(gu)cL据表频繁的关联查询应适当提高数据冗余设计?/p>
Q?Q?nbsp; 数据cd的选择
数据cd的合理选择对于数据库的性能和操作具有很大的影响?/p>
? Identify字段不要作ؓ(f)表的主键与其他表兌Q这会(x)影响到该表的数据q移?/p>
? Text和Image字段属指针型数据Q主要用来存放二q制大型对象(BLOB)。这cL据的操作相比其他数据cd较慢Q因此要避开使用?/p>
? 日期型字D늚优点是有众多的日期函数支持,因此Q在日期的大比较、加减操作上非常单。但是,按照日期作ؓ(f)条g的查询操作也要用函数Q相比其他数据类型在速度上就慢许多。这是因为用函数作ؓ(f)查询的条件时Q服务器无法用先q的性能{略来优化查询,只能q行表扫描遍历每行?/p>
二?nbsp; 数据库设计的基本步骤
对于数据库设计来_(d)比较l一的看法是分ؓ(f)5个步骤:(x)需求分析,概念l构设计Q逻辑l构设计Q物理设计,数据实施和维护?/p>
1Q?nbsp; 需求分?/p>
要设计一个良好的数据库系l,首先要明应用环境对pȝ的要求。因此,对应用环境的需求收集和分析是数据库设计的W一步。需求阶D|集到的基数据和一l数据流E图是进行下一步概念设计的基础。需求分析包括以下几个方面:(x)
Q?Q?nbsp; 攉资料
攉资料是数据库设计人员和用户共同完成的d。强调各U用L(fng)参与是数据库应用pȝ设计的特点之一?/p>
Q?Q?nbsp; 分析整理
在大量资料收集完成以后,p对资料进行分析和整理。分析的q程是对所攉到的数据q行抽象的过E?/p>
Q?Q?nbsp; 数据程?/p>
在系l分析中通常采用数据程?Data Flow Diagram)来描q系l的数据向和对数据的处理功能?/p>
Q?Q?nbsp; 数据字典(Data Dictionary)
除了一套数据流E图外,q要从原始的数据资料中分析整理出下述数据信息Q数据元素的名称、同义词、性质、取D围、提供者、用者、控制权限、保密要求、用频率、数据量、数据之间联pȝ语义说明、各个部门对数据的要求以?qing)数据处理要求?/p>
Q?Q?nbsp; 用户认
数据程N和数据字典的内容必须q回l用Pq且用非专业术语与用户交?/p>
需求分析阶D늚成果要Ş成文档资料,臛_包括各项业务的数据流E图?qing)有兌明和对各cL据描q的集合Q即数据字典?/p>
2Q?nbsp; 概念l构设计
需求分析得到的用户需求抽象ؓ(f)信息l构设计?qing)概忉|型的q程是概念l构设计Q它是整个数据库设计的关键。概念徏模的q程包括定义实体集、定义联pd定义属性。当q?U成分确定之后,可以用E-RҎ(gu)来进行数据库的概念设计。在设计完全局的E-R图之后,要尽量消除冗余?/p>
3Q?nbsp; 逻辑l构设计
数据库逻辑设计的Q务是概늻构设计阶D设计好的基本E-R图,转换成特定DBMS所支持的数据模型的q程。这样开始进?#8220;实现设计”Q需要考虑具体DBMS的性能Q具体的数据模型特点。逻辑设计可分为E-R囑关系模型的{化、数据模型的优化和设计用户子模式3个过E?/p>
4Q?nbsp; 物理设计
对于l定的逻辑数据模型选取一个最适合应用环境的物理结构的q程Q称为数据库物理设计。数据库的物理设计通常分ؓ(f)两步Q确定数据库的物理结构,在关pL据库中主要指存取Ҏ(gu)与存储结构:(x)对物理结构进行评P评h(hun)的重点的旉和空间效率?/p>
5Q?nbsp; 数据库的实施和维?/p>
数据库的实施和维护过E可分数据的载入和应用程序的调试、数据库的试q行和数据库的维护与q行?/p>
一个好的数据库产品不等于就有一个好的应用系l,如果不能设计一个合理的数据库模型,不仅?x)增加客L(fng)和服务器D늨序的~程和维护的隑ֺQ而且会(x)影响pȝ实际q行的性能。一般来Ԍ在一个MISpȝ分析、设计、测试和试运行阶D,因ؓ(f)数据量较?yu),设计人员和测试h员往往只注意到功能的实玎ͼ而很难注意到性能的薄׃处,{到pȝ投入实际q行一D|间后Q才发现pȝ的性能在降低,q时再来考虑提高pȝ性能则要p更多的h力物力,而整个系l也不可避免的Ş成了一个打补丁工程。笔者依据多q来设计和用数据库的经验,提出以下一些设计准则,供同仁们参考?
命名的规?/p>
---- 不同的数据库产品对对象的命名有不同的要求Q因此,数据库中的各U对象的命名、后台程序的代码~写应采用大写敏感的Ş式,各种对象命名长度不要过30个字W,q样便于应用pȝ适应不同的数据库?/p>
游标QCursorQ的慎用
---- 游标提供了对特定集合中逐行扫描的手D,一般用游标逐行遍历数据Q根据取出的数据不同条gq行不同的操作。尤其对多表和大表定义的游标Q大的数据集合)循环很容易ɽE序q入一个O长的{特甚至LQ笔者在某市《住房公U金理pȝ》进行日l帐hU数计息处理Ӟ对一?0万个帐户的游标处理导致程序进入了一个无限期的等特(后经算需48个小时才能完成)(g环境QAlpha/4000 128Mram ,Sco Unix ,Sybase 11.0)Q后Ҏ(gu)不同的条件改成用不同的UPDATE语句得以在二十分钟之内完成。示例如下:(x)
Declare Mycursor cursor for select count_no from COUNT
Open Mycursor
Fetch Mycursor into @vcount_no
While (@@sqlstatus=0)
Begin
If @vcount_no=’’ 条g1
操作1
If @vcount_no=’’ 条g2
操作2
。。?br />
Fetch Mycursor into @vcount_no
End
。。?br />
。。?br />
改ؓ(f)
Update COUNT set 操作1 for 条g1
Update COUNT set 操作2 for 条g2
。。?br />
。。?/p>
---- 在有些场合,有时也非得用游标,此时也可考虑符合条件的数据行{入(f)时表中,再对临时表定义游标进行操作,可时性能得到明显提高。笔者在某地市〈电(sh)信收费系l〉数据库后台E序设计中,对一个表Q?万行中符合条件的30多行数据Q进行游标操?g环境QPC服务器,PII266 64Mram ,NT4.0 Ms Sqlserver 6.5)?CZ如下Q?
Create #tmp /* 定义临时?*/
(字段1
字段2
。。?br />
)
Insert into #tmp select * from TOTAL where
条g /* TOTAL?万行 W合条g只有几十?*/
Declare Mycursor cursor for select * from #tmp
/*对(f)时表定义游标*/
。。?/p>
索引(Index)的用原?/p>
---- 创徏索引一般有以下两个目的Q维护被索引列的唯一性和提供快速访问表中数据的{略。大型数据库有两U烦引即烦引和非簇索引Q一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的NQ而徏立了烦引的表,其数据在物理上会(x)按照烦引键的顺序存储,一个表只允许有一个簇索引Q因此,Ҏ(gu)B?wi)结构,可以理解dM一U烦引均能提高按索引列查询的速度Q但?x)降低插入、更新、删除操作的性能Q尤其是当填充因子(F(tun)ill FactorQ较大时。所以对索引较多的表q行频繁的插入、更新、删除操作,和烦引时因设|较?yu)的填充因子Q以便在各数据页中留下较多的自由I间Q减页分割?qing)重新组l的工作?/p>
数据的一致性和完整?/p>
---- Z保证数据库的一致性和完整性,设计人员往往?x)设计过多的表间兌QRelationQ,可能的降低数据的冗余。表间关联是一U强制性措施,建立后,对父表(Parent TableQ和子表(Child Table)的插入、更新、删除操作均要占用系l的开销Q另外,最好不要用Identify 属性字D作Z键与子表兌。如果数据冗余低Q数据的完整性容易得C证,但增加了表间q接查询的操作,Z提高pȝ的响应时_(d)合理的数据冗余也是必要的。用规则(RuleQ和U束QCheckQ来防止pȝ操作人员误输入造成数据的错误是设计人员的另一U常用手D,但是Q不必要的规则和U束也会(x)占用pȝ的不必要开销Q需要注意的是,U束Ҏ(gu)据的有效性验证要比规则快。所有这些,设计人员在设计阶D应Ҏ(gu)pȝ操作的类型、频度加以均衡考虑?/p>
事务的陷?/p>
---- 事务是在一ơ性完成的一l操作。虽然这些操作是单个的操作,SQL Server能够保证q组操作要么全部都完成,要么一炚w不做。正是大型数据库的这一Ҏ(gu),使得数据的完整性得C极大的保证?br /> ---- 众所周知QSQL Server为每个独立的SQL语句都提供了隐含的事务控Ӟ使得每个DML的数据操作得以完整提交或回滚Q但是SQL Serverq提供了昑ּ事务控制语句
---- BEGIN TRANSACTION 开始一个事?
---- COMMIT TRANSACTION 提交一个事?
---- ROLLBACK TRANSACTION 回滚一个事?
---- 事务可以嵌套Q可以通过全局变量@@trancount索到q接的事务处理嵌套层ơ。需要加以特别注意ƈ且极Ҏ(gu)使编Eh员犯错误的是Q每个显C或隐含的事物开始都使得该变量加1Q每个事务的提交使该变量?Q每个事务的回滚都会(x)使得该变量置0Q而只有当该变量ؓ(f)0时的事务提交Q最后一个提交语句时Q,q时才把物理数据写入盘?/p>
数据库性能调整
---- 在计机g配置和网l设计确定的情况下,影响到应用系l性能的因素不外乎为数据库性能和客L(fng)E序设计。而大多数数据库设计员采用两步法进行数据库设计Q首先进行逻辑设计Q而后q行物理设计。数据库逻辑设计去除了所有冗余数据,提高了数据吞吐速度Q保证了数据的完整性,清楚地表达数据元素之间的关系。而对于多表之间的兌查询Q尤其是大数据表Q时Q其性能会(x)降低Q同时也提高了客 L(fng)E序的编E难度,因此Q物理设计需折衷考虑Q根据业务规则,定对关联表的数据量大小、数据项的访问频度,Ҏ(gu)cL据表频繁的关联查询应适当提高数据冗余设计?/p>
数据cd的选择
---- 数据cd的合理选择对于数据库的性能和操作具有很大的影响Q有兌斚w的书c也有不的阐述Q这里主要介l几点经验?br /> Identify字段不要作ؓ(f)表的主键与其它表兌Q这会(x)影响到该表的数据q移?/p>
Text 和Image字段属指针型数据Q主要用来存放二q制大型对象QBLOBQ。这cL据的操作相比其它数据cd较慢Q因此要避开使用?
日期型字D늚优点是有众多的日期函数支持,因此Q在日期的大比较、加减操作上非常单。但是,在按照日期作为条件的查询操作也要用函敎ͼ相比其它数据cd速度上就慢许?因ؓ(f)用函C为查询的条gӞ服务器无法用先进的性能{略来优化查询而只能进行表扫描遍历每行?
---- 例如Q要从DATA_TAB1中(其中有一个名为DATE的日期字D)查询1998q的所有记录?
---- Select * from DATA_TAB1 where datepart(yy,DATE)=1998
2.PK采用无意义的字段Q逻辑主键Q还是有意义的字D(业务主键Q?个h們?#8220;逻辑主键”Q理由是q样设计出的数据库模型结构清晰、关p脉l清楚,往往更符?#8220;W三范式”Q虽然不是故意的Q呵呵)。而且更容易避开“联合主键”Q而且可以使用索引效率高的字段cdQ比如int、long、number。缺Ҏ(gu)用无意义的字D徏立表间的关系Q跨表查询增多Q效率下降。(矛盾无处不在Q前面刚说完可以提高效率Q这里马上又降低效率Q?#8220;业务主键”可以提升查询~码的简z度和效率?br /> 个h使用实际状况QM来说“逻辑主键”?#8220;业务主键”执行效率低,但不?x)低到无法满需求。采?#8220;逻辑主键”比采?#8220;业务主键”更利于数据库模型的结构、关pL晎ͼ也更便于l护?br /> 对于分析型数据库Q如数据仓库Q千万不要这样做?/p>
3.不要使用多对多关p?个h們于少使用多对多关pR这个问题其实不是数据库设计的问题了Q在数据库设计中Q多对多关系也仅仅存在于概念模型QE-RQ阶D,物理模型不在有多对多关系Q实际数据库中也不会(x)?#8220;多对?#8221;关系。这是用ORM时的问题Q比如用HibernateQ多对多关系有时?x)ɾ~码看v来灵zM些,代h(hun)是效率的明显降低?br /> 个h实际使用中,设计时基本不考虑多对多关p,但编码时M(x)有小l成员用一些多对多关系Q自己徏立多对多的ORMQ自己~码方便些,用在数据量小的地方,影响不大。大数据量,?#8220;止使用”?/p>
4.为每个表增加一个state字段Q我?fn)惯在设计时l每个表设一个state字段Q取??Q默认gؓ(f)1Q具体业务意义或操作上的意义可以自定义。可以作Z个状态控制字D,如查询、更新、删除条Ӟ单据是否有效Q业务单据对应的表会(x)有业务意义上?#8220;?无效”?#8220;状?#8221;字段Q这U情况下Q我q是?x)再加一个state字段Q,甚至仅仅是控制一条数据是?#8220;有效”Q有效的意义你自己定Q。在数据q移Q如转入分析用的数据库)时也可能?x)发挥作用?/p>
5.为每个表讄一些备用字D?没办法,我L设计不出“完美”的数据表Q给每个表加几个备用字段Q我一般用字符串型Q随你)可以应付“不时之需”Q尤其是需要长期维护的、业务可能有临时性变动的pȝ?/p>
6.量不要在一个表中存入其兌表的字段Q徏议不存!q样做确实可以提高查询效率,但在一个有很多表,q且兌表多的情况下Q很难保持数据的一致性!数据库结构也比较p糕。而且不存Q也不会(x)使效率十分低下?/p>
7.不要ȝ接修Ҏ(gu)据库Q个点很重要Q当需要修Ҏ(gu)Q应该先MҎ(gu)型,然后同步物理数据库,其是团队开发,否则要多做更多的事情来搞定,也可能会(x)引入更多的错误?nbsp;
本文首先讨论了基于第三范式的数据库表的基本设计,着重论qC建立主键和烦引的{略和方案,然后从数据库表的扩展设计和库表对象的攄{角度概qC数据库管理系l的优化Ҏ(gu)?
1 引言
数据库优化的目标无非是避免磁盘I(y)/O瓉、减CPU利用率和减少资源竞争。ؓ(f)了便于读者阅d理解Q笔者参阅了Sybase、Informix和Oracle{大型数据库pȝ参考资料,Z多年的工E实늻验,从基本表设计、扩展设计和数据库表对象攄{角度进行讨论,着重讨Z如何避免盘I(y)/O瓉和减资源竞争,怿读者会(x)一目了然?
2 ZW三范式的基本表设计
在基于表驱动的信息管理系l(MISQ中Q基本表的设计规范是W三范式Q?NFQ。第三范式的基本特征是非主键属性只依赖于主键属性。基于第三范式的数据库表设计h很多优点Q一是消除了冗余数据Q节省了盘存储I间Q二是有良好的数据完整性限Ӟ卛_于主外键的参照完整限制和Z主键的实体完整性限Ӟq得数据容易维护,也容易移植和更新Q三是数据的可逆性好Q在做连接(JoinQ查询或者合q表时不遗漏、也不重复;四是因消除了冗余数据Q冗余列Q, 在查询(SelectQ时每个数据存的数据行多Q这样就有效地减了逻辑I/OQ每个Cash存的面多Q也减少物理I/OQ五是对大多C?Transaction)而言Q运行性能好;六是物理设计(Physical Design)的机动性较大,能满x益增长的用户需求?
在基本表设计中,表的主键、外键、烦引设计占有非帔R要的CQ但pȝ设计人员往往只注重于满用户要求Q而没有从pȝ优化的高度来认识和重视它们。实际上Q它们与pȝ的运行性能密切相关。现在从pȝ数据库优化角度讨些基本概念及(qing)光要意义:(x)
Q?Q主?Primary Key)Q主键被用于复杂的SQL语句Ӟ频繁地在数据讉K中被用到。一个表只有一个主键。主键应该有固定|不能为Null或缺省|要有相对E_性)Q不含代码信息,易访问。把常用Q众所周知Q的列作Z键才有意义。短主键最佻I于25bytesQ,主键的长短媄响烦引的大小Q烦引的大小影响索引늚大小Q从而媄响磁盘I(y)/O。主键分然主键和Zؓ(f)主键。自然主键由实体的属性构成,自然主键可以是复合性的Q在形成复合主键Ӟ主键列不能太多,复合主键使得Join*作复杂化、也增加了外键表的大。hZ键是Q在没有合适的自然属性键、或自然属性复杂或灉|度高ӞZؓ(f)形成的。hZ键一般是整型|满最化要求Q,没有实际意义Q也略微增加了表的大;但减了把它作ؓ(f)外键的表的大?
Q?Q外键(F(tun)oreign KeyQ:(x)外键的作用是建立关系型数据库中表之间的关p(参照完整性)Q主键只能从独立的实体迁Ud非独立的实体Q成为后者的一个属性,被称为外键?
Q?Q烦?Index)Q利用烦引优化系l性能是显而易见的Q对所有常用于查询中的Where子句的列和所有用于排序的列创建烦引,可以避免整表扫描或访问,在不改变表的物理l构的情况下Q直接访问特定的数据列,q样减少数据存取旉Q利用烦引可以优化或排除耗时的分c?作;把数据分散到不同的页面上Q就分散了插入的数据Q主键自动徏立了唯一索引Q因此唯一索引也能保数据的唯一性(卛_体完整性)Q烦引码小Q定位就直接;新徏的烦引效能最好,因此定期更新索引非常必要。烦引也有代P(x)有空间开销Q徏立它也要p旉Q在q行Insert、Delete和Update*作时Q也有维护代仗烦引有两种Q聚族烦引和非聚族烦引。一个表只能有一个聚族烦引,可有多个非聚族烦引。用聚族烦引查询数据要比用非聚族索引快。在建烦引前Q应利用数据库系l函C烦引的大小?
?聚族索引QClustered IndexQ:(x)聚族索引的数据页按物理有序储存,占用I间。选择{略是,被用于Where子句的列Q包括范围查询、模p查询或高度重复的列Q连l磁盘扫描)Q被用于q接Join*作的列;被用于Order by和Group by子句的列。聚族烦引不利于插入*作,另外没有必要用主键徏聚族索引?
?非聚族烦引(Nonclustered IndexQ:(x)与聚族烦引相比,占用I间大,而且效率低。选择{略是,被用于Where子句的列Q包括范围查询、模p查询(在没有聚族烦引时Q、主键或外键列、点Q指针类Q或范_(d)q回的结果域于整表数据?0%Q查询;被用于连接Join*作的列、主键列Q范围查询)Q被用于Order by和Group by子句的列Q需要被覆盖的列。对只读表徏多个非聚族烦引有利。烦引也有其弊端Q一是创建烦引要耗费旉Q二是烦引要占有大量盘I间Q三是增加了l护代h(hun)Q在修改带烦引的数据列时索引?x)减~修攚w度Q。那么,在哪U情况下不徏索引呢?对于表Q数据小?)、小C表(不直接访问单行数据或l果集不用排序)、单值域Q返回值密集)、烦引列值太长(大于20bitysQ、容易变化的列、高度重复的列、Null值列Q对没有被用于Where子语句和Join查询的列都不能徏索引。另外,对主要用于数据录入的Q尽可能徏索引。当Ӟ也要防止建立无效索引Q当Where语句中多?个条件时Q维护烦引的开销大于索引的效益,q时Q徏立(f)时表存储有关数据更有效?
扚w导入数据时的注意事项Q在实际应用中,大批量的计算Q如?sh)信话单计费Q用C语言E序做,q种Zd键关pL据计而得的批量数据(文本文gQ,可利用系l的自n功能函数Q如Sybase的BCP命o(h)Q快速批量导入,在导入数据库表时Q可先删除相应库表的索引Q这有利于加快导入速度Q减导入时间。在导入后再重徏索引以便优化查询?
Q?Q锁Q锁是ƈ行处理的重要机制Q能保持数据q发的一致性,x事务q行处理Q系l利用锁Q保证数据完整性。因此,我们避免不了死锁Q但在设计时可以充分考虑如何避免长事务,减少排它锁时_(d)减少在事务中与用L(fng)交互Q杜l让用户控制事务的长短;要避免批量数据同时执行,其是耗时q用到相同的数据表。锁的征用:(x)一个表同时只能有一个排它锁Q一个用L(fng)Ӟ其它用户在等待。若用户数增加,则Server的性能下降Q出?#8220;假死”现象。如何避免死锁呢Q从锁到行锁,减少了锁征用Q给表增加无效记录Q从锁到行锁没有媄响,若在同一内竞争有媄响,可选择合适的聚族索引把数据分配到不同的页面;创徏冗余表;保持事务短;同一批处理应该没有网l交互?
Q?Q查询优化规则:(x)在访问数据库表的数据(Access Data)Ӟ要尽可能避免排序QSortQ、连?Join)和相兛_查询*作。经验告诉我们,在优化查询时Q必d刎ͼ(x)
?可能少的行Q?
?避免排序或ؓ(f)可能少的行排序Q若要做大量数据排序Q最好将相关数据攑֜临时表中*作;用简单的键(列)排序Q如整型或短字符串排序;
?避免表内的相兛_查询Q?
?避免在Where子句中用复杂的表达式或非v始的子字W串、用长字W串q接Q?
?在Where子句中多使用“?#8221;QAndQ连接,?#8220;?#8221;(Or)q接Q?
?利用临时数据库。在查询多表、有多个q接、查询复杂、数据要qo(h)Ӟ可以Z(f)时表Q烦引)以减I/O。但~点是增加了I间开销?
除非每个列都有烦引支持,否则在有q接的查询时分别扑և两个动态烦引,攑֜工作表中重新排序?
3 基本表扩展设?
ZW三范式设计的库表虽然有其优性(见本文第一部分Q,然而在实际应用中有时不利于pȝq行性能的优化:(x)如需要部分数据时而要扫描整表Q许多过E同时竞争同一数据Q反复用相同行计相同的l果Q过E从多表获取数据时引发大量的q接*作,当数据来源于多表时的q接*作;q都消耗了盘I(y)/O和CPU旉?
其在遇C列情形时Q我们要对基本表q行扩展设计Q许多过E要频繁讉K一个表、子集数据访问、重复计和冗余数据Q有时用戯求一些过E优先或低的响应旉?/p>
如何避免q些不利因素呢?Ҏ(gu)讉K的频J程度对相关表进行分割处理、存储冗余数据、存储衍生列、合q相兌处理Q这些都是克服这些不利因素和优化pȝq行的有效途径?
3.1 分割表或储存冗余数据
分割表分为水q_割表和垂直分割表两种。分割表增加了维护数据完整性的代h(hun)?
水^分割表:(x)一U是当多个过E频J访问数据表的不同行Ӟ水^分割表,q消除新表中的冗余数据列Q若个别q程要访问整个数据,则要用连?作,q也无妨分割表;典型案例是电(sh)信话单按月分割存放。另一U是当主要过E要重复讉K部分行时Q最好将被重复访问的q些行单独Ş成子集表Q冗余储存)Q这在不考虑盘I间开销时显得十分重要;但在分割表以后,增加了维护难度,要用触发器立x新、或存储q程或应用代码批量更斎ͼq也?x)增加额外的盘I(y)/O开销?
垂直分割表(不破坏第三范式)Q一U是当多个过E频J访问表的不同列Ӟ可将表垂直分成几个表Q减磁盘I(y)/OQ每行的数据列少Q每存的数据行多Q相应占用的就)Q更新时不必考虑锁,没有冗余数据。缺Ҏ(gu)要在插入或删除数据时要考虑数据的完整性,用存储过E维护。另一U是当主要过E反复访问部分列Ӟ最好将q部分被频繁讉K的列数据单独存ؓ(f)一个子集表Q冗余储存)Q这在不考虑盘I间开销时显得十分重要;但这增加了重叠列的维护难度,要用触发器立x新、或存储q程或应用代码批量更斎ͼq也?x)增加额外的盘I(y)/O开销。垂直分割表可以辑ֈ最大化利用Cache的目的?
MQؓ(f)主要q程分割表的Ҏ(gu)适用于:(x)各个q程需要表的不联结的子集,各个q程需要表的子集,讉K频率高的主要q程不需要整表。在主要的、频J访问的主表需要表的子集而其它主要频J访问的q程需要整表时则生冗余子集表?
注意Q在分割表以后,要考虑重新建立索引?
3.2 存储衍生数据
对一些要做大量重复性计的q程而言Q若重复计算q程得到的结果相同(源列数据E_Q因此计结果也不变Q,或计牵扯多行数据需额外的磁盘I(y)/O开销Q或计算复杂需要大量的CPU旉Q就考虑存储计算l果Q冗余储存)。现予以分类说明Q?
若在一行内重复计算Q就在表内增加列存储l果。但若参与计的列被更新Ӟ必须要用触发器更新这个新列?
若对表按c进行重复计,增加新表(一般而言Q存攄和结果两列就可以了)存储相关l果。但若参与计的列被更新Ӟ必要用触发器立即更新、或存储q程或应用代码批量更新这个新表?
若对多行q行重复性计(如排名次Q,在表内增加列存储结果。但若参与计的列被更新Ӟ必须要用触发器或存储q程更新q个新列?
MQ存储冗余数据有利于加快讉K速度Q但q反了第三范式,q会(x)增加l护数据完整性的代h(hun)Q必ȝ触发器立x新、或存储q程或应用代码批量更斎ͼ以维护数据的完整性?
3.3 消除昂贵l合
对于频繁同时讉K多表的一些主要过E,考虑在主表内存储冗余数据Q即存储冗余列或衍生列(它不依赖于主键)Q但破坏了第三范式,也增加了l护隑ֺ。在源表的相兛_发生变化Ӟ必须要用触发器或存储q程更新q个冗余列。当主要q程d时访问两个表时可以合q表Q这样可以减磁盘I(y)/O*作,但破坏了W三范式Q也增加了维护难度。对父子表和1Q?关系表合q方法不同:(x)合ƈ父子表后Q生冗余表Q合q?Q?关系表后Q在表内产生冗余数据?
4 数据库对象的攄{略
数据库对象的攄{略是均匀地把数据分布在系l的盘中,qI/O讉KQ避免I/O瓉?
?讉K分散C同的盘Q即使用h据尽可能跨越多个讑֤Q多个I/Oq{Q避免I/O竞争Q克服访问瓶颈;分别攄随机讉K和连l访问数据?
?分离pȝ数据库I/O和应用数据库I/O。把pȝ审计表和临时库表攑֜不忙的磁盘上?
?把事务日志放在单独的盘上,减少盘I(y)/O开销Q这q有利于在障后恢复Q提高了pȝ的安全性?
?把频J访问的“zL?#8221;表放在不同的盘上;把频J用的表、频J做Join*作的表分别放在单独的盘上,甚至把把频繁讉K的表的字D|在不同的盘上,把访问分散到不同的磁盘上Q避免I/O争夺Q?
?利用D分频J访问的表及(qing)其烦引(非聚族的Q、分L本和囑փ数据。段的目的是qI/OQ避免瓶颈,增加吞吐量,实现q行扫描Q提高ƈ发度Q最大化盘的吞吐量。利用逻辑D功能,分别攄“zL?#8221;表及(qing)光聚族索引以^衡I/O。当然最好利用系l的默认Dc(din)另外,利用D可以备䆾和恢复数据更加灵z,使系l授权更加灵zR?/p>
随着计算机技术越来越q泛地应用于国民l济的各个领域,在计机g不断微型化的同时Q应用系l向着复杂化、大型化的方向发展。数据库是整个系l的核心Q它的设计直接关pȝl执行的效率和系l的E_性。因此在软gpȝ开发中Q数据库设计应遵循必要的数据库范式理论,以减冗余、保证数据的完整性与正确性。只有在合适的数据库品上设计出合理的数据库模型,才能降低整个pȝ的编E和l护隑ֺQ提高系l的实际q行效率。虽然对于小目或中{规模的目开发h员可以很Ҏ(gu)地利用范式理计出一套符合要求的数据库,但对于一个包含大型数据库的Y仉目,必L一套完整的设计原则与技巧?/p>
一、成立数据小l?/p>
大型数据库数据元素多Q在设计上有必要成立专门的数据小l。由于数据库设计者不一定是使用者,对系l设计中的数据元素不可能考虑周全Q数据库设计出来后,往往难以扑ֈ所需的库表,因此数据组最好由熟?zhn)业务的项目骨q组成?/p>
数据组的职能ƈ非是设计数据库,而是通过需求分析,在参考其他相似系l的基础上,提取pȝ的基本数据元素,担负Ҏ(gu)据库的审核。审核内容包括审核新的数据库元素是否完全、能否实现全部业务需?Ҏ(gu)数据?如果存在旧系l?的分析及(qing)数据转换;数据库设计的审核、控制及(qing)必要调整?/p>
二、设计原?/p>
1.规范命名。所有的库名、表名、域名必遵循统一的命名规则,q进行必要说明,以方便设计、维护、查询?/p>
2.控制字段的引用。在设计Ӟ可以选择适当的数据库设计理工具Q以方便开发h员的分布式设计和数据组的集中审核管理。采用统一的命名规则,如果设计的字D已l存在,可直接引?否则Q应重新设计?/p>
3.库表重复控制。在设计q程中,如果发现大部分字D都已存在,开发h员应怀疑所设计的库表是否已存在。通过对字D|在库表及(qing)相应设计人员的查询,可以认库表是否实重复?/p>
4.q发控制。设计中应进行ƈ发控Ӟ卛_于同一个库表,在同一旉只有一个h有控制权Q其他h只能q行查询?/p>
5.必要的讨论。数据库设计完成后,数据组应与相关人员q行讨论Q通过讨论来熟(zhn)数据库Q从而对设计中存在的问题q行控制或从中获取数据库设计的必要信息?/p>
6.数据组的审核。库表的定版、修Ҏ(gu)l都要通过数据组的审核,以保证符合必要的要求?/p>
7.头文件处理。每ơ数据修改后Q数据小l要对相应的头文件进行修?可由理软g自动完成)Qƈ通知相关的开发h员,以便q行相应的程序修攏V?/p>
三、设计技?/p>
1.分类拆分数据量大的表。对于经怋用的?如某些参数表或代码对照表)Q由于其使用频率很高Q要量减少表中的记录数量。例如,银行的户主̎表原来设计成一张表Q虽然可以方便程序的设计与维护,但经q分析发玎ͼ׃数据量太大,?x)媄响数据的q速定位。如果将户主账表分别设计为活期户主̎、定期户主̎?qing)对公户主̎{,则可以大大提高查询效率?/p>
2.索引设计。对于大的数据库表,合理的烦引能够提高整个数据库的操作效率。在索引设计中,索引字段应挑选重复D?yu)的字?在对建有复合索引的字D进行检索时Q应注意按照复合索引字段建立的顺序进行。例如,如果对一?万多条记录的水表以日期和流水号为序建立复合索引Q由于在该表中日期的重复值接q整个表的记录数Q用水可行查询所用的旉接近3U?而如果以水号ؓ(f)索引字段建立索引q行相同的查询,所用时间不?U。因此在大型数据库设计中Q只有进行合理的索引字段选择Q才能有效提高整个数据库的操作效率?/p>
3.数据操作的优化。在大型数据库中Q如何提高数据操作效率值得x。例如,每在数据库流水表中增加一W业务,必M水控制表中取出水Pq将其流水号的数值加一。正常情况下Q单W操作的反应速度属正常Q但当用它进行批量业务处理时Q速度?x)明昑և慢。经q分析发玎ͼ每次Ҏ(gu)水控制表中的水h值加一旉要锁定该表,而该表却是整个系l操作的核心Q有可能在操作时被其他进E锁定,因而整个事务操作速度变慢。对q一问题的解决的办法是,Ҏ(gu)扚w业务的ȝ数批量申h水号QƈҎ(gu)水控制表q行一ơ更斎ͼ卛_提高扚w业务处理的速度。另一个例子是Ҏ(gu)表的优化。对于大扚w的业务处理,如果在插入数据库表时用普通的Insert语句Q速度?x)很慢。其原因在于Q每ơ插表都要进行一ơI/O操作Q花费较长的旉。改q后Q可以用Put语句{缓冲区形式{满后再进行I/O操作Q从而提高效率。对大的数据库表q行删除Ӟ一般会(x)直接用Delete语句Q这个语句虽然可以进行小表操作,但对大表却会(x)因带来大事务而导致删除速度很慢甚至p|。解决的Ҏ(gu)是去掉事务,但更有效的办法是先进行Drop操作再进行重建?/p>
4.数据库参数的调整。数据库参数的调整是一个经验不断积累的q程Q应由有l验的系l管理员完成。以Informix数据库ؓ(f)例,记录锁的数目太少?x)造成锁表的失?逻辑日志的文件数目太会(x)造成插入大表p|{,q些问题都应Ҏ(gu)实际情况q行必要的调整?/p>
5.必要的工兗在整个数据库的开发与设计q程中,可以先开发一些小的应用工P如自动生成库表的头文件、插入数据的初始化、数据插入的函数装、错误跟t或自动昄{,以此提高数据库的设计与开发效率?/p>
6.避免长事务。对单个大表的删除或插入操作?x)带来大事务Q解决的办法是对参数q行调整Q也可以在插入时Ҏ(gu)件进行分剌Ӏ对于一个由一pd事务顺序操作共同构成的长事?如银行交易系l的日终交易)Q可以由一pd操作完成整个事务Q但其缺Ҏ(gu)有可能因整个事务太大而不能完成Q或者,׃偶然的意外而事务重做所需的时间太ѝ较好的解决Ҏ(gu)是,把整个事务分解成几个较小的事务,再由应用E序控制整个pȝ的流E。这P如果其中某个事务不成功,则只需重做该事务,因而既可节U时_(d)又可避免长事务?/p>
7.适当前。计机技术发展日新月异,数据库的设计必须h一定前L,不但要满_前的应用要求Q还要考虑未来的业务发展,同时必须有利于扩展或增加应用pȝ的处理功能?/p>
相对于中型数据库,大型数据库的设计与开发要复杂得多Q因此在设计、开发过E中Q除了要遵@数据库范式理论、增加系l的一致性和完整性外Q还要在M上根据具体情况进行分布式设计Q紧紧把握集中控制、统一审核的基本原则,保证数据库设计结构紧凑、分布^衡、定位迅速。在数据库操作上Q要采用一定的技巧提高整个应用系l的执行效率Qƈ注意适当前Q以适应不断变化的应用及(qing)pȝ发展的要求?/p>
1. 原始单据与实体之间的关系
可以是一对一、一对多、多对多的关pR在一般情况下Q它们是一对一的关p:(x)即一张原始单据对
应且只对应一个实体。在Ҏ(gu)情况下,它们可能是一对多或多对一的关p,即一张原始单证对应多个实
体,或多张原始单证对应一个实体。这里的实体可以理解为基本表。明这U对应关pdQ对我们设计
录入界面大有好处?/p>
〖例1〗:(x)一份员工历资料,在h力资源信息系l中Q就对应三个基本表:(x)员工基本情况表、社?/p>
关系表、工作简历表。这是“一张原始单证对应多个实?#8221;的典型例子?/p>
2. 主键与外?/p>
一般而言Q一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实? 可以定义主键Q?/p>
也可以不定义主键(因ؓ(f)它无子孙), 但必要有外?因ؓ(f)它有父亲)?/p>
主键与外键的设计Q在全局数据库的设计中,占有重要C。当全局数据库的设计完成以后Q有?/p>
国数据库设计专家说Q?#8220;键,到处都是键,除了键之外,什么也没有”Q这是他的数据库设计经?/p>
之谈Q也反映了他对信息系l核?数据模型)的高度抽象思想。因为:(x)主键是实体的高度抽象Q主键与
外键的配对,表示实体之间的连接?/p>
3. 基本表的性质
基本表与中间表、(f)时表不同Q因为它h如下四个Ҏ(gu):(x)
(1) 原子性。基本表中的字段是不可再分解的?/p>
(2) 原始性。基本表中的记录是原始数据(基础数据Q的记录?/p>
(3) 演绎性。由基本表与代码表中的数据,可以z出所有的输出数据?/p>
(4) E_性。基本表的结构是相对E_的,表中的记录是要长期保存的?/p>
理解基本表的性质后,在设计数据库Ӟp基本表与中间表、(f)时表区分开来?/p>
4. 范式标准
基本表及(qing)其字D之间的关系, 应尽量满第三范式。但是,满W三范式的数据库设计Q往往不是
最好的设计。ؓ(f)了提高数据库的运行效率,常常需要降低范式标准:(x)适当增加冗余Q达CI间换时?/p>
的目的?/p>
〖例2〗:(x)有一张存攑֕品的基本表,如表1所C?#8220;金额”q个字段的存在,表明该表的设计不?/p>
第三范式,因ؓ(f)“金额”可以?#8220;单h(hun)”乘以“数量”得到Q说?#8220;金额”是冗余字Dc(din)但是,增加
“金额”q个冗余字段Q可以提高查询统计的速度Q这是以空间换旉的作法?/p>
在Rose 2002中,规定列有两种cdQ数据列和计列?#8220;金额”q样的列被称?#8220;计算?#8221;Q?#8220;
单h(hun)”?#8220;数量”q样的列被称?#8220;数据?#8221;?/p>
? 商品表的表结?/p>
商品名称 商品型号 单h(hun) 数量 金额
?sh)视?29?2,500 40 100,000
5. 通俗地理解三个范?/p>
通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中Qؓ(f)了更好地应用三个范式Q就
必须通俗地理解三个范?通俗地理解是够用的理解,q不是最U学最准确的理?Q?/p>
W一范式Q?NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
W二范式Q?NF是对记录的惟一性约束,要求记录有惟一标识Q即实体的惟一性;
W三范式Q?NF是对字段冗余性的U束Q即M字段不能由其他字D|生出来,它要求字D|有冗?/p>
?/p>
没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时Z提高q?/p>
行效率,必降低范式标准,适当保留冗余数据。具体做法是Q在概念数据模型设计旉守第三范?/p>
Q降低范式标准的工作攑ֈ物理数据模型设计时考虑。降低范式就是增加字D,允许冗余?/p>
6. 要善于识别与正确处理多对多的关系
若两个实体之间存在多对多的关p,则应消除q种关系。消除的办法是,在两者之间增加第三个?/p>
体。这P原来一个多对多的关p,现在变ؓ(f)两个一对多的关pR要原来两个实体的属性合理地分配
C个实体中厅R这里的W三个实体,实质上是一个较复杂的关p,它对应一张基本表。一般来Ԍ?/p>
据库设计工具不能识别多对多的关系Q但能处理多对多的关pR?/p>
〖例3〗:(x)?#8220;图书馆信息系l?#8221;中,“图书”是一个实体,“读?#8221;也是一个实体。这两个实体?/p>
间的关系Q是一个典型的多对多关p:(x)一本图书在不同旉可以被多个读者借阅Q一个读者又可以借多
本图书。ؓ(f)此,要在二者之间增加第三个实体Q该实体取名?#8220;借还?#8221;Q它的属性ؓ(f)Q借还旉、?/p>
q标?0表示借书Q?表示q书)Q另外,它还应该有两个外?“图书”的主键,“读?#8221;的主?Q
它能?#8220;图书”?#8220;读?#8221;q接?/p>
7. 主键PK的取值方?/p>
PK是供E序员用的表间q接工具Q可以是一无物理意义的数字? q序自动加1来实现。也?/p>
以是有物理意义的字段名或字段名的l合。不q前者比后者好。当P(yng)K是字D名的组合时Q徏议字D늚?/p>
C要太多,多了不但索引占用I间大,而且速度也慢?/p>
8. 正确认识数据冗余
主键与外键在多表中的重复出现, 不属于数据冗余,q个概念必须清楚Q事实上有许多hq不清楚
。非键字D늚重复出现, 才是数据冗余Q而且是一U低U冗余,即重复性的冗余。高U冗余不是字D늚
重复出现Q而是字段的派生出现?/p>
〖例4〗:(x)商品中的“单h(hun)、数量、金?#8221;三个字段Q?#8220;金额”是?#8220;单h(hun)”乘以“数量”z?/p>
来的Q它?yu)是冗余Q而且是一U高U冗余。冗余的目的是ؓ(f)了提高处理速度。只有低U冗余才?x)增加?/p>
据的不一致性,因ؓ(f)同一数据Q可能从不同旉、地炏V角色上多次录入。因此,我们提倡高U冗?z?/p>
生性冗?Q反对低U冗?重复性冗??/p>
9. E--R图没有标准答?/p>
信息pȝ的E--R图没有标准答案,因ؓ(f)它的设计与画法不是惟一的,只要它覆盖了pȝ需求的业务
范围和功能内容,是可行的。反之要修改E--R图。尽它没有惟一的标准答案,q不意味着可以随意
设计。好的E—R囄标准是:(x)l构清晰、关联简z、实体个数适中、属性分配合理、没有低U冗余?/p>
10. 视图技术在数据库设计中很有?/p>
与基本表、代码表、中间表不同Q视图是一U虚表,它依赖数据源的实表而存在。视图是供程序员
使用数据库的一个窗口,是基表数据综合的一UŞ? 是数据处理的一U方法,是用h据保密的一U?/p>
手段。ؓ(f)了进行复杂处理、提高运速度和节省存储空? 视图的定义深度一般不得超q三层?若三?/p>
视图仍不够用, 则应在视图上定义临时? 在(f)时表上再定义视图。这样反复交q定? 视图的深度就
不受限制了?/p>
对于某些与国家政沅R经、技术、军事和安全利益有关的信息系l,视图的作用更加重要。这?/p>
pȝ的基本表完成物理设计之后Q立卛_基本表上建立W一层视图,q层视图的个数和l构Q与基本?/p>
的个数和l构是完全相同。ƈ且规定,所有的E序员,一律只准在视图上操作。只有数据库理员,?/p>
着多个人员共同掌握?#8220;安全钥匙”Q才能直接在基本表上操作。请读者想惻I(x)q是Z么?
11. 中间表、报表和临时?/p>
中间表是存放l计数据的表Q它是ؓ(f)数据仓库、输出报表或查询l果而设计的Q有时它没有主键?/p>
外键(数据仓库除外)。(f)时表是程序员个h设计的,存放临时记录Qؓ(f)个h所用。基表和中间表由DBAl?/p>
护,临时表由E序员自qE序自动l护?/p>
12. 完整性约束表现在三个斚w
域的完整性:(x)用Check来实现约束,在数据库设计工具中,对字D늚取D围进行定义时Q有一个Ch
eck按钮Q通过它定义字D늚值城?/p>
参照完整性:(x)用PK、FK、表U触发器来实现?/p>
用户定义完整性:(x)它是一些业务规则,用存储过E和触发器来实现?/p>
13. 防止数据库设计打补丁的方法是“三少原则”
(1) 一个数据库中表的个数越越好。只有表的个数少了,才能说明pȝ的E--R囑ְ而精Q去掉了
重复的多余的实体QŞ成了对客观世界的高度抽象Q进行了pȝ的数据集成,防止了打补丁式的设计Q?/p>
(2) 一个表中组合主键的字段个数少好。因Z键的作用Q一是徏主键索引Q二是做为子表的
外键Q所以组合主键的字段个数了Q不仅节省了q行旉Q而且节省了烦引存储空_(d)
(3) 一个表中的字段个数少好。只有字D늚个数了Q才能说明在pȝ中不存在数据重复Q且
很少有数据冗余,更重要的是督促读者学?#8220;列变?#8221;Q这样就防止了将子表中的字段拉入C表中?/p>
Q在主表中留下许多空余的字段。所?#8220;列变?#8221;Q就是将主表中的一部分内容拉出去,另外单独Z
个子表。这个方法很单,有的人就是不?fn)惯、不采纳、不执行?/p>
数据库设计的实用原则是:(x)在数据冗余和处理速度之间扑ֈ合适的q炏V?#8220;三少”是一个整体概
念,l合观点Q不能孤立某一个原则。该原则是相对的Q不是绝对的?#8220;三多”原则肯定是错误的。试
惻I(x)若覆盖系l同L(fng)功能Q一百个实体(׃千个属? 的E--R图,肯定比二百个实体(׃千个属?
的E--R图,要好得多?/p>
提?#8220;三少”原则Q是叫读者学?x)利用数据库设计技术进行系l的数据集成。数据集成的步骤是将
文gpȝ集成为应用数据库Q将应用数据库集成ؓ(f)主题数据库,主题数据库集成为全局l合数据库?/p>
集成的程度越高,数据׃n性就强Q信息孤岛现象就少Q整个企业信息系l的全局E—R图中实体?/p>
个数、主键的个数、属性的个数׃(x)少?/p>
提?#8220;三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改Q企业数据
库变成了随意设计数据库表?#8220;垃圾?#8221;Q或数据库表?#8220;大杂?#8221;Q最后造成数据库中的基本表、代
码表、中间表、(f)时表杂ؕ无章Q不计其敎ͼD企事业单位的信息pȝ无法l护而瘫痪?/p>
“三多”原则M人都可以做到Q该原则?#8220;打补丁方?#8221;设计数据库的歪理学说?#8220;三少”原则
是少而精的原则,它要求有较高的数据库设计技巧与艺术Q不是Q何h都能做到的,因ؓ(f)该原则是杜绝
?#8220;打补丁方?#8221;设计数据库的理论依据?/p>
14. 提高数据库运行效率的办法
在给定的pȝg和系lY件条件下Q提高数据库pȝ的运行效率的办法是:(x)
(1) 在数据库物理设计Ӟ降低范式Q增加冗? 用触发? 多用存储q程?/p>
(2) 当计非常复杂、而且记录条数非常巨大?例如一千万?Q复杂计要先在数据库外面,?/p>
文gpȝ方式用C++语言计算处理完成之后Q最后才入库q加到表中去。这是电(sh)信计费系l设计的l验?/p>
(3) 发现某个表的记录太多Q例如超q一千万条,则要对该表进行水q_剌Ӏ水q_割的做法是,
以该表主键PK的某个gؓ(f)界线Q将该表的记录水q_割ؓ(f)两个表。若发现某个表的字段太多Q例如超q?/p>
八十个,则垂直分割该表,原来的一个表分解Z个表?/p>
(4) Ҏ(gu)据库理pȝDBMSq行pȝ优化Q即优化各种pȝ参数Q如~冲Z数?/p>
(5) 在用面向数据的SQL语言q行E序设计Ӟ量采取优化法?/p>
MQ要提高数据库的q行效率Q必M数据库系l优化、数据库设计U优化、程序实现优化
Q这三个层次上同时下功夫?/p>
上述十四个技巧,是许多h在大量的数据库分析与设计实践中,逐步ȝ出来的。对于这些经验的
q用Q读者不能生帮硬套,死记背Q而要消化理解Q实事求是,灉|掌握。ƈ逐步做到Q在应用中发
展,在发展中应用?/p>
?/strong>
数据库已l是l大多数IT应用的核心,各种数据库看上去很大不同Q多层体pȝ构以?qing)SOA的发展,使得应用逻辑的实现前UR数据库的性能Q与其功能相比较Q变得越来越重要了。因此,性能是衡量数据库的非帔R要的斚wQ我们这里将讨论数据库性能基准的五个常见问题?/p>
1.Windows和LinuxQ哪个操作系l的性能基准l果更好Q?/strong>
q是一个有争议的很隑֛{的问题。虽然大部分可能认ؓ(f)Linux可能更快一些,但是Windows serverq_在过ȝ几年中已l快速成熟了。下面是图表1,它是在相同的g环境下执行得到的在线TPC-C基准l果的图表,使用?2位和64位的Windows 2003 Server Release 2 ?CentOS 4 Update 3 (一个免费Redhat的企业版??/p>
你可以看刎ͼ技术上看来是不分胜负的。因?你可以按自己意愿选择Q或者考虑到培训成本,可以选择拥有较多pȝ理员的那个操作pȝ?/p>
?
2. 32位还?4位,哪种更好?q会(x)影响操作pȝ的选择?
64位Unix 服务器已l有很多q了,?4位的Windows操作pȝ才刚刚变成现实?Windows NT可运行在DEC Alpha?但一直没有真正进入主?很长一D|_(d)AMD的Athlon-64和Opteron处理器一直很。直?006q中Intel的二代双核CPU的出玎ͼ它的表现相当让h惊讶Q现在我们可以用更好的h(hun)D买这些硬件。我们将能耗和戉K制冷都计到TCO中?/p>
?2位相比,64位真的有明显差异?Ҏ(gu)图表1,回答是否定的。但那是因ؓ(f)64位提供的主要优势在于增加了可d内存。图?再ơ显CTPC-C基准执行的结果,但系l和数据库可以分配的内存的L量增加了。
?
我们有了q些很清楚的l果。这些数据显C?如果你的服务器有2GB或少一些的内存,?2位和64位的处理下没有明昄差别。但当你的服务器的内存增加到过2GB以后,64位的优势׃(x)昄出来.管诸如Oracle数据库有32位联接选项来欺骗数据库Q之可以访问稍多的内存(知名的巨大内存模?Q这仅仅只能有一Ҏ(gu)果。特大内存对pȝ和数据库来说Q可以不断实现性能的改q?/p>
一般情况下Q服务器的内存大?GBӞ使用64位。不q值得注意的是Q有时某些类型的gQ例如驱动器QiSCSQ和更新的数据库选项(例如QASM,OCFS)?2位的Linux上工作得更好?/p>
3.哪个数据库拥有最好的性能基准QOracle 10gQSQL Server 2005 q是MySQL 5.0?
q也是一个有争议的问题。说到它Q仅仅是把经常提到最多的三个数据库拿来讨论。(q里q不是有意忽略DB2QUDBQPostgreSQL或所有的其他数据库)。我们知道数据库厂商一般是不欢q公布性能基准数据的,特别是在它们之间的比较情c(din)尽如此,我们来讨个常见的问题。图?昄了在MySQL,SQL Server和Oracle数据库上执行的TPCQC基准的结果?
?
y的是我们不必冒Q何厂商愤怒的风险Q因为性能l果昄Q它们的技术不分胜负。同P你可以按照你的意愉K择数据库,或者是哪个数据库管理员多就选择哪一个?/p>
当然Q在q些厂商之间的花Ҏ(gu)不同的,但是因ؓ(f)没有Z(x)按照报h(hun)购买产品Q所以按照这个因素进行比较TPC-C是很困难的?/p>
4.如何定一个服务器所能支持的最大ƈ发OLTP用户?
q始l是一个很隑֛{得问题Q因Zh们经常想听到Q?#8220;Dell 1850能处理多的q发用户量?#8221;事实上,即是同一pd的服务器Q有相同的内存容量,但是也会(x)׃CPU的数量、CPU的时钟频率、CPU的内核数、高速缓冲存储器的大等因素D能力的差异。比较服务器是很困难的,除非你有看v来几乎一样配|的机器。但是你也需要比较相同的|络和磁盘I(y)O{情c(din)假设你那样做,问题变成你如何分析这L(fng)基准l果Qƈ准确定那台服务器的最大ƈ发用戯载。图?昄了TPC-C基准的结果,只在一台服务器上确定拐点(即用戯载开始对响应旉有负面媄响)?/p>
?
如果你的最l用戯求响应时_(d)最常见的指标)于2U,那么?00个ƈ发用戯个点你应该停下来。图4昄q个服务器可支持多达250个用户ƈ发直到响应时间达到无法接受的急骤上升的点. 在这U情况下QTPS比率开始趋于^~或减少Q这个例子中yQ这两个点同时出现。但是ƈ不L如此明显;q是因ؓ(f)有时两个拐点q不一定排列的q么整齐。当拿不准时Q徏议通常xTPC-C或OLTPcd事务的响应时间?/p>
5.如何定一个服务器所能支持的最大数据仓库大?
q又是一个很隑֛{的问题Q因为大多数人想听到是,“处理X千兆字节的数据需要一台Dell 1850?#8221;上文中提刎ͼ比较服务器是不容易的事情Q除非你拥有的主机几乎有一L(fng)配置Q以?qing)一L(fng)|络和磁盘I(y)/O环境。磁盘I(y)/O在这里是特别重要的,因ؓ(f)TPC-Hl果大部分是q盘数量来军_的。如果能比较服务器,那么问题变为如何从基准l果中确定那台指定服务器的最大数据仓库的大小。在图表5中,昄了基于几个强大的Oracle RAC服务器配|的TPC-H基准的测试结果。这些服务器讉K分布在多个SAN和超q?00个磁盘上?00GB数据?/p>
?
在TPC-H中,值得注意的是Q应该同时关注整体运行时和间q_响应旉。TPC-H的询问是非常复杂的,通常要花C时Q或好几天才能完成?/p>
Ҏ(gu)图表6Q最好的g配置大运?时Q^均响应时间约4时。然而,通过几次q行旉很长的测试,实际的响应时间的变化是很倾斜的。因此,如果你的用户对于高度复杂的决{支持查询能接受q行旉?个小时的Q?个节点的集群可以满求。如果不能接受的话,那么需要购买更多磁盘,而不是增加更多的服务器。对于千兆容量的数据仓库Q?00?000个磁盘可以达到最佳的效果Q这U情况ƈ不少见?/p>
?
很早以前Q也是一提到SQL ServerQ就觉得它的性能没法跟Oracle相比Q一提到大数据处理就惛_Oracle。自׃路走来,在本地blog上记录了很多优化斚w?postQ对的错的都有,没有旉pd的整理出来,q篇文章joinҎ(gu)的概늨微整理在一Pl大家个参考。通过查资料了解里面提到的各种概念Q在?际中不断验证ȝQ完全可以对数据库一步步深入理解下去的?/p>
我只对SQL Server 2000比较了解Q但qƈ不阻我在Oracle、MySqlq行SQL调优、品架构,因ؓ(f)在数据库理论原理上,各大数据库基本出入不大,Ҏ(gu)据库的深入理解,也不?x)媄响你架构设计思想变坏Q相反给你带来的是更深层ơ的思考?
关于执行计划的说?/p>
在SQL Server查询分析器的Query菜单中选择Show Execution PlanQ运行SQL查询语句Q在l果H口中有Grid、Execution Plan、Messages三个Tab。看囑Ş形式的执行计划,序是从叛_左,q也是执行的序。执行计划中的每一个图标表CZ个操作,每一个操作都?有一个或多个输入Q也?x)有一个或多个输出。输入和输出Q有可能是一个物理数据表、烦引数据结构,或者是执行q程中的一些中间结果集/数据l构。鼠标移动到 图标上,?x)显C个操作的具体信息Q例如逻辑和物理操作名U、记录的数量和大、I/O成本、CPU成本、操作的具体表达式(参数ArgumentQ。鼠 标移动到q接头上,?x)显C箭头v始端的操作输出结果集的记录数、记录的大小Q一般情况下可以这个输出结果集理解为箭头结束端的输入?
?外关于执行计划的一些补充说明:(x)1. 执行计划中显C的信息Q都是一?#8220;评估”的结果,不是100%准确的信息,例如记录数量是取自统计信息,I/O成本、CPU成本来自执行计划生成q程中基 于统计信息等得出的评估结果?. 执行计划不一定准,一斚w受SQL Serverl护的统计信息准性的影响Q另一斚wSQL语句~译时刻与执行时ȝ环境Q内存用状c(din)CPU状况{)可能?x)不一栗?
关于l计信息、I/O成本和CPU成本的评估、SQL语句的编译和执行q程Q这里不再深入。另外尽执行计划不一定准,但它仍是SQL语句分析最重要的依据,因ؓ(f)你可以理解ؓ(f)Q绝大部分情况下QSQL Server是以q种方式来执行的?/p>
JOINҎ(gu)说明
数据库中Q象tableA inner join tableB、tableA left out join tableBq样的SQL语句是如何执行join操作的?是说SQL Server使用什么算法实C个表数据的join操作Q?/p>
SQL Server 2000有三U方式:(x)nested loop、merge、hash。Oracle也是使用q三U方式,不过Oracle选择使用nested loop的条件跟SQL Server有点差别Q内存管理机制跟SQL Server不一P因此查看执行计划QOracle中nested loopq用非常多,而merge和hash方式相对较少QSQL Server中,merge跟hash方式则是非常普遍?/p>
以SQL Server 2000Z对这三种方式q行说明Q穿插在里面讲解执行计划的一些初U用?/p>
1. nested loop join
1.1 CZSQL
select ... from tableA inner join tableB on tableA.col1=tableB.col1 where tableA.col2=? and tableB.col2=?tableA中没有徏立Q何烦引,tableB中在col1上有建立一个主键(聚集索引Q?
1.2 法伪代码描q?
foreach rowA in tableA where tableA.col2=?{search rowsB from tableB where tableB.col1=rowA.col1 and tableB.col2=? ;if(rowsB.CountQ?0)discard rowA ;elseoutput rowA and rowsB ;}
join操作有两个输入,上面例子中tableA是outer inputQ用于外层@环;tableB是inner inputQ用于@环内部。下面针Ҏ(gu)行计划描qC下SQL Server完成q个操作的具体步骤?%. ^ g.L
2vt [ AhVA
1.3 查看执行计划Ҏ(gu)
Ud文章最前面?
1.4 执行步骤
?面是CZSQL的执行计划图?nested loop操作的右边,位于上面的是outer inputQ位于下面的是inner input。你不能够根据join中哪个表出现在前面来定outer input和inner input关系Q而必M执行计划中来定Q因为SQL Server?x)自动选择哪个作ؓ(f)inner input?/p>
1、用烦引来更快地遍历表?
~省情况下徏立的索引是非集索引Q但有时它ƈ不是最佳的。在非群集烦引下Q数据在物理上随机存攑֜数据上。合理的索引设计要徏立在对各U查询的分析和预上。一般来_(d)(x)
a.有大量重复倹{且l常有范围查询( > ,<Q?gt; =,<=Q和order by、group by发生的列Q可考虑建立集索引Q?
b.l常同时存取多列Q且每列都含有重复值可考虑建立l合索引Q?
c.l合索引要尽量关键查询形成索引覆盖Q其前导列一定是使用最频繁的列。烦引虽有助于提高性能但不是烦引越多越好,恰好相反q多的烦引会(x)Dpȝ低效。用户在表中每加q一个烦引,l护索引集合p做相应的更新工作?
2、在量查询时尽量少用格式{换?
3、ORDER BY和GROPU BY使用ORDER BY和GROUP BY短语QQ何一U烦引都有助于SELECT的性能提高?
4、Q何对列的操作都将D表扫描,它包括数据库函数、计表辑ּ{等Q查询时要尽可能操作移至等号右辏V?
5、IN、OR子句怼(x)使用工作表,使烦引失效。如果不产生大量重复|可以考虑把子句拆开。拆开的子句中应该包含索引?
6、只要能满你的需求,应尽可能使用更小的数据类型:(x)例如使用MEDIUMINT代替INT
7、尽量把所有的列设|ؓ(f)NOT NULLQ如果你要保存NULLQ手动去讄它,而不是把它设为默认倹{?
8、尽量少用VARCHAR、TEXT、BLOBcd
9、如果你的数据只有你所知的量的几个。最好用ENUMcd
10、正如graymice所讲的那样Q徏立烦引?
以下是我做的一个实验,可以发现索引能极大地提高查询的效率:(x)
我有一个会(x)员信息表usersQ里Ҏ(gu)37365条用戯录:(x)
在不加烦引的时候进行查询:(x)
sql语句A:
select * from users where username like '%?';
在Mysql-Front中的8ơ查询时长ؓ(f)Q?.40,0.54,0.54,0.54,0.53,0.55,0.54 共找?60条记?
sql语句B:
select * from users where username like '?';
在Mysql-Front中的8ơ查询时长ؓ(f)Q?.53,0.53,0.53,0.54,0.53,0.53,0.54,0.54 共找?36条记?
sql语句C:
select * from users where username like '%?;
在Mysql-Front中的8ơ查询时长ؓ(f)Q?.51,0.51,0.52,0.52,0.51,0.51,0.52,0.51 共找?条记?
为username列添加烦?
create index usernameindex on users(username(6));
再次查询Q?
sql语句A:
select * from users where username like '%?';
在Mysql-Front中的8ơ查询时长ؓ(f)Q?.35,0.34,0.34,0.35,0.34,0.34,0.35,0.34 共找?60条记?
sql语句B:
select * from users where username like '?';
在Mysql-Front中的8ơ查询时长ؓ(f)Q?.06,0.07,0.07,0.07,0.07,0.07,0.06,0.06 共找?36条记?
sql语句C:
select * from users where username like '%?;
在Mysql-Front中的8ơ查询时长ؓ(f)Q?.32,0.31,0.31,0.32,0.31,0.32,0.31,0.31 共找?条记?
在实验过E中Q我没有另开ME序Q以上的数据说明在单表查询中Q徏立烦引的可以极大地提高查询速度?
另外要说的是如果建立了烦引,对于like '?'cd的查询,速度提升是最明显的。因此,我们在写sql语句的时候也量采用q种方式查询?
对于多表查询我们的优化原则是Q?
量烦引徏立在Qleft join on/right join on ... Q条Ӟ的条件语句中所涉及(qing)的字D上?
多表查询比单表查询更能体现烦引的优势?
11、烦引的建立原则Q?
如果一列的中数据的前缀重复值很,我们最好就只烦引这个前~。Mysql支持q种索引。我在上面用到的索引Ҏ(gu)是对username最左边?个字W进行烦引。烦引越短,占用?盘I间少Q在索过E中q旉也越。这Ҏ(gu)可以Ҏ(gu)多左255个字W进行烦引?
在很多场合,我们可以l徏立多列数据徏立烦引?
索引应该建立在查询条件中q行比较的字D上Q而不是徏立在我们要找出来q且昄的字D上
12、一往情深问到的问?IN、OR子句怼(x)使用工作表,使烦引失效。如果不产生大量重复|可以考虑把子句拆开。拆开的子句中应该包含索引?
q句话怎么理解冻I请D个例?
例子如下:
如果在fields1和fields2上同时徏立了索引Qfields1Z索引
以下sql?x)用到烦?
select * from tablename1 where fields1='value1' and fields2='value2'
以下sql不会(x)用到索引
select * from tablename1 where fields1='value1' or fields2='value2'
13.索引带来查询上的速度的大大提?但烦引也占用了额外的盘I间(当然现在一般硬盘空间不成问?,而且往表中插入新记录时索引也要随着更新q也需要一定时?
有些表如果经常insert,而较?yu)select,׃用加索引?不然每次写入数据都要重新改写索引,p旉; q个视实际情况而定,通常情况下烦引是必需?
14.我在Ҏ(gu)询效率有怀疑的时?一般是直接用Mysql的Explain来跟t查询情?
你用Mysql-Front是通过旉来比?我觉得如果从查询时扫描字D늚ơ数来比较更_一?
1、选取最适用的字D属?/p>
MySQL可以很好的支持大数据量的存取Q但是一般说来,数据库中的表小Q在它上面执行的查询也就?x)越快。因此,在创的时候,Z获得更好的性能Q我们可以将表中字段的宽度设得尽可能。例如,在定义邮政编码这个字D|Q如果将其设|ؓ(f)CHAR(255),昄l数据库增加了不必要的空_(d)甚至使用VARCHARq种cd也是多余的,因ؓ(f)CHAR(6)可以很好的完成d了。同L(fng)Q如果可以的话,我们应该使用MEDIUMINT而不是BIGIN来定义整型字Dc(din)?/p>
另外一个提高效率的Ҏ(gu)是在可能的情况下Q应该尽量把字段讄为NOT NULLQ这样在来执行查询的时候,数据库不用去比较NULL倹{?/p>
对于某些文本字段Q例?#8220;省䆾”或?#8220;性别”Q我们可以将它们定义为ENUMcd。因为在MySQL中,ENUMcd被当作数值型数据来处理,而数值型数据被处理v来的速度要比文本cd快得多。这P我们又可以提高数据库的性能?/p>
2、用连接(JOINQ来代替子查?Sub-Queries)
MySQL?.1开始支持SQL的子查询。这个技术可以用SELECT语句来创Z个单列的查询l果Q然后把q个l果作ؓ(f)qo(h)条g用在另一个查询中。例如,我们要将客户基本信息表中没有M订单的客户删除掉Q就可以利用子查询先从销售信息表中将所有发单的客户ID取出来,然后结果传递给L询,如下所C:(x)
DELETE FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )
使用子查询可以一ơ性的完成很多逻辑上需要多个步骤才能完成的SQL操作Q同时也可以避免事务或者表锁死Qƈ且写h也很Ҏ(gu)。但是,有些情况下,子查询可以被更有效率的连接(JOINQ?. 替代。例如,假设我们要将所有没有订单记录的用户取出来,可以用下面这个查询完成:(x)
SELECT * FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )
如果使用q接QJOINQ?. 来完成这个查询工作,速度会(x)快很多。尤其是当salesinfo表中对CustomerID建有索引的话Q性能会(x)更好Q查询如下:(x)
SELECT * FROM customerinfo LEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo. CustomerID WHERE salesinfo.CustomerID IS NULL
q接QJOINQ?. 之所以更有效率一些,是因?MySQL不需要在内存中创Z(f)时表来完成这个逻辑上的需要两个步骤的查询工作?/p>
3、用联?UNION)来代替手动创建的临时?/p>
MySQL ?4.0 的版本开始支?UNION 查询Q它可以把需要用(f)时表的两条或更多?SELECT 查询合ƈ的一个查询中。在客户端的查询?x)话l束的时候,临时表会(x)被自动删除,从而保证数据库整齐、高效。?UNION 来创建查询的时候,我们只需要用 UNION作ؓ(f)关键字把多个 SELECT 语句q接h可以了Q要注意的是所?SELECT 语句中的字段数目要想同。下面的例子演CZ一个?UNION的查询?/p>
SELECT Name, Phone FROM client UNION SELECT Name, BirthDate FROM author
UNION
SELECT Name, Supplier FROM product
4、事?/p>
管我们可以使用子查询(Sub-QueriesQ、连接(JOINQ和联合QUNIONQ来创徏各种各样的查询,但不是所有的数据库操作都可以只用一条或数几条SQL语句可以完成的。更多的时候是需要用Cpd的语句来完成某种工作。但是在q种情况下,当这个语句块中的某一条语句运行出错的时候,整个语句块的操作׃(x)变得不确定v来。设想一下,要把某个数据同时插入两个相关联的表中Q可能会(x)出现q样的情况:(x)W一个表中成功更新后Q数据库H然出现意外状况Q造成W二个表中的操作没有完成Q这P׃(x)造成数据的不完整Q甚至会(x)破坏数据库中的数据。要避免q种情况Q就应该使用事务Q它的作用是Q要么语句块中每条语句都操作成功Q要么都p|。换句话_(d)是可以保持数据库中数据的一致性和完整性。事物以BEGIN 关键字开始,COMMIT关键字结束。在q之间的一条SQL操作p|Q那么,ROLLBACK命o(h)可以把数据库恢复到BEGIN开始之前的状态?/p>
BEGIN;
INSERT INTO salesinfo SET CustomerID=14;
UPDATE inventory SET Quantity=11
WHERE item='book';
COMMIT;
事务的另一个重要作用是当多个用户同时用相同的数据源时Q它可以利用锁定数据库的Ҏ(gu)来ؓ(f)用户提供一U安全的讉K方式Q这样可以保证用L(fng)操作不被其它的用hq扰?/p>
5、锁定表
管事务是维护数据库完整性的一个非常好的方法,但却因ؓ(f)它的独占性,有时?x)媄响数据库的性能Q尤其是在很大的应用pȝ中。由于在事务执行的过E中Q数据库会(x)被锁定,因此其它的用戯求只能暂时等待直到该事务l束。如果一个数据库pȝ只有数几个用户
来用,事务造成的媄响不?x)成Z个太大的问题Q但假设有成千上万的用户同时讉K一个数据库pȝQ例如访问一个电(sh)子商务网站,׃(x)产生比较严重的响应gq?/p>
其实Q有些情况下我们可以通过锁定表的Ҏ(gu)来获得更好的性能。下面的例子q锁定表的Ҏ(gu)来完成前面一个例子中事务的功能?/p>
LOCK TABLE inventory WRITE
SELECT Quantity FROM inventory
WHEREItem='book';
...
UPDATE inventory SET Quantity=11
WHEREItem='book';
UNLOCK TABLES
q里Q我们用一?SELECT 语句取出初始数据Q通过一些计,?UPDATE 语句新值更新到表中。包含有 WRITE 关键字的 LOCK TABLE 语句可以保证?UNLOCK TABLES 命o(h)被执行之前,不会(x)有其它的讉K来对 inventory q行插入、更新或者删除的操作?/p>
6、用外?/p>
锁定表的Ҏ(gu)可以l护数据的完整性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。例如,外键可以保证每一条销售记录都指向某一个存在的客户。在q里Q外键可以把customerinfo 表中的CustomerID映射到salesinfo表中CustomerIDQQ何一条没有合法CustomerID的记录都不会(x)被更新或插入到salesinfo中?/p>
CREATE TABLE customerinfo
(
CustomerID INT NOT NULL ,
PRIMARY KEY ( CustomerID )
) TYPE = INNODB;
CREATE TABLE salesinfo
(
SalesID INT NOT NULL,
CustomerID INT NOT NULL,
PRIMARY KEY(CustomerID, SalesID),
FOREIGN KEY (CustomerID) REFERENCES customerinfo
(CustomerID) ON DELETECASCADE
) TYPE = INNODB;
注意例子中的参数“ON DELETE CASCADE”。该参数保证?customerinfo 表中的一条客戯录被删除的时候,salesinfo 表中所有与该客L(fng)关的记录也会(x)被自动删除。如果要?MySQL 中用外键,一定要C在创的时候将表的cd定义Z务安全表 InnoDBcd。该cd不是 MySQL 表的默认cd。定义的Ҏ(gu)是在 CREATE TABLE 语句中加?TYPE=INNODB。如例中所C?/p>
7、用烦?/p>
索引是提高数据库性能的常用方法,它可以o(h)数据库服务器以比没有索引快得多的速度索特定的行,其是在查询语句当中包含有MAX(), MIN()和ORDERBYq些命o(h)的时候,性能提高更ؓ(f)明显。那该对哪些字段建立索引呢?一般说来,索引应徏立在那些用于JOIN, WHERE判断和ORDER BY排序的字D上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUMcd的字D|_(d)出现大量重复值是很有可能的情况,例如customerinfo中的“province”.. 字段Q在q样的字D上建立索引不?x)有什么帮助;相反Q还有可能降低数据库的性能。我们在创徏表的时候可以同时创建合适的索引Q也可以使用ALTER TABLE或CREATE INDEX在以后创建烦引。此外,MySQL
从版?.23.23开始支持全文烦引和搜烦。全文烦引在MySQL 中是一个FULLTEXTcd索引Q但仅能用于MyISAM cd的表。对于一个大的数据库Q将数据装蝲C个没有FULLTEXT索引的表中,然后再用ALTER TABLE或CREATE INDEX创徏索引Q将是非常快的。但如果数据装载到一个已l有FULLTEXT索引的表中,执行q程会(x)非常慢?/p>
8、优化的查询语句
l大多数情况下,使用索引可以提高查询的速度Q但如果SQL语句使用不恰当的话,索引无法发挥它应有的作用。下面是应该注意的几个方面。首先,最好是在相同类型的字段间进行比较的操作。在MySQL 3.23版之前,q甚x一个必ȝ条g。例如不能将一个徏有烦引的INT字段和BIGINT字段q行比较Q但是作为特D的情况Q在CHARcd的字D和VARCHARcd字段的字D大相同的时候,可以它们进行比较。其ơ,在徏有烦引的字段上尽量不要用函数进行操作?/p>
例如Q在一个DATEcd的字D上使用YEAE()函数Ӟ会(x)使烦引不能发挥应有的作用。所以,下面的两个查询虽然返回的l果一P但后者要比前者快得多?/p>
SELECT * FROM order WHERE YEAR(OrderDate)<2001;
SELECT * FROM order WHERE OrderDate<"2001-01-01";
同样的情形也?x)发生在?gu)值型字段q行计算的时候:(x)
SELECT * FROM inventory WHERE Amount/7<24;
SELECT * FROM inventory WHERE Amount<24*7;
上面的两个查询也是返回相同的l果Q但后面的查询将比前面的一个快很多。第三,在搜索字W型字段Ӟ我们有时?x)?LIKE 关键字和通配W,q种做法虽然单,但却也是以牺牲系l性能ZL(fng)。例如下面的查询会(x)比较表中的每一条记录?/p>
SELECT * FROM books
WHERE name like "MySQL%"
但是如果换用下面的查询,q回的结果一P但速度p快上很多Q?/p>
SELECT * FROM books
WHERE name>="MySQL"and name<"mysqm"
最后,应该注意避免在查询中让MySQLq行自动cd转换Q因{换过E也?x)索引变得不v作用?/p>
标签Q?/td> | ||||
CREATE TABLE Products ( ProductID int, ProductName nvarchar (40), Unit char(2), UnitPrice money ) |
表中的数据如?Q?br />
?
?中可以看出,产品Chang和Tofu的记录在产品信息表中存在重复。现在要删除q些重复的记录,只保留其中的一条。步骤如下:(x)
W一板斧——徏立一张具有相同结构的临时?br />
CREATE TABLE Products_temp ( ProductID int, ProductName nvarchar (40), Unit char(2), UnitPrice money ) |
insert into Products_temp Select * from Products |
delete Products insert into Products select * from Products_temp drop table Products_temp |
========W一?========
在一张表中某个字D下面有重复记录Q有很多Ҏ(gu)Q但是有一个方法,是比较高效的Q如下语句:(x)
select data_guid from adam_entity_datas a where a.rowid > (select min(b.rowid) from adam_entity_datas b where b.data_guid = a.data_guid)
如果表中有大量数据,但是重复数据比较?yu),那么可以用下面的语句提高效?/p>
select data_guid from adam_entity_datas where data_guid in (select data_guid from adam_entity_datas group by data_guid having count(*) > 1)
此方法查询出所有重复记录了Q也是_(d)只要是重复的选出来,下面的语句也许更高效
select data_guid from adam_entity_datas where rowid in (select rid from (select rowid rid,row_number()over(partition by data_guid order by rowid) m from adam_entity_datas) where m <> 1)
目前只知道这三种比较有效的方法?/p>
W一U方法比较好理解Q但是最慢,W二U方法最快,但是选出来的记录是所有重复的记录Q而不是一个重复记录的列表Q第三种Ҏ(gu)Q我认ؓ(f)最好?br />
========W二?========
select usercode,count(*) from ptype group by usercode having count(*) >1
========W三?========
扑և重复记录的ID:
select ID from
( select ID ,count(*) as Cnt
from 要消除重复的?
group by ID
) T1
where T1.cnt>1
删除数据库中重复数据的几个方?nbsp;
数据库的使用q程中由于程序方面的问题有时候会(x)到重复数据Q重复数据导致了数据库部分设|不能正设|?#8230;…
Ҏ(gu)一
declare @max integer,@id integer
declare cur_rows cursor local for select dD?count(*) from
表名 group by dD? having count(*) > 1
open cur_rows
fetch cur_rows into @id,@max
while @@fetch_status=0
begin
select @max = @max -1
set rowcount @max
delete from 表名 where dD? = @id
fetch cur_rows into @id,@max
end
close cur_rows
set rowcount 0
Ҏ(gu)?nbsp;
有两个意义上的重复记录,一是完全重复的记录Q也x有字D均重复的记录,二是部分关键字段重复的记录,比如Name字段重复Q而其他字D不一定重复或都重复可以忽略?nbsp;
1、对于第一U重复,比较Ҏ(gu)解决Q?nbsp;
select distinct * from tableName
可以得到无重复记录的结果集?nbsp;
如果该表需要删除重复的记录Q可以按以下Ҏ(gu)删除
select distinct * into #Tmp from tableName
drop table tableName
select * into tableName from #Tmp
drop table #Tmp
2、这c重复问题通常要求保留重复记录中的W一条记录,*作方法如?nbsp;
假设有重复的字段为Name,AddressQ要求得到这两个字段唯一的结果集
select identity(int,1,1) as autoID, * into #Tmp from
tableName
select min(autoID) as autoID into #Tmp2 from #Tmp group by
Name,autoID
select * from #Tmp where autoID in(select autoID from
#tmp2)
最后一个select卛_CNameQAddress不重复的l果?nbsp;
更改数据库中表的所属用L(fng)两个Ҏ(gu)
大家可能?x)经常碰C个数据库备䆾q原到另外一台机器结果导致所有的表都不能打开了,原因是徏表的时候采用了当时的数据库用户……
========W四?========
如何查询数据库中的重复记录?
比如说有个表中的数据是这P(x)
---------
a
a
a
b
b
c
---------
查询出的l果是:(x)
记录 数量
a 3
b 2
c 1
怎样写这个SQL语句Q?br />
-----------------------
select distinct(name),count(*) from tabname group by name;
-------------------------------------
惛_来了Q这样就可以排序了?br />
select a1,count(a1) as total from tablename group by a1 order by total desc
--------------------------------------
select distinct(a1),count(a1) as total from tablename group by a1 order by total desc
加个distinct更有效率
--------------------------------------------------------------
select p.*, m.* from table1 p left join table2 m on p.item1=m.item2 where p.item3='#$#@%$@' order by p.item3 asc limit 10
qD么写
========W五?========
如何查找数据库中的重复记? 能在Access中用的方?
----------------------------------------------------------------------
select *
from ?nbsp;A inner join (select 字段1,字段2 from ?nbsp;group by 字段1,字段2 having Count(*)>1) B on A.字段1=B.字段1 and A.字段2=B.字段2
--------------------------------------------------------
问题Q?br />
Ҏ(gu)其中几个字段判断重复Q只保留一条记录,但是要显C全部字D,怎么查询Q谢谢!Q?
比如
字段1 字段2 字段3 字段4
a b c 1
a b c 1
a b d 2
a b d 3
b b d 2
惛_到的l果?
a b c 1
a b d 2Q或?Q?
b b d 2
说明Q根据字D?Q?,3l合不重复,字段4 不考虑Q得C3个记?
但是也要昄字段4?nbsp;
Ҏ(gu)一Q?nbsp;
可以用(f)时表的方法来解决Q?
CurrentProject.Connection.Execute "drop table temptable"
CurrentProject.Connection.Execute "select * into temptable from ? where 1=2"
CurrentProject.Connection.Execute "insert into temptable(字段1,字段2,字段3) SELECT DISTINCT ?.字段1, ?.字段2, ?.字段3 FROM ?;"
CurrentProject.Connection.Execute "UPDATE temptable INNER JOIN ? ON (?.字段1 = temptable.字段1) AND (?.字段2 = temptable.字段2) AND (?.字段3 = temptable.字段3) SET temptable.字段4 = [?].[字段4];"
Ҏ(gu)二:(x)
可以直接使用一个SELECT查询{选出需要的数据Q?
可以假定W四字段都选值最的
SELECT [1],[2], [3], Min([4]) AS Min4
FROM ?
GROUP BY ?.[1], ?.[2], ?.[3];
问题Q?br />
?
id NAME r1 r2
1 1 w ee
1 1 1 1232
1 2 123 123
1 2 12 434
1 2 123 123
2 1 123 123
ID 为数|NAME 为字W。每条记录没有唯一标识?
要求取得 ID ?nbsp;NAME 合ƈ后不重复的记录,如有重复保留其中一条即可,但要昄所有记录?nbsp;
回答Q?nbsp;
SELECT a.*, (select top 1 r1 from ? as a1 where a1.id=a.id and a1.name=a.name) AS r1, (select top 1 r2 from ? as a2 where a2.id=a.id and a2.name=a.name) AS r2
FROM [SELECT DISTINCT ?.id, ?.NAME
FROM ?]. AS a;
SELECT a.*, dlookup("r1","?","id=" & a.id & " and name='"& a.name & "'") AS r1, dlookup("r2","?","id=" & a.id & " and name='"& a.name & "'") AS r2
FROM [SELECT DISTINCT ?.id, ?.NAME
FROM ?]. AS a;
注意Q上qC码中׃没有唯一标识列,因此昄?nbsp;R1 R2 的先后次序无从确定,一般是按输入的先后序Q但是微软没有官方资料说明到底按哪个序Q请|友注意?
h意,上述?为没有唯一标识字段Q如果现在再建立一个自动编号字D?#8220;主键”则可以用以下代码
SELECT a.ID, a.name, b.r1, b.r2, b.主键
FROM (SELECT ?.id, ?.NAME, Min(?.主键) AS 主键
FROM ?
GROUP BY ?.id, ?.NAME) AS a inner JOIN ? AS b ON a.主键=b.主键;
========W六?========
1.查询数据库中重复的记?
select realname,count(*) from users group by realname having count(*)>1
========W七?========
SELECT T0.ItemCode, T0.ItemName FROM OITM T0 WHERE exists (select 1 from OITM A where A.CODEBARS = TO.CODEBARS And A.ItemCode < > TO.ItemCode)
========W八?========
怿很多人在查询数据库时都会(x)到索某表中不重复记录的时?提到索不重复记录,马上惛_的肯定是Distinct或者Group By分组,
弟在初ơ用的时候碰C一些麻?q里拿出来与大家分n,希望Ҏ(gu)多的朋友有所帮助!
先看看数据库表结构:(x)
表名: TEST 字段: Id,A,B,C,D
其中B字段包含重复?
Id |
A |
B |
C |
D |
1 |
11 |
a |
34 |
bvb |
2 |
22 |
a |
35 |
fgfg |
3 |
33 |
d |
ht |
sdf |
4 |
44 |
a |
345 |
de |
5 |
55 |
c |
sfsf |
sscv |
6 |
66 |
b |
rt |
fg |
但是:
q里有一个非帔R帔R要注意的地方Q?br />
SELECT DISTINCT [字段名]后面不能再跟其他的字D,否则索出来的记录仍然?x)含有重复项Q?br />
错误写法Q?br />
SELECT DISTINCT [字段名] Q[其他字段名] FROM [表名] WHERE [索条件字句]
实际?我们上面SQL语句l果集里只有B字段;(一般情况下,q种l果应该是很难满需求的)
如果我们的记录集里还需要有其他字段?那怎么办呢?
实际?我们完全可以用另一U办法来解决问题;只是需要用到子查询而已!
使用GROUP BY 分组
有一炚w要注?
使用带有GROUP BY字句的查询语句时,在SELECT列表指定的列要么是GROUP BY 指定的列,要么包含聚合l函?/font>
所以用q样一句SQL可以去掉重复项?
q样得到我们想要的l果集了:
Id |
A |
B |
C |
D |
1 |
11 |
a |
34 |
bvb |
3 |
33 |
d |
ht |
sdf |
5 |
55 |
c |
sfsf |
sscv |
6 |
66 |
b |
rt |
fg |
========W二?========
========W二?========
========W二?========
mysql存储q程的创建,删除Q调用及(qing)其他常用命o(h)
一.创徏存储q程
2.参数传?/p>
?调用存储q程
?删除存储q程
?区块Q条Ӟ循环
3.循环语句
(1).while循环
?其他常用命o(h)
mysql存储q程中要用到的运符
术q算W?/strong>
+ ?nbsp; SET var1=2+2; 4
- ?nbsp; SET var2=3-2; 1
* ?nbsp; SET var3=3*2; 6
/ ?nbsp; SET var4=10/3; 3.3333
DIV 整除 SET var5=10 DIV 3; 3
% 取模 SET var6=10%3 ; 1
比较q算W?/strong>
逻辑q算W?/strong>
?/strong>(AND)
AND |
TRUE |
FALSE |
NULL |
---|---|---|---|
TRUE |
TRUE |
FALSE |
NULL |
FALSE |
FALSE |
FALSE |
NULL |
NULL |
NULL |
NULL |
NULL |
?OR)
OR |
TRUE |
FALSE |
NULL |
---|---|---|---|
TRUE |
TRUE |
TRUE |
TRUE |
FALSE |
TRUE |
FALSE |
NULL |
NULL |
TRUE |
NULL |
NULL |
异或(XOR)
XOR |
TRUE |
FALSE |
NULL |
---|---|---|---|
TRUE |
FALSE |
TRUE |
NULL |
FALSE |
TRUE |
FALSE |
NULL |
NULL |
NULL |
NULL |
NULL |
位运符
| 位或
& 位与
<< 左移?br />
>> 右移?br />
~ 位非(单目q算Q按位取?
mysq存储q程中常用的函数Q字W串cd操作Q数学类Q日期时间类?/p>
一.字符串类
TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字W?br /> UCASE (string2 ) //转换成大?br /> RIGHT(string2,length) //取string2最后length个字W?br /> SPACE(count) //生成count个空?nbsp;
?数学c?/span>
mysql> select round(1.56);
+———?+
| round(1.56) |
+———?+
| 2 |
+———?+
1 row in set (0.00 sec)
(2)可以讑֮数位数Q返回Q点型数据
mysql> select round(1.567,2);
+————?+
| round(1.567,2) |
+————?+
| 1.57 |
+————?+
1 row in set (0.00 sec)
SIGN (number2 ) //q回W号,正负?
SQRT(number2) //开qx
?日期旉c?/span>
SHOW VARIABLES LIKE 'version';
or
SELECT VERSION();
SHOW TABLES FROM database; 查看数据库里面所有的表,
执行 desc table_name; 或?nbsp;
show columns from talbe_name; 查看表中的所有的?br />
查看数据?br />
show databases;
查看?br />
show tables;
show create table table_name;
l计一个表的字D|
1.如何l标识列插入?/p>
表中W一个字Did为标识列
insert into table values (null,'aa',1)
2.如果表存在删除表
drop table if exists tablename
3.date too long for column 解决Ҏ(gu)
我用的是5.1Q昨天把mysql,php,phpmyadmin的字W集都改成utf8后,用load data infile 命o(h)插入数据时L出现q样的错误提C:(x)data too long for column 'cname' at row 1;|上搜一下,大都说set character_set=utf8之类的,但还是不行,最后找C一个:(x)
修改my.ini文gQ将
sql-mode=STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
注释掉,okQ?br />
Update:mysql5在phpmyadmin无法q接时执行的语句Q?br />
SET PASSWORD FOR ‘root’@'localhost’ = OLD_PASSWORD(’[newpassword]‘);
刚才在导入数据的时候,navicat报错:
Data too long for column ‘ip’ at row 1
提示数据对于ip字段太长
如果数据cd不正?也会(x)出错,而不?.*那样自动转换:
sendQuery:Incorrect datetime value: ‘未知’ for column ‘date’ at row 1
如果是数据x (int 11)cd的可能有些奇?
insert into a (x) values (’a')
出现:
Out of range value adjusted for column ‘x’ at row 1
insert into a (x) values (’11a’)
出现:
Data truncated for column ‘x’ at row 1
解决办法:
在my.ini里找?br />
sql-mode=”STRICT_TRANS_TABLES,NO_AUTO_Create_USER,NO_ENGINE_SUBSTITUTION”
把其中的
STRICT_TRANS_TABLES,
L,然后重启mysqlok?/p>
4.分页语句
select * from table where ... order by ... limit n,n
5.mysql 5.0 中文q问题
解决mysql5.0的中文ؕ码问题,只要按下面三步做可以了Q?br />
1.W一步,修改MySql的配|文件my.iniQ?br />
在安装好Mysql后,在Mysql所在的目录下有一个my.ini文gQ修改这个my.ini文gQ修Ҏ(gu)式如下:(x)
1.1 在[client] 的后面加一?default-character-set=gb2312
2.2 把[mysql] 的后?default-character-set=latin1 Ҏ(gu) default-character-set=gb2312
2.3 把[mysqd] 的后?default-character-set=latin1 Ҏ(gu) default-character-set=gb2312
2.4 在改了上面三处后Q后面还一个default-character-set=latin1,q个default-character-set的作用是指定在创建新的表或数据库
Ӟ所使用的默认字W编?Z方便创徏新的表或数据库,把定?default-character-set也改成gb2312?/p>
2.W二步,讄与数据库q接的字W串Q?br />
在连接字W串(URL)后加?useUnicode=true&characterEncoding=gb2312q一句,具体如下Q?br />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=gb2312</value>
</property>
<property name="username">
<value>用户?lt;/value>
</property>
<property name="password">
<value>密码</value>
</property>
</bean>
3.W三步,在java代码Q把SQL语句转换成gb2312的编码,然后再执行该SQL.
3.1 把字W串转换成gb2312的编码的方式如下Q?br />
public static String GB2312Converter(String str) {
if (str == null) {
str = "";
} else {
try {
str = new String(str.getBytes("gb2312"), "gb2312");
} catch (Exception ex) {
ex.printStackTrace();
}
}
return str;
}
3.2 获取gb2312~码的sql语句Q?br />
String sql = "select name from user ";
sql = GB2312Converter(sql); // 获取gb2312~码的sql语句,然后可以执行该sql语句了?/p>