简体   繁体   English

MySQL能源系统建模数据库EAV设计

[英]MySQL Energy System Modelling Database EAV Design

We are designing a database schema for an open source energy system optimization project. 我们正在为一个开源能源系统优化项目设计一个数据库模式。

We are using an EAV model because we want it to be flexible and allow problem definition through data. 我们使用EAV模型是因为我们希望它具有灵活性并允许通过数据定义问题。 Ie we want to be able to create new object classes and data parameters associated with them on the fly without having to change the database structure. 也就是说,我们希望能够动态创建新的对象类和与它们相关的数据参数,而不必更改数据库结构。

The model will be implemented in Julia JuMP and we will query the data via sql. 该模型将在Julia JuMP中实现,我们将通过sql查询数据。 There will be an interface with Julia to access the data via SQL and a GUI in PyQT to view, edit, filter the data. Julia将有一个接口,可通过SQL访问数据,而PyQT中的GUI则可查看,编辑和过滤数据。

I have given the SQL for the current schema below. 我在下面给出了当前模式的SQL。

The idea is pretty simple... and object_class table to define types of object. 这个想法很简单...用object_class表定义对象的类型。 An object table to define instances of objects and a parameter_definition table to define parameters that can be associated with objects of each type and a parameter table to define actual values for parameters associated with object instances. 用于定义对象实例的对象表和用于定义可以与每种类型的对象关联的参数的parameter_definition表以及用于定义与对象实例关联的参数的实际值的参数表。 Lets forget about relationships for the moment to keep the discussion simple. 让我们暂时忘记关系,以使讨论变得简单。 Also I have omitted id fields which we will include. 我也省略了我们将包括的id字段。

The parameter table is a little nuanced because our optimization models are chronological models that run over time - so it is very common to have time varying data. 参数表有些细微差别,因为我们的优化模型是随时间推移运行的时间顺序模型-因此,具有时变数据非常普遍。 To handle this, we can give a "time_pattern" to a data value. 为了解决这个问题,我们可以给数据值一个“ time_pattern”。 Also our models will have scenarios. 此外,我们的模型将具有方案。 In the parameters table we can set this value to indicate the parameter value applies to a particular scenario. 在参数表中,我们可以设置该值以指示该参数值适用于特定场景。 A NULL in the scenario field indicates a "base case" data item. 方案字段中的NULL表示“基本情况”数据项。

Now to the crunch... a member of the team has had the idea to replace the parameters table with a JSON field in the objects table. 现在到了紧要关头……团队的一位成员曾想过用对象表中的JSON字段替换参数表。 He is convinced this is better because all the data for an object is contained in this and it avoids the nulls that we will have in the parameters table when there is no time pattern or scenario specified. 他相信这样做会更好,因为对象中的所有数据都包含在其中,并且避免了在未指定时间模式或场景的情况下参数表中的空值。 However, I have a number of problems with this: 1. we lose the referential integrity between the parameter table and the parameter definition table. 但是,我对此有很多问题:1.我们失去了参数表和参数定义表之间的参照完整性。 I know you can link on JSON fields, but isn't it inefficient? 我知道您可以链接JSON字段,但是效率不低吗? 2. There may be some merit to the idea if we were to assume that each object could have a list of parameters which are static (ie no time_pattern or scenario defined. However, when these are defined, we need to have nested JSONs in the JSON field of the objects table. Can we join on this? 3. From what I've read, it is not good practice to bury any fields which you might want to query on inside a JSON field. Is this correct? 4. Is it even possible to join on fields inside a nested JSONs and if you can is it inefficient? 5. Even if you can query and join on fields buried inside a nested JSON, won't the sql be complicated for no real gain? 2.如果我们假设每个对象可以有一个静态参数列表(即未定义time_pattern或场景,则可能有一定的想法。但是,当定义了这些参数时,我们需要在对象表的JSON字段。我们可以加入吗?3.从我所读的内容来看,将可能要查询的任何字段都埋在JSON字段中不是一个好习惯。这是正确的吗?4.是5.即使可以查询和加入嵌套在JSON内的字段,SQL也不会因为没有实际收益而变得复杂吗?

To me, on the surface, the only advantage is you get rid of one table which may simplify some calls. 从表面上看,对我来说,唯一的好处就是您摆脱了一张桌子,这可以简化某些调用。 However you are just burying the data of that table inside a JSON field in another table 但是,您只是将该表的数据埋入另一个表的JSON字段中

Am I missing something? 我想念什么吗? Are there benefits to this proposal that I'm not getting? 我没有得到该建议的好处?

Since the data will be queried en masse to Julia, this element probably doesnt care, JSON or no... but the PyQT Gui where there will be filtering of data etc... the code for this could be greatly complicated? 由于数据将被大量查询到Julia,因此该元素可能不在乎,是JSON还是否...但是PyQT Gui上将进行数据过滤等...用于此的代码可能会非常复杂?

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`class_category` (
  `name` VARCHAR(255) NOT NULL,
  `description` VARCHAR(255) NULL DEFAULT NULL,
  PRIMARY KEY (`name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`object`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`object` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`object` (
  `class_name` VARCHAR(155) NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `description` VARCHAR(255) NULL DEFAULT NULL,
  `category_name` VARCHAR(255) NULL DEFAULT NULL,
  PRIMARY KEY (`class_name`, `name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`object_category`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`object_category` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`object_category` (
  `object_class_name` VARCHAR(255) NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `description` VARCHAR(255) NULL DEFAULT NULL,
  PRIMARY KEY (`object_class_name`, `name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`object_class`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`object_class` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`object_class` (
  `name` VARCHAR(255) NOT NULL,
  `description` VARCHAR(255) NULL DEFAULT NULL,
  `category_name` VARCHAR(155) NULL DEFAULT NULL,
  `display_order` INT(11) NULL DEFAULT '99',
  `display_icon` INT(11) NULL DEFAULT NULL,
  `hidden` TINYINT(1) NULL DEFAULT '0',
  PRIMARY KEY (`name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`parameter`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`parameter` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`parameter` (
  `object_name` VARCHAR(155) NOT NULL,
  `name` VARCHAR(155) NOT NULL,
  `index` TINYINT(2) NULL DEFAULT '1',
  `value` VARCHAR(155) NULL DEFAULT NULL,
  `expression` VARCHAR(255) NULL DEFAULT NULL,
  `time_pattern` VARCHAR(155) NULL DEFAULT NULL,
  `deterministic_timeseries_id` VARCHAR(155) NULL DEFAULT NULL,
  `stochastic_timeseries_id` VARCHAR(155) NULL DEFAULT NULL,
  `stochasticmodel_id` VARCHAR(155) NULL DEFAULT NULL,
  `comment` VARCHAR(255) NULL DEFAULT NULL,
  PRIMARY KEY (`object_name`, `name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`parameter_definition`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`parameter_definition` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`parameter_definition` (
  `name` VARCHAR(155) NOT NULL,
  `description` VARCHAR(155) NULL DEFAULT NULL,
  `data_type` VARCHAR(155) NULL DEFAULT 'NUMERIC',
  `object_type` VARCHAR(155) NOT NULL,
  `object_class_name` VARCHAR(155) NOT NULL,
  `CanHaveTimeSeries` TINYINT(1) NULL DEFAULT '0',
  `CanHaveTimePattern` TINYINT(1) NULL DEFAULT '1',
  `CanBeStochastic` TINYINT(1) NULL DEFAULT '0',
  `dafault_value` VARCHAR(155) NULL DEFAULT '0',
  `is_madatory` TINYINT(1) NULL DEFAULT '0',
  `precision` TINYINT(2) NULL DEFAULT '2',
  `minimum_value` DOUBLE(10,4) NULL DEFAULT NULL,
  `maximum_value` DOUBLE(10,4) NULL DEFAULT NULL,
  PRIMARY KEY (`object_class_name`, `name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`relationship`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`relationship` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`relationship` (
  `class_name` VARCHAR(155) NOT NULL,
  `name` VARCHAR(155) NOT NULL,
  `parent_object_name` VARCHAR(155) NOT NULL,
  `child_object_name` VARCHAR(155) NOT NULL,
  PRIMARY KEY (`class_name`, `name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;


-- -----------------------------------------------------
-- Table `db1303628_spine`.`relationship_class`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `db1303628_spine`.`relationship_class` ;

CREATE TABLE IF NOT EXISTS `db1303628_spine`.`relationship_class` (
  `name` VARCHAR(155) NOT NULL,
  `parent_class_name` VARCHAR(155) NOT NULL,
  `child_class_name` VARCHAR(155) NOT NULL,
  `inheritance` VARCHAR(155) NULL DEFAULT NULL,
  `hidden` TINYINT(1) NULL DEFAULT '0',
  `type` INT(11) NULL DEFAULT NULL,
  PRIMARY KEY (`name`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

You can use the function 您可以使用该功能

common_schema.extract_json_value(json_data,'title')

To query JSON in columns, but as I said above it's Inefficient, and precludes the use of indexes / all the things that make use SQL powerful. 要查询列中的JSON,但是正如我上面所说的那样,它效率低下,并且无法使用索引/使SQL强大的所有功能。 Sounds like he's just wants to be lazy regarding his queries. 听起来他只是想对自己的查询保持懒惰。 There's no reason at all to store information that should be laid out as tables / columns in JSON format. 完全没有理由以JSON格式存储应作为表/列布局的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM