База данных моделирования энергетической системы MySQL EAV Design - PullRequest
0 голосов
/ 04 мая 2018

Мы разрабатываем схему базы данных для проекта оптимизации энергосистемы с открытым исходным кодом.

Мы используем модель EAV, потому что хотим, чтобы она была гибкой и позволяла определять проблемы с помощью данных. То есть мы хотим иметь возможность создавать новые классы объектов и связанные с ними параметры данных на лету без необходимости изменять структуру базы данных.

Модель будет реализована в Julia JuMP, и мы будем запрашивать данные через sql. Будет интерфейс с Джулией для доступа к данным через SQL и графический интерфейс в PyQT для просмотра, редактирования, фильтрации данных.

Я дал SQL для текущей схемы ниже.

Идея довольно проста ... и таблица object_class для определения типов объектов. Таблица объектов для определения экземпляров объектов и таблица параметров_определения для определения параметров, которые могут быть связаны с объектами каждого типа, и таблица параметров для определения фактических значений параметров, связанных с экземплярами объектов. Давайте на время забудем об отношениях, чтобы обсуждение было простым. Также я пропустил поля id, которые мы будем включать.

Таблица параметров немного нюансов, потому что наши модели оптимизации являются хронологическими моделями, которые работают с течением времени - поэтому очень часто иметь изменяющиеся во времени данные. Чтобы справиться с этим, мы можем дать «time_pattern» значению данных. Также у наших моделей будут сценарии. В таблице параметров мы можем установить это значение, чтобы указать, что значение параметра применяется к конкретному сценарию. Значение NULL в поле сценария указывает элемент данных «базовый случай».

Теперь самое главное ... член команды решил заменить таблицу параметров полем JSON в таблице объектов. Он убежден, что это лучше, потому что все данные для объекта содержатся в нем, и он избегает нулей, которые мы будем иметь в таблице параметров, когда не указан временной шаблон или сценарий. Однако у меня есть ряд проблем с этим: 1. мы теряем ссылочную целостность между таблицей параметров и таблицей определения параметров. Я знаю, что вы можете ссылаться на поля JSON, но разве это не неэффективно? 2. Может быть некоторая заслуга в идее, если мы предположим, что у каждого объекта может быть список статических параметров (т. Е. Не определен time_pattern или сценарий. Однако, когда они определены, нам нужно иметь вложенные JSON в Поле JSON таблицы объектов. Можем ли мы присоединиться к этому? 3. Из того, что я прочитал, не рекомендуется скрывать какие-либо поля, по которым вы можете запрашивать внутри поля JSON. Это правильно? 4. Можно ли вообще объединять поля внутри вложенных JSON и если это возможно, неэффективно ли это? 5. Даже если вы можете запрашивать и объединять поля, скрытые во вложенном JSON, разве SQL не будет сложным без реальной выгоды?

На первый взгляд, единственное преимущество в том, что вы избавляетесь от одного стола, который может упростить некоторые вызовы. Однако вы просто закапываете данные этой таблицы в поле JSON в другой таблице

Я что-то упустил? Есть ли у этого предложения какие-то преимущества, которые я не получаю?

Так как данные будут массово запрашиваться Джулией, этот элемент, вероятно, не имеет значения, 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;

1 Ответ

0 голосов
/ 05 мая 2018

Вы можете использовать функцию

common_schema.extract_json_value(json_data,'title')

Для запроса JSON в столбцах, но, как я уже сказал выше, он неэффективен и исключает использование индексов / всего того, что делает использование SQL мощным. Похоже, он просто хочет быть ленивым в отношении своих запросов. Нет никакой причины хранить информацию, которая должна быть представлена ​​в виде таблиц / столбцов в формате JSON.

...