选择显示字体大小

树型论坛的数据库设计和快速算法

树型论坛(即阶梯式论坛)的实现算法,是一直被讨论的问题。总结起来,一般无非是两种:  
第一是递归。这种方式最简单,思路最清楚,但是效率也最低,特别是进行页定位的时候。由于每进行一次递归调用,就必须执行一条数据库查询,使它在大量并发请求时的负载成为灾难性的。因此这种算法一般不实用。  
第二是增加一个排序字段,思路是使用一个特殊设计的字段,例如排序串或者中值排序基数,来实现贴子的插入,在显示的时候,只需要为每一个主贴执行一次查询,将所有得到的记录按序显示即可。这种方式在效率上有了很大提高,但是仍然不很理想,而且使得插入的代码增加了不必要的复杂性,同时还往往导致了支持层次有限制的问题。  

有没有一种办法可以简单、高效地实现树型论坛呢?  

左轻侯提出一种算法,在显示速度上超过我见的任何类似算法,实现起来也不复杂。  
它的思路很简单:就是完全不理会树型结构本身,将整个论坛视为一个简单的顺序表。这样不论任何形式的页面,只需要一条查询即可得到。那么如何实现树型结构呢?方法是添加两个格式化字段,一个记录顺序表的次序,一个记录树的层次,对取得的记录集进行相应格式化,即可得到原汁原味的树型论坛。  

我的改进是,  
               1。取消ordernum,用messageid的顺序来实现,  
               2。在bbsmessage表里面取消threadid的fk,用算法来映射  
               3。在bbsthread表里面增设一个endmessageid来为最大messageid,提高插入数据的速度  

具体实现方法如下:  

dbschema:  

bbsmessage:                        贴子表  
       messageid      int                                  :  贴子id  
       deep                smallint                        :  树的深度,0为主贴,以此类推  
       context          varchar  4096                :  正文  
       title              varchar  256                  :  标题  
       clickdate      timestamp                      :  阅读时间  
       createdate    timestamp                      :  创建时间(发布时间)  
       clickcnt        smallint                        :  人气  
       rewards          smallint                        :  得分  
       userid            int                                  :  创建用户id  
       flag                char(1)                          :  标志    d=删除状态    a  =活跃状态  
//    threadid        int                                  :  主题id  =  messageid/1000  

bbsthread:                            话题表  
       threadid                        int                  :  话题id  
       forumid                          int                  :  所属论坛id  
       clickdate                      timestamp      :  阅读时间  
       createdate                    timestamp      :  创建时间  

       clicksum                        smallint        :  话题人气  
       replysum                        smallint        :  回复数量  
       endmessageid                int                  :  尾部id  
//    rootmessageid              int                  :  该话题的根贴子id,可以用threadid*1000得到rootmessageid  
//    replydate                      timestamp      :  最新回复时间,因为可以用lastmessageid得到时间  
//    title                              vchar(20)      :  标题,可以用threadid*1000得到rootmessageid,再取得title  

bbsuserinfo:                        用户表  
       userid                            int                  :  用户id  
       usernickname                vchar  20        :  昵称  
       sex                                  char  (1)        :  性别  
       rewards                          smallint        :  得分  
       postcnt                          smallint        :  一共发贴数  
       icon                                smallint        :  图标id  


列出全部话题列表的sql:  
//            主题          人气                创建人    最后更新时间  回复人  删除属性  
select  title  ,  clicksum  ,  replydate  ,  username  ,  deep  ,  replysum,deep,visual  
       from  
               bbsuserinfo,bbsthread,bbsmessage  
       where  
               bbsmessage.userid  =  bbsuserinfo.userid  
               and  
               bbsmessage.messageid  =  bbsthread.rootmessageid  
               and  
               bbsthread.messageid  <  bbsthread.message+1000  
       order  by  messageid  desc  


其中threadid  *  1000  =  rootmessageid,  

对贴子的管理实现:  
     1.      树结构:  
     1.1    deep层,那么n层message就缩进n个tablelet  
     1.2    如果插入数据,那么就在thread表里面的endmessageid+1并以此为最新id写入bbsmessage  
               比左先生的select  max(ordernum)再添加效果好,因为这样是row级锁,而select  max()是表级锁。如果不加事务处理,必定有问题。因此,这点必须改进。  
               中间插入操作分析:  
               messageid由thread表里面的threadid*1000得到,因此,这个动作是如同在一个顺序表里面插入数据一般。  
               对此,我没有做改进,因为我认为左先生的分析已经很明确了。  
               但是如果数据中间有+n个间隔,如0,5,10,的顺序,那么中间插入纪录的也许速度有所提高。但是这样有效贴子数就下降了。  

例子:  
└─api  (1000)  
         ├─java  (1001)  
         │    ├─                                --  1002已经被delete  
         │    ├─applet  (1003)--  del  1003,同时要delete  1004,  因为在(awt  1005  deep3)前有class-use(1004,deep4)  
         │    │    └─class-use  (1004)  
         │    ├─awt  (1005)    
         │    │    ├─class-use  (1006)    
         │    │    ├─color    (1007)  
         │    │    │    └─  new  !  <--  1008,  同时>1008都+1  
         │    │    ├─datatransfer  (1008)  
         │    │    │    └─class-use  (1009)    <--  new  

=>  


效率分析:  

在message表中,  messageid并不是按顺序存放的,而是跳着存放,  
系统限制没个话题总回贴数不能超过1000,那么一个long型数据在一个论坛里面可以最大支持2147483647/1000=2147483条记录  
应该说,一张有214万7千左右的bbs数据库应该是很够用了。  
如果系统还要大,那么就可以按时间段更换数据表即可实现无限量贴子。具体做法:如引入messagehistory2002表等等。  

显示速度应该不会更快了,仅仅是一条简单的select,对一个int字段进行排序,而且支持无限的回复层次。相比之下,递归需要为一个页面中的每一条贴子进行一次select,对datetime字段进行排序,而&ldquo;主贴排序字段法&rdquo;需要为每一个主贴进行一次select,对char字段进行排序。效率比较差的只有在插入时,如果插入的位置很靠前,可能要更新大量记录的messageid字段。但是经验告诉我们,这种树型论坛,回复一般都集中在第一二页,极少有人回复很久以前的贴子,所以偶尔为之,也不会增加太大的负担。如果你实在不放心,也可以用技术手段强制禁止回复一段时间  
---------------------------------------------------------------  


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons