在存储许多属性的历史数据时,联结表是正确的解决方案吗?

时间:2011-07-06 11:37:50

标签: mysql database-design

我正在设计一个存储与网站相关的SEO指标的网络应用程序。每个网站每天计算和存储大约50个与每个网站相关的指标。我需要能够随时跟踪每个指标的变化。我根据对规范化的理解设计了以下模式。似乎联结表(tbl_website_metric)将非常快地增长。我想知道这是否是最佳模式,或者我是否犯了任何设计错误。

CREATE  TABLE `tbl_website` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(100) NOT NULL ,
  `domain` VARCHAR(100) NULL ,
  `url` VARCHAR(100) NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

CREATE `tbl_metric` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NOT NULL ,
  `description` VARCHAR(100) NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

CREATE `tbl_website_metric` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `metric_id` INT NOT NULL ,
  `website_id` INT NOT NULL ,
  `created` TIMESTAMP NULL ,
  `value` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`) ,
  CONSTRAINT `fk_tbl_website_metric_tbl_metric1`
    FOREIGN KEY (`metric_id` )
    REFERENCES `tbl_metric` (`id` )
  CONSTRAINT `fk_tbl_website_metric_tbl_website1`
    FOREIGN KEY (`website_id` )
    REFERENCES `tbl_website` (`id` ) )
 ENGINE = InnoDB;

3 个答案:

答案 0 :(得分:0)

看起来很不错。

id上的索引应该保持你的表现健康。

答案 1 :(得分:0)

一般看起来不错......一些小问题,主要是关于列类型:

  • tbl_website_metric IMO中没有明确主键的理由。 (metric_id, website_id, created)上的唯一索引应该足够了
  • tbl_website_metric.created应该是DATE(保存1个字节,对于索引的唯一性是必需的)
  • value必须是文字吗?
  • 您为metric_idwebsite_id声明了外键约束;虽然这当然有一些优点,但这也意味着锁定问题,参见http://www.mysqlperformanceblog.com/2006/12/12/innodb-locking-and-foreign-keys/

HTH

答案 2 :(得分:0)

您的数据库设计似乎适用于该方案;但是有一些建议:

  1. 我不确定您的应用会存储多少个网站的统计信息,但如果不超过几千个,请考虑将tbl_websiteid更改为SMALLINT UNSIGNED。这将允许您存储65535个网站

  2. 同样,由于您有大约50个指标,因此将tbl_metricid更改为TINYINT UNSIGNED是有意义的。这将允许您存储255个指标

  3. 我认为FK会自动在各个列上创建索引,但如果没有,请考虑为tbl_website_metric创建索引。metric_idtbl_website_metricwebsite_id

  4. 请注意,对于1和2,您还需要相应更改tbl_website_metricmetric_idtbl_website_metricwebsite_id的数据类型。

    我不确定联结表有多大,但是MySQL非常能够处理大型表。无论如何,考虑从tbl_website_metric中清除过时的条目,或者将它们存档到另一个表,这将是一个很好的方法。

    我也想提出另一种方法。如果1)您的指标非常静态,从某种意义上说,通常不会添加或删除指标,2)它是所有网站的相同指标,您可以考虑将指标存储在列中:

    CREATE TABLE `tbl_website_metric` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `website_id` INT NOT NULL,
      `created` TIMESTAMP NULL,
      `metric_1` VARCHAR(45) NULL,
      `metric_2` VARCHAR(45) NULL,
      `metric_3` VARCHAR(45) NULL,
      `metric_4` VARCHAR(45) NULL,
       ...
       ...
      `metric_50` VARCHAR(45) NULL
    );
    

    这意味着每个网站都有一个插入和单个选择。 Plus会将表中的记录数减少N倍,其中N =指标数。

    希望它有所帮助。