Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#8 - Описание реляционная модели данных для аналога neo4j #8

Open
azazzze1 opened this issue Oct 21, 2024 · 2 comments

Comments

@azazzze1
Copy link
Collaborator

Необходимо расписать модель данных в соответствие со следующими пунктами:

A. Графическое представление модели (ER-диаграмма)
B. Описание назначений коллекций, типов данных и сущностей
C. Оценка объема информации, хранимой в модели (сколько потребуется памяти, чтобы сохранить объекты, как объем зависит от количества объектов - нужно выразить через переменную (количество одного из видов объектов вашей БД)). У вас должна получится формула - зависимость объема от одной переменной.
D. Избыточность модели (отношение между фактическим объемом модели и «чистым» объемом данных).. У вас должна получится формула - зависимость избыточности от одной переменной.
E. Направление роста модели при увеличении количества объектов каждой сущности.
F. Примеры хранения данных в БД для модели (два подраздела «Примеры данных»).
G. «Примеры запросов» - запросы к модели, с помощью которых реализуются сценарии использования
i. Текст запросов
ii. Количество запросов для совершения юзкейсов в зависимости от числа объектов в БД и прочих параметров
iii. Количество задействованных коллекций (если есть)

Готовое задание прикрепить в файле с разметкой markdown (,md) к данному тикету.
Дедлайн: 28 октября 2024

@azazzze1
Copy link
Collaborator Author

@azazzze1
Copy link
Collaborator Author

Реляционная СУБД

Диаграмма без названия.drawio.png

Описание назначений коллекций, типов данных и сущностей

Patient – коллекция, которая хранит в себе данные о всех зарегистрированных на сайте пользователях:

  • id : int – индификатор для обращения. Обладает свойством автоинкримента. Составной первичный ключ.
  • mail : char(255) – почта пользователя, указанная при регистрации. Обязательное поле.
  • password : char(64) – пароль от аккаунта для пользователя. Обязательное поле
  • full_name : char(100) – ФИО пользователя. Обязательное поле.
  • sex : bool – пол пользователя. True – мужской, False – женский. Необязательное поле.
  • weight : int – вес пользователя. Необязательное поле.
  • height : int – рост пользователя. Необязательное поле.

Необязательные поля указываются для сбора статистики для симптомов.

Appeal – обращение пользователя, которое нужно для сохранения истории поиска болезней пользователя:

  • id : int – индификатор для обращения. Обладает свойством автоинкримента. Первичный ключ.
  • date : datetime – точное время запроса. Дата показывается пользователю в истории. Также нужно для сбора статистики для симптомов за определённый период. Обязательное поле.
  • patient_id : int – индификатор пользователя, к которому привязано обращение. Внешний ключ. Обязательное поле.

Diaseas – список всех существующих в базе данных болезней, которые могут быть спрогнозированы системой :

  • title : char(50) – название болезни. Первичный ключ, т.к. названия болезней не повторяются.
  • description : char(500) – текст с описанием болезни. Обязательное поле.
  • recommendation : char(500) – текст с рекомендациями по лечению болезни. Обязательное поле.

Analysis – анализы, которые необходимо сдать, чтобы подтвердить наличие симптома и, соответственно, для подтверждения болезни:

  • title : char(50) – название анализа. Первичный ключ.

Анализы вынесены в отдельную коллекцию, т. к. у одного симптома может быть сразу несколько анализов для его подтверждения.

Appeal's symptoms – список симптомов, которые ввёл пользователей в рамках одного обращения, использующиеся для поиска возможных заболеваний:

  • symp_title : char(50) – название введённого пользователем симптома. Часть составного первичного ключа.
  • app_id : int – индификатор обращения. Часть составного первичного ключа.

У обращения должен быть хотя бы один симптом в данной таблице.

Symptoms – список всех существующих в базе данных симптомов:

  • symp_title : char(50) – название симптома. Первичный ключ.
  • description : char(50) – описание симптома. Обязательное поле.
  • weight : int – вес симптома. Симптомы могут иметь разный вес, который определяет, насколько симптом вероятен при заболевании. С его помощью подчитывается процент вероятности наличия заболевания по введённым симптомам. Обязательное поле.

Analysis for symptom – список анализов, которые надо провести для определения симптома:

  • symp_title : char(50) – название симптома, для которого определяем необходимые анализы. Часть составного первичного ключа.
  • analyz_title : char(50) – название анализа для определения симптома. Часть составного первичного ключа.

Каждый анализ направлен на выявление какого-то симптома, но не у каждого симптома обязан быть анализ для выявления.

Disease's symptoms – у каждой болезни есть свой набор симптомов, которые в совокупности дают 100% вероятность наличия у пользователя болезни:

  • symp_title : char(50) – название симптома. Часть составного первичного ключа.
  • dis_title : char(50) – название болезни. Часть составного первичного ключа.

У каждой болезни обязан быть набор симптомов, также как и укаждого симптома должна быть хотя бы одна болезнь, в которую он входит.

Predicted diseases – результат выполнения алгоритма, в котором хранятся болезни, вероятность наличия которых у пользователя ненулевая:

  • dis_title : char(50) – название болезни. Часть составного первичного ключа.
  • app_id : int – индификатор обращения. Часть составного первичного ключа.
  • risk : int – процент, который показывает, какова вероятность наличия болезни у пользователя. Составляется по формуле: risk = (Вес выбранных пользователем симптомов) \ (Вес симптомов у вероятной болезни) * 100.

Оценка объема информации, хранимой в модели

Аналогично нереляционной модели предположим, что

  • пользователь будет создавать в среднем 7 обращений
  • каждый симптом будет иметь в среднем один анализ для своего подтверждения
  • каждая болезнь будет иметь в среднем по 5 симптомов
  • в каждом обращении будет в среднем по 5 симптомов
  • каждое обращение будет прогнозировать с среднем 10 болезней

Будем считать, что каждый символ у нас занимает 2 байта в связи с использованием русского языка.

Рассмотрим объём информации для каждого объекта сущности:

Patien

  • id : int – 4 Байта
  • mail : char(255) – 510 Байта
  • password : char(64) – 128 Байт
  • full_name : char(100) – 200 Байт
  • sex : bool – 1 Байт
  • age : int – 4 Байта
  • weight : int – 4 Байта
  • height : int – 4 Байта

Всего: 855 Байт

Appeal

  • id : int – 4 Байта
  • date : datetime – 8 Байт
  • patient_id : int – 4 Байта

Всего: 16 Байт

Diaseas

  • title : char(50) – 100 Байт
  • description : char(500) – 1000 Байт
  • recommendation : char(500) – 1000 Байт

Всего: 2100 Байт

Analysis

  • title : char(50) – 100 Байт

Всего: 100 Байт

Appeal's symptoms

  • symp_title : char(50) – 100 Байт
  • app_id : int – 4 Байта

Всего: 104 Байта

Symptoms

  • symp_title : char(50) – 100 Байт
  • description : char(500) – 1000 Байт
  • weight : int – 4 Байта

Всего: 1104 Байта

Analysis for symptom

  • symp_title : char(50) – 100 Байт
  • analyz_title : char(50) – 100 Байт

Всего: 200 Байт

Disease's symptoms

  • symp_title : char(50) – 100 Байт
  • dis_title : char(50) – 100 Байт

Всего: 200 Байт

Predicted diseases

  • dis_title : char(50) – 100 Байт
  • app_id : int – 4 Байта
  • risk : smallint – 2 Байта

Всего: 106 Байт

Таблица 2

Label Количество Размер (в байтах)
Patient N 855 * N
Appeal 7 * N 126 * N
Symptom 133 146832
Disease 41 86100
Analysis 133 13300
Analysis for symptom 133 26600
Disease's symptoms 133 26600
Predicted diseases 7 * N * 10 7420 * N
Appeal's symptoms 7 * N * 5 3640 * N

Таким образом, общий объём в зависимости от количества пользователей будет выглядеть следующим образом:

$$ v'_{clean}(N) = 12041 * N + 299432 $$

Избыточность модели

В качестве альтернативы neo4j в СУБД возьмём PostgreSQL. В данной БД каждая таблица хранится в отдельном файле, которые называют страницей. Объём одной такой страницы равен 8192 Байта. Таким образом, необходимо прибавить это значение для каждой таблицы (всего их 9). Также каждая строка в таблице имеет свои метаданные:

  • Заголовок – 23 Байта
  • Строковой указатель – 2 Байта
  • Смещение данных для выравнивания столбцов, в среднем – 4 Байта на строку

Следовательно, для каждой строки мы также прибавляем 29 Байтов.

Формула оценки избыточности будет выглядеть так:

$$
\frac{v'{common}}{v'{clean}} = \frac{(12041 + 116) * N + 299432 + 73728 + 16617}{12041 * N + 299432} = \frac{12157 * N + 389777}{12041 * N + 299432}
$$

загруженное.png

По графику видно, что с ростом количества пользователей, разница между чистыми данными и полным объёмом будет уменьшаться. Это связано с тем, что трата на размер листа остаётся постоянной, а объём метаданных строки становится мал по сравнению с весом чистых данных.

Направление роста модели при увеличении количества объектов каждой сущности

Patient

Увеличение количества строк приводит к линейному росту, равному собственному размеру данной сущности.

f(n) = 855*n Байт

Appeal

Увеличение количества строк приводит к созданию новых связей в таблицах Appeal's symptoms и Predicted diseases. В худшем случае, пользователь введёт все симптомы, которые будут характеризовать все заболевания.

f(n) = (16 + 133104 + 41106 ) * n = 18194*n Байт

Symptoms

Увеличение количества строк приводит к созданию новых связей в таблице Disease's symptoms. В худшем случае, симптом будет у всех болезней.

f(n) = (1104 + 41200) * n = 9304n Байт

Analysis

Увеличение количества строк приводит к созданию новых связей в таблице Analysis for symptom. В худшем случае, анализ будет необходим для выявления всех симптомов.

f(n) = (100 + 133200) * n = 26700n Байт

При это метаданные будут расти согласно этой функции для каждой из таблиц:

f(n) = 29*n Байт

Примеры хранения данных в БД для модели

image.png

Пример хранения данных в БД

INSERT INTO Patient (mail, password, full_name, sex, weight, height) VALUES
('user1@example.com', 'password1', 'John Doe', TRUE, 70, 180),
('user2@example.com', 'password2', 'Jane Smith', FALSE, 60, 170);

INSERT INTO Appeal (date, patient_id) VALUES
(NOW(), 11),
(NOW(), 12);

INSERT INTO Disease (title, description, recommendation) VALUES
('Flu', 'Common cold symptoms', 'Rest and hydration'),
('Covid-19', 'Fever, cough, shortness of breath', 'Isolation and medical attention');

-- Вставка тестовых данных в таблицу Analysis
INSERT INTO Analysis (title) VALUES
('Blood Test'),
('X-Ray');

-- Вставка тестовых данных в таблицу Symptom
INSERT INTO Symptom (symp_title, description, weight) VALUES
('Fever', 'High body temperature', 50),
('Cough', 'Persistent cough', 30);

select * from symptom
select * from patient

Вывод данных из таблицы Symptom

title description weight
Fever High body temperature 5
Cough Persistent cough 3

Вывод данных из таблицы Patient

id mail password full_name sex weight height
11 user1@example.com password1 John Doe true 70 180
12 user2@example.com password2 Jane Smith false 60 170

Примеры запросов

Регистриция пользователя

INSERT INTO Patient (mail, password, full_name, sex, weight, height) VALUES
('user1@example.com', 'password1', 'John Doe', TRUE, 70, 180);

Количество запросов для совершения UseCase: 1

Количество задействованных коллекций: 1

Создание обращения

INSERT INTO Appeal (id, date, patient_id) VALUES
(17, NOW(), 11);

insert into appealsymptom (symp_title, app_id) values
('Fever', 17),
('Cough', 17);

Количество запросов для совершения UseCase: 2

Количество задействованных коллекций: 2

Получение статистики распространённости симптома среди пациентов

SELECT a.*
FROM Appeal a
JOIN Patient p ON a.patient_id = p.id
WHERE a.date > '2023-05-20' AND a.date < '2023-05-27' AND p.sex = TRUE;

Количество запросов для совершения UseCase: 1

Количество задействованных коллекций: 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant