不一致数据的数据库结构

时间:2012-06-26 21:27:59

标签: mysql

我正在为我的公司创建一个存储许多不同类型信息的数据库。类别包括亮度,对比度,色度等。每个类别都有一些我公司想要开始存储的数据点。

通常,我会为每个类别创建一个表,用于存储相应的数据。 (这就是我学会这样做的方式)。但是,有时这些类别具有“子数据”,这将改变每个表中所需的字段数。

我的问题是人们在构建数据库时如何处理数据的不一致?他们只是不断添加更多的表来获取额外的数据,还是完全不同的其他内容?

3 个答案:

答案 0 :(得分:1)

关于关系数据库模型,有一些(并且非常感谢一些)不可修改的规则。其中之一是,如果您不知道要存储的 ,那么您很难存储它。有可能,你将更难以检索它。

尽管如此,业务规则的现实往往不如数据库设计的象牙塔那么明确。最重要的是,您可能希望甚至需要一种方法来引入新属性而无需更改架构。

以下是两种可行的方法:

  1. 使用专门用于松散或不连续架构的数据存储区 (NoSQL和朋友)。详细解释这是CS的主题 论文,而不是stackoverflow答案。
  2. 我的建议:使用单独的属性表 - 这是如何 这就是:
  3. 假设为了论证,您的产品总是有(唯一字符串)name,(整数)idbrightness,{{1} },contrast加上有时(整数)chromaticity和(字符串)foo,请考虑这些表格

    bar

    现在,您的“标准”属性将照常放在CREATE TABLE products ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, brightness INT, contrast INT, chromaticity INT, UNIQUE INDEX(name) ); CREATE TABLE properties ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, proptype ENUM('null','int','string') NOT NULL default 'null', UNIQUE INDEX(name) ); INSERT INTO properties VALUES (0,'foo','int'), (0,'bar','string'); CREATE TABLE product_properties ( id INT PRIMARY KEY AUTO_INCREMENT, products_id INT NOT NULL, properties_id INT NOT NULL, intvalue INT NOT NULL, stringvalue VARCHAR(250) NOT NULL, UNIQUE INDEX(products_id,properties_id) ); 表中,而“可选”属性将存储在引用产品ID和属性ID的products行中,值为product_propertiesintvalue

    选择包含stringvalue的产品(如果有)

    foo

    甚至

    SELECT 
      products.*,
      product_properties.intvalue AS foo
    FROM products
      LEFT JOIN product_properties 
        ON products.id=product_properties.product_id 
        AND product_properties.property_id=1
    

    请理解,这会导致性能下降 - 实际上您会根据灵活性交换性能:添加另一个属性只不过SELECT products.*, product_properties.intvalue AS foo FROM products LEFT JOIN product_properties ON products.id=product_properties.product_id LEFT JOIN properties ON product_properties.property_id=properties.id WHERE properties.name='foo' OR properties.name IS NULL INSERT中的行,架构保持不变。< / p>

答案 1 :(得分:0)

如果你不是mysql绑定,那么其他数据库有table inheritancearrays来解决某些特殊情况。 Postgresql是一个非常好的数据库,您可以像mysql一样轻松自如地使用它。

使用mysql你可以:

  1. 更改您的表,添加额外的列,并在您不需要的子类别数据中允许NULL。这样可以检查完整性,因为您仍然可以在列上添加约束。除非你真的有这样的 lot 子类别列,否则我建议这样做,否则选择3。

  2. 在一个单独的表中动态存储子类别数据,该表具有category_id,category_row_id,子类别标识符(=子类别的类型)和值列:这样您就可以通过category_id链接它来检索数据(确定table)和category_row_id(链接到原始类别表行的PK)。坏事:你不能正确地使用外键或约束来强制完整性,你需要编写毛茸茸的插入/更新触发器仍然有一些控制,这将完全支持客户端的完整性检查和参考检查的负担。 (在这种情况下,你可以更好地进入NoSQL路线)总之我不推荐这个。

  3. 您可以为每个类别表创建一个单独的子类别表,列可以通过值列固定或变量+可选的子类别标识符,仍然可以使用外键,最好保持完整性,因为您'我们将为您提供全方位的限制。如果您有一个 lot 的子类别列,否则会使您的常规子类别表混乱,那么我建议将其与固定列一起使用。像之前的选项一样,我绝不会建议除了一次性数据之外的任何动态。

  4. 或者,如果您的子类别非常易变且易变:使用NoSQL和文档数据库(例如mongodb),请注意您可以将所有常规数据保存在正确的RDBMS中,只保留存储数据在文档数据库中虽然可能不推荐。

    如果您的子类别数据处于已知固定状态且不易更改,我只需将额外列添加到特定类别表中。请记住,正确的DBMS的主要特征是通过检查和约束来保护数据的完整性,废除它绝不是一个好主意。

答案 2 :(得分:0)

如果您不仅限于MySQL,则可以考虑使用Microsoft SQL Server并使用Sparse Columns这将允许您扩展架构以包含所需的多个列,而不会对不是的列产生存储损失对于给定的行是相关的。