【问题标题】:Database-schema Design for e-commerce website电子商务网站的数据库模式设计
【发布时间】:2020-05-12 10:33:21
【问题描述】:

我正在制作一个电子商务网站并使用 MySQL 来存储数据。

我在下面添加了 Schema 图。请让我知道设计中可能存在的缺陷或可能出现的其他问题。

我正在设计的产品在其表面处理、尺寸方面有很大的变化,并具有其独特的属性。

这是我想要实现的目标:

  • 产品 A 可以有 1 个或多个变体。(例如:1.AA(哑光饰面)、AB(木饰面)、AC(油饰面))。
  • 每个变体可以有 0 个或多个尺寸,例如 30x40、40x60 等。(例如:AA 可以有 30x40 和 40x60)
  • 每个产品都有其独特的属性。 (例如:产品 A 可以有 Thickness ,产品 B 可以有 Class)
  • 产品的 SKU 和价格取决于其所有不同的尺寸、表面处理及其独特属性。

对于我本可以使用 EAV 的独特属性,但改为使用这种方法。

让我在这里解释一下表格:

  • 品牌、类别和系列正是他们所说的。
  • base_relation_table是以上3个表之间的关系,所有可能的组合。
  • 产品(包含所有产品,例如:产品 A、产品 B)并参考 base_relation_tableID 以了解它属于哪个组合。它还引用了包含其外观(石头、木纹等)的图案
  • product_option_relation 是唯一属性的关系(例如产品 A ID、厚度 ID)
  • option_table只包含名称(厚度、等级、印刷技术等)
  • option_value 包含 option_tables 的所有值(例如:0.7、0.9、Professional、Beginners 等)
  • product_variant 包含产品的所有变体(例如:AA、AB、AC、BA、BB 等)
  • 颜色、光洁度对于所有产品变体都是 1:n。(例如:AA 亚光红色,AB 亮白色)
  • Dimensions 包含与 product_variant 的 n:m 关系
  • variant_values 是所有属性、所有变体和独特属性的组合。

正如我之前提到的 SKU 和价格随着其独特性和变化属性而变化,所以我在这里添加了它。因为在这里我得到了所有的组合。

这里是架构代码:

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='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

-- -----------------------------------------------------
-- Schema Catelogue
-- -----------------------------------------------------

-- -----------------------------------------------------
-- Schema Catelogue
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `Catelogue` DEFAULT CHARACTER SET utf8 ;
USE `Catelogue` ;

-- -----------------------------------------------------
-- Table `Catelogue`.`brands`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`brands` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`brands` (
  `ID` VARCHAR(45) NOT NULL,
  `b_name` VARCHAR(45) NULL,
  `thumbnails` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`categorys`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`categorys` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`categorys` (
  `ID` VARCHAR(45) NOT NULL,
  `c_name` VARCHAR(45) NULL,
  `thumbnails` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`collections`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`collections` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`collections` (
  `ID` VARCHAR(45) NOT NULL,
  `co_name` VARCHAR(45) NULL,
  `thumbnails` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`base_Relation_table`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`base_Relation_table` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`base_Relation_table` (
  `ID` INT NOT NULL,
  `Brands_ID` VARCHAR(45) NOT NULL,
  `Categorys_ID` VARCHAR(45) NOT NULL,
  `Collections_ID` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`ID`),
  INDEX `fk_base_Relation_table_Brands_idx` (`Brands_ID` ASC) VISIBLE,
  INDEX `fk_base_Relation_table_Categorys1_idx` (`Categorys_ID` ASC) VISIBLE,
  INDEX `fk_base_Relation_table_Collections1_idx` (`Collections_ID` ASC) VISIBLE,
  CONSTRAINT `fk_base_Relation_table_Brands`
    FOREIGN KEY (`Brands_ID`)
    REFERENCES `Catelogue`.`brands` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_base_Relation_table_Categorys1`
    FOREIGN KEY (`Categorys_ID`)
    REFERENCES `Catelogue`.`categorys` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_base_Relation_table_Collections1`
    FOREIGN KEY (`Collections_ID`)
    REFERENCES `Catelogue`.`collections` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`pattern`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`pattern` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`pattern` (
  `ID` VARCHAR(45) NOT NULL,
  `option_name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE INDEX `values_UNIQUE` (`option_name` ASC) VISIBLE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`product`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`product` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`product` (
  `ID` INT NOT NULL,
  `p_name` VARCHAR(45) NULL,
  `Description` VARCHAR(45) NULL,
  `base_Relation_table_ID` INT NOT NULL,
  `pattern_ID` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`ID`),
  INDEX `fk_Product_base_Relation_table1_idx` (`base_Relation_table_ID` ASC) VISIBLE,
  UNIQUE INDEX `name_UNIQUE` (`p_name` ASC) VISIBLE,
  INDEX `fk_Product_pattern1_idx` (`pattern_ID` ASC) VISIBLE,
  CONSTRAINT `fk_Product_base_Relation_table1`
    FOREIGN KEY (`base_Relation_table_ID`)
    REFERENCES `Catelogue`.`base_Relation_table` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Product_pattern1`
    FOREIGN KEY (`pattern_ID`)
    REFERENCES `Catelogue`.`pattern` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`colors`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`colors` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`colors` (
  `ID` INT NOT NULL,
  `color_name` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`option_table`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`option_table` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`option_table` (
  `ID` INT NOT NULL,
  `option_name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE INDEX `values_UNIQUE` (`option_name` ASC) VISIBLE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`option_values`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`option_values` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`option_values` (
  `ID` INT NOT NULL,
  `Option_ID` INT NOT NULL,
  `value_name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`ID`, `Option_ID`),
  UNIQUE INDEX `values_UNIQUE` (`value_name` ASC) VISIBLE,
  CONSTRAINT `fk_Option_values_Options1`
    FOREIGN KEY (`Option_ID`)
    REFERENCES `Catelogue`.`option_table` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`finish`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`finish` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`finish` (
  `ID` INT NOT NULL,
  `finish_name` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`product_variant`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`product_variant` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`product_variant` (
  `Variant_ID` INT NOT NULL,
  `Product_ID` INT NOT NULL,
  `Finish_ID` INT NOT NULL,
  `Colors_ID` INT NOT NULL,
  `metadata` VARCHAR(45) NULL,
  `thumbnail` VARCHAR(45) NOT NULL DEFAULT '\" \"',
  INDEX `fk_ProductDetails_Finish1_idx` (`Finish_ID` ASC) VISIBLE,
  INDEX `fk_ProductDetails_Colors1_idx` (`Colors_ID` ASC) VISIBLE,
  INDEX `fk_Product_Variant_Product1_idx` (`Product_ID` ASC) VISIBLE,
  PRIMARY KEY (`Variant_ID`, `Product_ID`),
  CONSTRAINT `fk_ProductDetails_Finish1`
    FOREIGN KEY (`Finish_ID`)
    REFERENCES `Catelogue`.`finish` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_ProductDetails_Colors1`
    FOREIGN KEY (`Colors_ID`)
    REFERENCES `Catelogue`.`colors` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Product_Variant_Product1`
    FOREIGN KEY (`Product_ID`)
    REFERENCES `Catelogue`.`product` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`product_option_relation`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`product_option_relation` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`product_option_relation` (
  `Product_ID` INT NOT NULL,
  `Option_ID` INT NOT NULL,
  INDEX `fk_Product_Option_Product1_idx` (`Product_ID` ASC) VISIBLE,
  INDEX `fk_Product_Option_Options1_idx` (`Option_ID` ASC) VISIBLE,
  PRIMARY KEY (`Product_ID`, `Option_ID`),
  CONSTRAINT `fk_Product_Option_Product1`
    FOREIGN KEY (`Product_ID`)
    REFERENCES `Catelogue`.`product` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Product_Option_Options1`
    FOREIGN KEY (`Option_ID`)
    REFERENCES `Catelogue`.`option_table` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`dimensions`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`dimensions` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`dimensions` (
  `ID` INT NOT NULL,
  `dimensions_value` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`dimensions_has_product_variant`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`dimensions_has_product_variant` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`dimensions_has_product_variant` (
  `Dimensions_ID` INT NOT NULL,
  `Product_ID` INT NOT NULL,
  `Variant_ID` INT NOT NULL,
  PRIMARY KEY (`Dimensions_ID`, `Product_ID`, `Variant_ID`),
  INDEX `fk_Dimensions_has_Product_Variant_Product_Variant1_idx` (`Product_ID` ASC, `Variant_ID` ASC) VISIBLE,
  CONSTRAINT `fk_Dimensions_has_Product_Variant_Dimensions1`
    FOREIGN KEY (`Dimensions_ID`)
    REFERENCES `Catelogue`.`dimensions` (`ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Dimensions_has_Product_Variant_Product_Variant1`
    FOREIGN KEY (`Product_ID` , `Variant_ID`)
    REFERENCES `Catelogue`.`product_variant` (`Product_ID` , `Variant_ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `Catelogue`.`variant_value`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Catelogue`.`variant_value` ;

CREATE TABLE IF NOT EXISTS `Catelogue`.`variant_value` (
  `Product_ID` INT NOT NULL,
  `Option_ID` INT NOT NULL,
  `Value_ID` INT NOT NULL,
  `Dimensions_ID` INT NOT NULL,
  `Variant_ID` INT NOT NULL,
  `price` VARCHAR(45) NOT NULL,
  `SKU` VARCHAR(45) NULL,
  PRIMARY KEY (`Product_ID`, `Option_ID`, `Value_ID`, `Dimensions_ID`, `Variant_ID`),
  INDEX `fk3_option_values_idx` (`Value_ID` ASC, `Option_ID` ASC) VISIBLE,
  INDEX `fk2_product_options_idx` (`Product_ID` ASC, `Option_ID` ASC) VISIBLE,
  INDEX `fk_variant_value_dimensions_has_product_variant1_idx` (`Dimensions_ID` ASC, `Variant_ID` ASC, `Product_ID` ASC) VISIBLE,
  CONSTRAINT `fk2_product_options`
    FOREIGN KEY (`Product_ID` , `Option_ID`)
    REFERENCES `Catelogue`.`product_option_relation` (`Product_ID` , `Option_ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk3_option_values`
    FOREIGN KEY (`Value_ID` , `Option_ID`)
    REFERENCES `Catelogue`.`option_values` (`ID` , `Option_ID`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_variant_value_dimensions_has_product_variant1`
    FOREIGN KEY (`Dimensions_ID` , `Variant_ID` , `Product_ID`)
    REFERENCES `Catelogue`.`dimensions_has_product_variant` (`Dimensions_ID` , `Variant_ID` , `Product_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;

我有什么遗漏吗?会是规模吗?设计好看吗?

【问题讨论】:

  • 乍一看我觉得还可以。但如果有缺点 - 您只会在开始创建报告时开始看到它们。如果您开始觉得报表查询变得过于复杂而无法构建 - 那么您可能正面临数据模型中的缺陷。

标签: mysql database database-design


【解决方案1】:

这是“过度标准化”。例如,查看colors。您正在用 4 字节整数替换 3 字节“红色”。不节省空间。 (好吧,“洋红色”占用超过 4 个字节,但不多。)

规范化的另一个目的是更容易更改整个数据集中“red”的拼写。我认为这不会发生。

所以...为“常见”或“重要”或“经常搜索”属性设置列。

对于其他属性,将它们放入 JSON 字符串中,并使其成为一个名为 other_attributes 的列。

虽然您的架构比常见的 EAV 更复杂,但这里讨论了为什么 EAV 很差以及如何处理它:http://mysql.rjweb.org/doc.php/eav

至于dimensions,想想你将如何处理值或值列表。我怀疑除了在屏幕上显示该列表之外,您不会对 "30x40,40x60" 做任何事情。它本质上是不可搜索的。所以唯一实际的事情就是将该字符串放入我建议的 JSON 中。

【讨论】:

  • 对于颜色,我确实有很多其他名称是“浅黄色”、“浅绿色”等单词的组合。而且我没有得到公用表部分你是什么意思?至于尺寸,我计划根据不同尺寸对我的产品进行分类。我会非常乐意尝试您为 other_attributes 建议的 JSON 字符串。
  • @Seeon - “深矢车菊蓝”。在product_variant 中,有color VARCHAR(..) 而不是color_id;然后折腾桌子colors。然后,SELECT ... ORDER BY color 无需JOIN
  • 知道了。但我想知道,因为我有超过 3k 的产品,这在存储方面是否是正确的方法,谢谢你的回复,我回复很感激。
  • @Seeon - 如果您有 1 亿个产品,您的存储问题值得考虑。只有 3K,我不会担心额外的,比如 10KB。
猜你喜欢
  • 1970-01-01
  • 2018-12-05
  • 2015-11-22
  • 2018-09-03
  • 2019-06-17
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多