mysqlmysql 分页 优化优化问题,急!

您所在的位置: &
MySQL查询分页的优化
MySQL查询分页的优化
MySQL数据库的效率优化是一个重要的问题,而对于查询中的分页优化也不可小视,下文对查询优化问题进行了深入探讨,供您参考。
MySQL查询分页应该如何优化呢?下面对MySQL查询分页的优化提出了一个设想,希望对您学习查询分页方面能有所帮助。
在有索引的情况下,limit m,n速度足够,可是在复杂条件搜索时,
where somthing order by somefield somefield
mysql会搜遍数据库,找出&所有&符合条件的记录,然后取出m,n条记录。
如果你的数据量有几十万条,用户又搜索一些很通俗的词,
然后要依次读最后几页重温旧梦。。。mysql该很悲壮的不停操作硬盘。所以,可以试着让mysql也存储分页,当然要程序配合。
(这里只是提出一个设想,欢迎大家一起讨论)
ASP的分页:在ASP系统中有Recordset对象来实现分页,但是大量数据放在内存中,而且不知道什么时候才失效(请ASP高手指点).
SQL数据库分页:用存储过程 游标方式分页,具体实现原理不是很清楚,设想如果用一次查询就得到需要的结果,或者是id集,需要后续页时只要按照结果中的IDs读出相关记录。这样只要很小的空间保留本次查询的所有IDs. (SQL中的查询结果不知道怎样清楚过期垃圾?)
这样,可以让mysql模拟存储分页机制:
1. select id from $table where $condition order by $field limit $max_pages*$查询符合条件的IDs.
限定最大符合条件的记录数量,也可以不加。
2. 因为php在执行结束后所有变量都要lost,所以可以考虑:
方案a. 在mysql建立临时表,查询结果用一个时间或随机数作为唯一标志插入。
其中建立page1~pagen个字段,每个字段保存该页中需要的ids, 这样一个id对一条记录.
方案b. 如果打开session,也可以放在session中保存,实际上是放在文件中保存。
建立一个$IDs数组,$IDs[1]~$IDs[$max_pages]. 考虑到有时候用户会开几个窗口同时查询,要为$ids做一个唯一标志,避免查询结果相互覆盖。二维数组和$$var都是好办法。
3. 在每页页的请求中,直接找到对应的IDs,中间以&,&间隔:
select * from $table where id in ($ids); 速度绝对快
4. 收尾要考虑查询结果的自动清除,可以设置定时或者按比例随机清楚。如果用mysql临时表要加上一个时间标志字段,
session中要加入$IDs[&time&]=time(); 在一定时间以后不操作视为过期数据。
5. 如果要优化,可以考虑用把1和2.a中的语句合并成select ...... into ....
【编辑推荐】
【责任编辑: TEL:(010)】
关于的更多文章
MariaDB是一个向后兼容、替代MySQL的数据库服务器。它包含所有主
数据库产品
数据库综合
数据库新闻
维基百科将切换到另外一款开源数据库MariaDB
Oracle数据库的配置工作十分复杂,不光涉及到存储数据
Infobright是一个与MySQL集成的开源数据仓库(Data Wa
作为甲骨文公司的基石,Oracle数据库一直占据着数据库
本书分为8章,首先介绍ASP.NET的开发技巧和重点技术,尤其针对初学者如何快速入门并掌握ASP.NET编程做了深入浅出的介绍;然后重
51CTO旗下网站mysql limit 大数据量分页优化步骤_一位码农的人生自述(十五)-暂时负责人_关于数据库范式及关系的小结__脚本百事通
稍等,加载中……
^_^请注意,有可能下面的2篇文章才是您想要的内容:
mysql limit 大数据量分页优化步骤
一位码农的人生自述(十五)-暂时负责人
关于数据库范式及关系的小结
mysql limit 大数据量分页优化步骤
mysql limit 大数据量分页优化方法Mysql的优化是非常重要的。其他最常用也最需要优化的就是limit。Mysql的limit给分页带来了极大的方便,但数据量一大的时候,limit的性能就急剧下降。
  同样是取10条数据
  select * from yanxue8_visit limit 10000,10 和
  select * from yanxue8_visit limit 0,10  就不是一个数量级别的。
  网上也很多关于limit的五条优化准则,都是翻译自Mysql手册,虽然正确但不实用。今天发现一篇文章写了些关于limit优化的,很不错。
  文中不是直接使用limit,而是首先获取到offset的id然后直接使用limit size来获取数据。根据他的数据,明显要好于直接使用limit。这里我具体使用数据分两种情况进行测试。(测试环境win2033+p4双核 (3GHZ) +4G内存 Mysql 5.0.19)
  1、offset比较小的时候。
  select * from yanxue8_visit limit 10,10
  多次运行,时间保持在0.5之间
  Select * From yanxue8_visit Where vid >=(
  Select vid From yanxue8_visit Order By vid limit 10,1
  ) limit 10  多次运行,时间保持在0.6之间,主要是0.0006
  结论:偏移offset较小的时候,直接使用limit较优。这个显然是子查询的原因。
  2、offset大的时候。
 select * from yanxue8_visit limit 10000,10
  多次运行,时间保持在0.0187左右
  Select * From yanxue8_visit Where vid >=(
  Select vid From yanxue8_visit Order By vid limit 10000,1
  ) limit10
  多次运行,时间保持在0.0061左右,只有前者的1/3。可以预计offset越大,后者越优。
  以后要注意改正自己的limit语句,优化一下Mysql了
据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是逐渐,vtype是tinyint,vtype是索引。这是一个基本的新闻系统的简单模型。现在往里面填充数据,填充10万篇新闻。
最后collect 为 10万条记录,数据库教程表占用硬盘1.6G。OK ,看下面这条sql语句:
select id,title from collect limit 1000,10; 很快;基本上0.01秒就OK,再看下面的
select id,title from collect limit 90000,10; 从9万条开始分页,结果?8-9秒完成,my god 哪出问题了????其实要优化这条数据,网上找得到答案。看下面一条语句:
select id from collect order by id limit 90000,10; 很快,0.04秒就OK。 为什么?因为用了id主键做索引当然快。网上的改法是:
select id,title from collect where id&=(select id from collect order by id limit 90000,1) limit 10;这就是用了id做索引的结果。可是问题复杂那么一点点,就完了。看下面的语句
select id from collect where vtype=1 order by id limit 90000,10; 很慢,用了8-9秒!
到了这里我相信很多人会和我一样,有崩溃感觉!vtype 做了索引了啊?怎么会慢呢?vtype做了索引是不错,你直接 select id from collect where vtype=1 limit 1000,10; 是很快的,基本上0.05秒,可是提高90倍,从9万开始,那就是0.05*90=4.5秒的速度了。和测试结果8-9秒到了一个数量级。从这里开始有人提出了分表的思路,这个和discuz 论坛是一样的思路。思路如下:
建一个索引表: t (id,title,vtype) 并设置成定长,然后做分页,分页出结果再到 collect 里面去找info 。 是否可行呢?实验下就知道了。
10万条记录到 t(id,title,vtype) 里,数据表大小20M左右。用
select id from t where vtype=1 order by id limit 90000,10; 很快了。基本上0.1-0.2秒可以跑完。为什么会这样呢?我猜想是因为collect 数据太多,所以分页要跑很长的路。limit 完全和数据表的大小有关的。其实这样做还是全表扫描,只是因为数据量小,只有10万才快。OK, 来个疯狂的实验,加到100万条,测试性能。
加了10倍的数据,马上t表就到了200多M,而且是定长。还是刚才的查询语句,时间是0.1-0.2秒完成!分表性能没问题?错!因为我们的limit还是9万,所以快。给个大的,90万开始
select id from t where vtype=1 order by id limit ; 看看结果,时间是1-2秒!why ?? 分表了时间还是这么长,非常之郁闷!有人说定长会提高limit的性能,开始我也以为,因为一条记录的长度是固定的,mysql教程 应该可以算出90万的位置才对啊? 可是我们高估了mysql 的智能,他不是商务数据库,事实证明定长和非定长对limit影响不大? 怪不得有人说 discuz到了100万条记录就会很慢,我相信这是真的,这个和数据库设计有关!
难道MySQL 无法突破100万的限制吗???到了100万的分页就真的到了极限???
答案是: NO !!!! 为什么突破不了100万是因为不会设计mysql造成的。下面介绍非分表法,来个疯狂的测试!一张表搞定100万记录,并且10G 数据库,如何快速分页!
好了,我们的测试又回到 collect表,开始测试结论是: 30万数据,用分表法可行,超过30万他的速度会慢道你无法忍受!当然如果用分表+我这种方法,那是绝对完美的。但是用了我这种方法后,不用分表也可以完美解决!
答案就是:复合索引! 有一次设计mysql索引的时候,无意中发现索引名字可以任取,可以选择几个字段进来,这有什么用呢?开始的select id from collect order by id limit 90000,10; 这么快就是因为走了索引,可是如果加了where 就不走索引了。抱着试试看的想法加了 search(vtype,id) 这样的索引。然后测试select id from collect where vtype=1 limit 90000,10; 非常快!0.04秒完成!
再测试: select id ,title from collect where vtype=1 limit 90000,10; 非常遗憾,8-9秒,没走search索引!
再测试:search(id,vtype),还是select id 这个语句,也非常遗憾,0.5秒。综上:如果对于有where 条件,又想走索引用limit的,必须设计一个索引,将where 放第一位,limit用到的主键放第2位,而且只能select 主键!
完美解决了分页问题了。可以快速返回id就有希望优化limit , 按这样的逻辑,百万级的limit 应该在0.0x秒就可以分完。看来mysql 语句的优化和索引时非常重要的!好了,回到原题,如何将上面的研究成功快速应用于开发呢?如果用复合查询,我的轻量级框架就没的用了。分页字符串还得自己写,那多麻烦?这里再看一个例子,思路就出来了:select * from collect where id in (,7000); 竟然 0秒就可以查完!mygod ,mysql 的索引竟然对于in语句同样有效!看来网上说in无法用索引是错误的!有了这个结论,就可以很简单的应用于轻量级框架了:代码如下:
复制代码 代码如下:
$db=dblink(); $db-&pagesize=20; $sql="select id from collect where vtype=$vtype"; $db-&execute($sql); $strpage=$db-&strpage(); //将分页字符串保存在临时变量,方便输出 while($rs=$db-&fetch_array()){ $strid.=$rs['id'].','; } $strid=substr($strid,0,strlen($strid)-1); //构造出id字符串 $db-&pagesize=0; //很关键,在不注销类的情况下,将分页清空,这样只需要用一次数据库连接,不需要再开; $db-&execute("select id,title,url,sTime,gTime,vtype,tag from collect where id in ($strid)"); &?php教程 while($rs=$db-&fetch_array()): ?& &tr& &td& &?php echo $rs['id'];?&&/td& &td& &?php echo $rs['url'];?&&/td& &td& &?php echo $rs['sTime'];?&&/td& &td& &?php echo $rs['gTime'];?&&/td& &td& &?php echo $rs['vtype'];?&&/td& &td& &a href="?act=show&id=&?php echo $rs['id'];?&" target="_blank"&&?php echo $rs['title'];?&&/a&&/td& &td& &?php echo $rs['tag'];?&&/td& &/tr& &? ?& &/table& &?php echo $ ?& 通过简单的变换,其实思路很简单:1)通过优化索引,找出id,并拼成 "123," 这样的字符串。2)第2次查询找出结果。 小小的索引+一点点的改动就使mysql 可以支持百万甚至千万级的高效分页! 通过这里的例子,我反思了一点:对于大型系统,PHP千万不能用框架,尤其是那种连sql语句都看不到的框架!因为开始对于我的轻量级框架都差点崩溃!只适合小型应用的快速开发,对于ERP,OA,大型网站,数据层包括逻辑层的东西都不能用框架。如果程序员失去了对sql语句的把控,那项目的风险将会成几何级数增加!尤其是用mysql 的时候,mysql 一定需要专业的dba 才可以发挥他的最佳性能。一个索引所造成的性能差别可能是上千倍!
性能优化:基于MySQL5.0中limit的高性能,我对数据分页也重新有了新的认识.
1.Select * From cyclopedia Where ID&=(Select Max(ID) From ( Select ID From cyclopedia Order By ID limit 90001) As tmp) limit 100;
2.Select * From cyclopedia Where ID&=(Select Max(ID) From ( Select ID From cyclopedia Order By ID limit 90000,1) As tmp) limit 100;同样是取90000条后100条记录,第1句快还是第2句快?第1句是先取了前90001条记录,取其中最大一个ID值作为起始标识,然后利用它可以快速定位下100条记录第2句择是仅仅取90000条记录后1条,然后取ID值作起始标识定位下100条记录第1句执行结果.100 rows in set (0.23) sec第2句执行结果.100 rows in set (0.19) sec
很明显第2句胜出.看来limit好像并不完全像我之前想象的那样做全表扫描返回limit offset+length条记录,这样看来limit比起MS-SQL的Top性能还是要提高不少的.
其实第2句完全可以简化成
Select * From cyclopedia Where ID&=(Select ID From cyclopedia limit 90000,1)limit 100;直接利用第90000条记录的ID,不用经过Max运算,这样做理论上效率因该高一些,但在实际使用中几乎看不到效果,因为本身定位ID返回的就是1条记录,Max几乎不用运作就能得到结果,但这样写更清淅明朗,省去了画蛇那一足.
可是,既然MySQL有limit可以直接控制取出记录的位置,为什么不干脆用Select * From cyclopedia limit 90000,1呢?岂不更简洁?这样想就错了,试了就知道,结果是:1 row in set (8.88) sec,怎么样,够吓人的吧,让我想起了昨天在4.1中比这还有过之的"高分".Select * 最好不要随便用,要本着用什么,选什么的原则, Select的字段越多,字段数据量越大,速度就越慢. 上面2种分页方式哪种都比单写这1句强多了,虽然看起来好像查询的次数更多一些,但实际上是以较小的代价换取了高效的性能,是非常值得的.
第1种方案同样可用于MS-SQL,而且可能是最好的.因为靠主键ID来定位起始段总是最快的.
Select Top 100 * From cyclopedia Where ID&=(Select Top 90001 Max(ID) From ( Select ID From cyclopedia Order By ID) As tmp)但不管是实现方式是存贮过程还是直接代码中,瓶颈始终在于MS-SQL的TOP总是要返回前N个记录,这种情况在数据量不大时感受不深,但如果成百上千万,效率肯定会低下的.相比之下MySQL的limit就有优势的多,执行:
Select ID From cyclopedia limit 90000Select ID From cyclopedia limit 90000,1的结果分别是:90000 rows in set (0.36) sec1 row in set (0.06) sec而MS-SQL只能用Select Top 90000 ID From cyclopedia 执行时间是390ms,执行同样的操作时间也不及MySQL的360ms.
更多详细内容请查看:http://www.111cn.net/database/mysql/39135.htm
一位码农的人生自述(十五)-暂时负责人
一位码农的人生自述(十五)------临时负责人临时负责人
这下我寝室人员全部到齐了!说来也是缘分吧,茫茫人海,从四面八方各地赶来,能在同一个班级学习已是不易了,况且还是在同一寝室!这也许就是命运的安排吧。命运把我们四个联系在了一起,想想在这一年的室友生活中,我们有过哭、有过泪,但更多的是互相的帮助与理解。
寝室齐聚的第二天,我们一起逛校园去了!想去看看我们这个美丽的校园到底啥模样!早饭过后的,我们一行漫步于校园中,欣赏这校园的风景。人都说看一个校园的美丽,图书馆是一个不能错过的地方,于是我们寻找图书馆的足迹,可是当我们走遍各大建筑物时,发现什么都没有,教学楼只有一幢,宽敞的足球场还是黄土泥沙,慢慢的我开始对我的大学校产生怀疑,这是我的大学么?难道大学四年都要在这个地方度过?曾经我想象过,也憧憬过我的大学以及我的大学生活,想象着我的大学校园是多么大,多么美丽,即充满古典的韵味,又暗含现代时尚的风采;如果看书看累了,就可以到海边吹吹海风,与大海一起呼吸,一起享受着世间万物的变化的美好;顺便找个人在海边一起建造我们爱的城堡,留下我们爱得痕迹。。。可是现在一切都是相反的。别人都说梦是相反的,或许我那时的这个梦也就只能是一个梦了吧!
我不甘心,不甘心就此失望,于是我找个迎接新生的自愿者询问了下,得知这里只是西校区,是专门为大一新生学习生活的地方,本部不在这...。我心里暗暗的诺了下,心想即使是一个校区,在这里容易一个五六千人也是够呛的。很显然他看出了我的心思,接着就对我说:“你别看这里小,但是这里的学习气氛不错,没有本部那边的浮躁,在这里你们可以静下心来学习,其实你们是身在湖中不知胡啊,多少你们的学长都想回到这里重温这里学习的记忆...”,我仍有点不相信,这是真的么!后来才知道,他说的一点不假,大学四年,西校区留下的美好记忆是最多的,在那一年大学生活过的是最充实的!那一年是真心能静下心学习的一年。
我们听到他的这些话,看来西校区也没啥好逛的,要逛下次一起去本部看看吧,于是几个人找了块草坪,做下了,在那聊天。在我记忆中这次聊天是最深刻的一次,因为这次是我寝室四人一起安安静静的做在一起聊天的唯一一次,在往后的大学岁月里,凯哥一般很少出来,只要没什么的话。而雪风则是忙着谈恋爱,更是没法与我们这群光棍玩了。唯一的就是我跟宁宁一起经常去外面游玩,因为宁宁跟我在这方面还是蛮相似的,都喜欢游历,不过宁宁喜欢安静,远离喧嚣。这一次谈话,我们聊了好多,从高中的往事到往后大学的规划;从各自的兴趣到生活琐事。反正那次,我们放佛有好多的话题。聊得很尽心,最后的一个话题是——班长。话题是我打开的,我问他们,你们有谁想当班长不?凯哥说:“没那个兴趣”,宁宁则:“你觉得我是当班长的人么?”,雪风则是:“玩我倒会,班长嘛干不了”,随后雪风问我想不想干,我说:“班长,难道你们都不想当?听说大学班长蛮能锻炼人的”,其实我主心骨里还是想当班长的,主要是我想追求自我改变,如果、能当上班长的话,我觉得自己各方面应该都会所有提升吧。所当雪风再一次跟我说:“那你是想当班长了“,我斩钉截铁的会了句:”是的“,”那行,如果你想当的话,我们几个都选举你。“雪峰说道。我用期望的眼神环视了下,希望能如所愿。
晚饭之后,我们都回寝室了。班上的同学也来的差不多,隔壁几个寝室都是我班上的,学校把同一个专业班级的同学都安排在一起。晚上我就去其他的几个寝室逛了下,想多认识几个人,以便到时多个选票,想想自己其实还是蛮有野心的。在325寝室我认识了蒋鹏,他是个大胖子,无疑是我班上甚至专业最胖的人,不过为人热情、幽默、容易亲近,在大学期间我被他欺负了无数次。跟他在一起你的时刻保持你有一颗坚挺的抗打击能力的心,语言犀利,让你不知道是夸你呢,还是在损你。之后,又认识了李伟升、欧阳邦勇、贺碧波、李政等。经过一番遍访之后,我来到寝室,大家都在。
辅导员在这个时候突然,来到寝室查访,身边跟着一个大三的学长,之后才知道他是学校的学生会主席。在我到大学的那天,我跟辅导员见过一次,期间主要是由于有一些人向我推销什么东西,我当时不知道怎么办,于是就去找了辅导员,跟他聊了下。其实主要是想通过这件事接近下辅导员吧,混个脸熟。然后辅导员看了下我,说叫我去通知其他寝室的人过来,有事要宣布。于是我就跟隔壁几个寝室说下了,到我寝室来。人齐之后,辅导员跟大伙聊了下天,主要是问下生活情况,之后步入正题,说:“过几天,就要军训了,今天需要选出一名临时负责人,你们有谁自愿做的“,此时大家都默不作声,而我则是心涌澎湃,我的机会来了,但是心情又很紧张,感觉喉咙都有点嘶哑,以前都不敢在大众面前大声说话的我面对这个场景要自己站出去,可想而知当时我的心情是多么的复杂。就在这时,雪风拉了下我的衣服,轻声的跟我说,你不是想当班长么,现在机会来了。我没回他,心想:”再等下,心里准备好点“。大三学长说话了:“这可是个很好的锻炼机会,现在的负责人,往后多半是班长了...“,听到这句话,我顿时震了下,措不及手,背后一股力把我推了出去,我顺势站了出来,用嘶哑的声音说:”我来...”,心情那个紧张啊,一下子就释放了出来,感觉自己说的话振聋发聩。辅导员看到站出来,于是就跟大家说说,那这段时间就由陈垂贵暂时管理班级事宜,大家有什么事,可以告诉他然后转达给我。之后老师要了我的手机号码,说有情况联系。
就这样,我成了软件081班的临时负责人,完美的实施了自我改变的第一步。对于这一步我看的好重。因为从这间事上,我看到了我在改变,我很高兴我勇敢的踏出了这一步。我相信在这一步的基础上,我会越来越有干劲。
关于数据库范式及关系的小结
关于数据库范式及关系的总结
关于数据库范式及关系的总结
PowerDesigner的使用:
1 创建概念模型,首先要找出实体,然后再确定实体之间的关系2 生成报告、交给负责人认可3 生成物理模型4 建立数据库连接5 导入数据库
-------------------------------数据建模技术:
数据模型:数据库系统中关于数据和联系的逻辑组织的形式表示。
层次模型、网状模型和关系模型三种,现在应用最广泛的是关系模型。关系模型与面向对象思想不一致,因此有了ORM来解决表和对象之间的关系。
数据库模式就是数据库结构,确定数据库模式是数据库建模的最重要任务模式分为逻辑模式、外模式和内模式,实际上可以分别对应到表、视图和索引模式在英文中是schema
模式:也叫作逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。
外模式:是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图
是与某应用有关的数据的逻辑表示。
内模式:是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。
外模式也叫作子模式或者用户模式,内模式也叫作存储模式。
数据库建模就是确定数据库结构的过程,也就是定义数据库模式的过程。
将现实世界中的事物以及他们之间的联系抽象出来,并且以某种组织方式存储在数据库中。这种组织方式就是数据库结构。
现实世界中的事物在数据库设计中称为实体,而事物与事物之间的联系叫做关系。
网上购物,业务流程是什么?有哪些事物呢?哪些事物需要持久化?哪些不需要?
数据库建模方法:1 ER图 2 对象定义语言(ODL:Object Defination Language)矩形表示实体,椭圆表示属性,菱形表示关系
先有一个思路,然后画出ER图,确定好关系,然后导入关系型数据库中。
--------------------------------数据库范式:一范式:数据库表中不存在重复字段,并且字段不可分割二范式:不存在非主键字段对任一主键字段的部分依赖关系(用来约束联合主键)
一个爸爸和一个妈妈决定了一个孩子;一个妈妈决定了一个孩子就是不符合第二范式
假如必须有两个主键但是你只设了一个主键的话,那么不符合第二范式三范式:不存在非主键对任一主键的传递依赖关系。
由a决定b,b决定c,但是没有a直接去决定c,就是传递依赖
任何字段都不存在传递函数依赖,即主键对主键没有传递依赖。
---------------------------------
第一范式就不说了,只要是个合法的表都满足第一范式,但是假如有个地址的字段,里面包含国、省份、市、地区的话,可以通过设置外键,或是分解字段的方法来解决。
二范式主要规范联合主键情况:要求非主键字段不能由符合主键的一个完全决定,而必须由符合主键共同决定!
只要没有使用联合主键,肯定不会出现违反第二范式的情况!例:学生选课表的设计应该如何实现?假设选课关系表为学号、姓名、年龄、课程名称、乘积、学分。那么这个表里面的主键应该为学号和课程名称联合作为主键,这是毫无疑问的,但是不符合第二范式:因为姓名可以由学号完全决定,和课程名称没有任何关系,也就是说姓名这个非主键字段对这个联合主键有部分依赖关系存在。同理,学分完全由课程名称来决定,也是部分依赖的。成绩是不存在部分依赖的,是由学号和课程名称共同决定的
所以这个表是不满足第二范式的,危害如下:1 数据冗余2 更新异常,若调整了课程的学分,那么每条记录都要调整3 删除异常,假如要删一个学生,那么他选的课也跟着丢了,要是这门课没有别人选的话,该课程的信息就永远的丢失了4 插入异常,假如新来了一门课程,但是没有人选,试问这怎么插入呢?没办法弄……
解决不满足第二范式情况的办法是分解主键建立学生表(学号,姓名,年龄)课程表(课程名称、学分)和选课关系(学号,课程名称,成绩)
一般认为,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字
满足第二范式的设计肯定满足第一范式的要求!
下面说说第三范式:要求不存在非关键字段对任一候选关键字段的传递函数依赖关系,其实,就是不能出现非主键字段决定其他非主键字段!
关键字段决定了非关键字段x,而x又决定了另外一个非关键字段y,这就不满足第三范式!
假设须生关系表(学号,姓名,年龄,所在班级,教室编号,班级人数)主键是学号
学号确定了其余的字段,但是呢,所在班级直接决定了教室编号和班级人数,这就是典型的传递依赖,不满足第三范式
解决方法:分解实体:学生(学号,姓名,年龄,所在班级)
学院(班级,地点,人数)
两者之间用主外键关系联系起来,二者是一对多的关系。
BC范式:主键也不可以有传递依赖关系。例:假如一个表(班号,课程号,老师号,课程时间)那么课程号和班号唯一决定是课程时间而且课程号和老师号也可以决定课程时间但是呢,班号决定了老师号,这就是说主键存在传递依赖。
解决方法:分解关系班级号,课程号,课程时间班级号,老师号建立成上面两个关系表就ok了
总的来说,各个范式都是在尽力去分解,不把数据都存在一个表中。应该尽可能的去满足范式的要求!在性能的要求下,也并非一定要严格遵从范式要求,以适当的数据冗余来提升性能也是一个很好的选择。
怎么在数据库中的表中表示关系:关系种类:一对一,多对多,一对多,多对一
怎么在数据库中的表里面表示上面这四种关系??可以通过外键方式;还可以通过主键对应方式,比如学生和电脑的一对一的关系可以通过让学生的主键和对应电脑的主键一致来做到,其中必然有一个主键是主动变化的,而另外一个主键是跟随这这个主键来变化
还有可以通过再建立一个关系表的方式,这个关系表中就有两个主键,一个是电脑,一个是学生将他们两个关联起来,在学生表和电脑表中都不考虑关系的问题,全部让关系表去考虑
一对多或是多对一的关系里面,用多的那一端来存放外键,还可以用关系表方式。
多对多的关系只能用关系表来解决了,没别的办法了。
因此一对一有三种方式:主键方式,外键方式和关系表方式一对多有两种方式:外键和关系表方式多对多只有关系表方式
hibernate中强烈建议使用关系表,这样把对象和关系分离开来,好处理。
如果您想提高自己的技术水平,欢迎加入本站官方1号QQ群:&&,&&2号QQ群:,在群里结识技术精英和交流技术^_^
本站联系邮箱:

我要回帖

更多关于 mysql 分页 优化 的文章

 

随机推荐