公告板 - 数据库优化

时间:2010-11-30 05:20:41

标签: php mysql database-design normalization

这个问题是由此产生的 Question

项目和问题

我目前正在开展的项目是一个大型非营利组织的公告板。公告板将用于允许组织内的办公室间通信。

我正在构建应用程序,并且无法从我的数据库中提取我需要的结果,因为我认为它没有正确规范化并且因为我对关系数据库理论的了解有限和mysql。

我非常感谢董事会设计的总体投入,特别是可以改进数据库结构以促进有效查询的方式,并帮助我更快地开发此应用程序和未来的应用程序

< p>

业务逻辑

公告牌将按以下方式使用

  1. 发布公告和对公告的回复   
          
    1. 全国各地办事处的员工或“用户”都可以在公告板上发布消息。必须将小册子发布到某个地点并进行分类 - 我将称之为“公告”。
    2.     
    3. 用户可以在任何一个公告上发布任意数量的回复,用户也可以回复自己的公告 - 我会称之为“回复”。
    4.   
    5. 评分公告和回复     
      1. 用户可以“喜欢”或“不喜欢”公告或回复,每个公告或回复都会显示喜欢或不喜欢的总数。
      2.   
      3. 查看公告栏和回复   
              
        1. 公告可以按时间顺序显示。
        2.     
        3. 用户可以按照该公告的最新回复按时间顺序或按时间顺序对公告进行排序(如果您需要更多解释,请告诉我)
        4.     
        5. 选择特定公告时,将按时间顺序显示对该公告的回复
        6.   
        -- phpMyAdmin SQL Dump
        -- version 3.2.4
        -- http://www.phpmyadmin.net
        --
        -- Host: localhost
        -- Generation Time: Jan 16, 2011 at 06:44 PM
        -- Server version: 5.1.41
        -- PHP Version: 5.3.1
        
        SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
        
        --
        -- Database: `bulletinboard`
        --
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bbs`
        --
        
        CREATE TABLE IF NOT EXISTS `bbs` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `bb_locations_id` int(11) NOT NULL,
          `bb_categories_id` int(11) NOT NULL,
          `users_id` int(11) NOT NULL,
          `title` varchar(255) NOT NULL,
          `content` text NOT NULL,
          `created_date` int(11) NOT NULL,
          `rank` int(11) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=87 ;
        
        --
        -- Dumping data for table `bbs`
        --
        
        INSERT INTO `bbs` (`id`, `bb_locations_id`, `bb_categories_id`, `users_id`, `title`, `content`, `created_date`, `rank`) VALUES
        (83, 8, 28, 44, 'sdaf', 'asdfasdf', 1292712797, 0),
        (84, 8, 28, 44, 'asdf', 'asdfasd', 1292875089, 0),
        (86, 8, 28, 44, 'Robert is leaving', 'Robert is leaving and going back to the states ', 1294344916, 0);
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bb_categories`
        --
        
        CREATE TABLE IF NOT EXISTS `bb_categories` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `title` varchar(255) NOT NULL,
          `description` varchar(255) NOT NULL,
          `list_order` varchar(255) NOT NULL,
          `admin` int(11) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=30 ;
        
        --
        -- Dumping data for table `bb_categories`
        --
        
        INSERT INTO `bb_categories` (`id`, `title`, `description`, `list_order`, `admin`) VALUES
        (28, 'Travel', 'Rideshares, proposed trips etc', '1', 1);
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bb_locations`
        --
        
        CREATE TABLE IF NOT EXISTS `bb_locations` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `title` varchar(255) NOT NULL,
          `description` varchar(255) NOT NULL,
          `address` varchar(255) NOT NULL,
          `post_code` int(11) NOT NULL,
          `list_order` int(11) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
        
        --
        -- Dumping data for table `bb_locations`
        --
        
        INSERT INTO `bb_locations` (`id`, `title`, `description`, `address`, `post_code`, `list_order`) VALUES
        (8, 'Washington DC', 'asdkf', 'dsf', 0, 1);
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bb_ratings`
        --
        
        CREATE TABLE IF NOT EXISTS `bb_ratings` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `bbs_id` int(11) NOT NULL,
          `users_id` int(11) NOT NULL,
          `like_id` int(2) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=68 ;
        
        --
        -- Dumping data for table `bb_ratings`
        --
        
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bb_replies`
        --
        
        CREATE TABLE IF NOT EXISTS `bb_replies` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `users_id` int(11) NOT NULL,
          `bbs_id` int(11) NOT NULL,
          `content` text NOT NULL,
          `created_date` int(11) NOT NULL,
          `rank` int(11) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=158 ;
        
        --
        -- Dumping data for table `bb_replies`
        --
        
        INSERT INTO `bb_replies` (`id`, `users_id`, `bbs_id`, `content`, `created_date`, `rank`) VALUES
        (156, 44, 86, 'good ridance i say\r\n', 1294788444, 0),
        (157, 44, 86, 'And stay away\r\n', 1294892751, 0);
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bb_reply_ratings`
        --
        
        CREATE TABLE IF NOT EXISTS `bb_reply_ratings` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `bb_replies_id` int(11) NOT NULL,
          `users_id` int(11) NOT NULL,
          `like_id` tinyint(11) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=115 ;
        
        --
        -- Dumping data for table `bb_reply_ratings`
        --
        
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `bb_sort_bys`
        --
        
        CREATE TABLE IF NOT EXISTS `bb_sort_bys` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `title` varchar(20) NOT NULL,
          `description` varchar(255) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
        
        --
        -- Dumping data for table `bb_sort_bys`
        --
        
        INSERT INTO `bb_sort_bys` (`id`, `title`, `description`) VALUES
        (1, 'Newest', 'Posts are sorted by their creation date'),
        (2, 'Popular', 'Posts are sorted by the date of their lates reply, or by post date if they have now replies');
        
        -- --------------------------------------------------------
        
        --
        -- Table structure for table `users`
        --
        
        CREATE TABLE IF NOT EXISTS `users` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `user_name` varchar(10) NOT NULL,
          `first_name` varchar(100) NOT NULL,
          `last_name` varchar(100) NOT NULL,
          `permission` int(1) NOT NULL,
          `bb_sort_bys_id` varchar(10) NOT NULL,
          `bb_locations_csv` varchar(255) NOT NULL,
          `defaultLocation` int(11) NOT NULL,
          `bb_categories_csv` varchar(255) NOT NULL,
          `total_bulletins` int(5) NOT NULL,
          `bulletins_per_page` int(5) NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=45 ;
        

5 个答案:

答案 0 :(得分:14)

答案 1 :(得分:5)

拥有高效数据库的关键是简化。关系数据库的主要目标不是重复任何信息。据我所知,我采用了SQL转储并快速起草了一个规范化的简单版本。我确实留下了你所拥有的一些领域的cvs等。我已经删除了字段,通过在需要信息时查询数据库来重新计算更简单,例如用户总帖子和给定帖子的排名。我还删除了你的bb_replies,因为你可以通过引用父帖来完成相同的结果。我已经将表重新命名为对我来说有意义的表,你可以使用你感觉舒适的命名方案。我发现使用简单的术语可以更容易地理解数据之间的相互关系。

我必须承认我同意上面的一些评论,有很多BB可以正常工作,并且具备您正在寻找的所有功能。你很幸运我今晚的阅读情绪大声笑,这是一个很长的问题。简化是一切的关键:)

alt text

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';


-- -----------------------------------------------------
-- Table `users`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `users` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `username` VARCHAR(45) NULL ,
  `password` VARCHAR(100) NULL ,
  `email` VARCHAR(255) NULL ,
  `first_name` VARCHAR(100) NULL ,
  `last_name` VARCHAR(100) NULL ,
  `permission` INT NULL ,
  `created` DATETIME NULL ,
  `modified` DATETIME NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `categories`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `categories` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  `description` TEXT NULL ,
  `order` INT NULL ,
  `admin` INT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `locations`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `locations` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  `description` TEXT NULL ,
  `address` TEXT NULL ,
  `order` INT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `posts`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `posts` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `post_id` INT NOT NULL ,
  `user_id` INT NOT NULL ,
  `category_id` INT NOT NULL ,
  `location_id` INT NOT NULL ,
  `title` VARCHAR(45) NULL ,
  `content` TEXT NULL ,
  `created` DATETIME NULL ,
  `modified` DATETIME NULL ,
  PRIMARY KEY (`id`, `post_id`, `user_id`, `category_id`, `location_id`) ,
  INDEX `fk_posts_users` (`user_id` ASC) ,
  INDEX `fk_posts_posts1` (`post_id` ASC) ,
  INDEX `fk_posts_categories1` (`category_id` ASC) ,
  INDEX `fk_posts_locations1` (`location_id` ASC) ,
  CONSTRAINT `fk_posts_users`
    FOREIGN KEY (`user_id` )
    REFERENCES `users` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_posts1`
    FOREIGN KEY (`post_id` )
    REFERENCES `posts` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_categories1`
    FOREIGN KEY (`category_id` )
    REFERENCES `categories` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_locations1`
    FOREIGN KEY (`location_id` )
    REFERENCES `locations` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `likes`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `likes` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `user_id` INT NOT NULL ,
  `post_id` INT NOT NULL ,
  `like` TINYINT(1)  NULL ,
  PRIMARY KEY (`id`, `user_id`, `post_id`) ,
  INDEX `fk_posts_users_users1` (`user_id` ASC) ,
  INDEX `fk_posts_users_posts1` (`post_id` ASC) ,
  CONSTRAINT `fk_posts_users_users1`
    FOREIGN KEY (`user_id` )
    REFERENCES `users` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_users_posts1`
    FOREIGN KEY (`post_id` )
    REFERENCES `posts` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `sort_options`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `sort_options` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  `description` TEXT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `preferences`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `preferences` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `user_id` INT NOT NULL ,
  `pagination` INT NULL ,
  `sort_option_id` INT NOT NULL ,
  `categories_csv` VARCHAR(45) NULL ,
  `locations_csv` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`, `user_id`, `sort_option_id`) ,
  INDEX `fk_preferences_users1` (`user_id` ASC) ,
  INDEX `fk_preferences_sort_options1` (`sort_option_id` ASC) ,
  CONSTRAINT `fk_preferences_users1`
    FOREIGN KEY (`user_id` )
    REFERENCES `users` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_preferences_sort_options1`
    FOREIGN KEY (`sort_option_id` )
    REFERENCES `sort_options` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;



SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

答案 2 :(得分:4)

答案 3 :(得分:3)

答案 4 :(得分:0)

不要害怕加入。如果我是你,我会减少你需要编写的所有数据库逻辑并使用像Doctrine或Propel这样的ORM,这将使设计和维护变得更加容易 - 包括你试图避免的所有连接。