Skip to content

Модель данных

Кардаш Ярослав edited this page Oct 26, 2024 · 46 revisions

Нереляционная модель

Графическое представление модели

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


Коллекция Announcement

Назначение

Хранинеие информации об объявлениях

{
    "title": "Announcement",
    "description": "Коллекция объявлений",
    "type": "object",
    "properties": { 
        "creation_date": {
            "description": "Дата публикации",
            "type": "number"
        },
        "content": {
            "description": "Содержимое объявления",
            "type": "string"
        },
        "tag": {
            "description": "Ассоциированный тэг",
            "type": "string"
        }
    },
    "required": ["creation_date", "content", "tag"]
}

Суммарный объем данных: 530 байт.


Коллекция Comment

Назначение

Хранение информации о комментариях к объявлениям

{
    "title": "Comment",
    "description": "Коллекция комментариев",
    "properties": { 
        "creation_date": {
            "description": "Дата создания",
            "type": "number"
        },
        "content": {
            "description": "Содержимое комментария",
            "type": "string"
        }
    },
    "required": ["creation_date", "content"]
}

Суммарный объем данных: 241 байт.


Коллекция Group

Назначение

Хранение информации о группах

{
    "title": "Group",
    "description": "Коллекция групп",
    "properties": { 
        "name": {
            "description": "Название группы",
            "type": "string"
        },
        "creation_date": {
            "description": "Дата создания",
            "type": "number"
        },
        "last_edit_date": {
            "description": "Дата последнего изменения",
            "type": "number"
        },
        "avatar_uri": {
            "description": "Ссылка на аватар",
            "type": "string"
        },
        "genres": {
            "description": "Список жанров группы",
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true
        }
    },
    "required": ["name", "creation_date", "last_edit_date", "avatar_uri", "genres"]
}

Суммарный объем данных: 348 байт.


Коллекция Place

Назначение

Хранение информации о местах

{
    "title": "Place",
    "description": "Коллекция мест",
    "properties": { 
        "user_id" : {
            "description": "Идентификатор пользователя-создателя",
            "type": "string"
        },
        "name": {
            "description": "Название места",
            "type": "string"
        },
        "creation_date": {
            "description": "Дата создания",
            "type": "number"
        },
        "last_edit_date": {
            "description": "Дата последнего изменения",
            "type": "number"
        },
        "avatar_uri": {
            "description": "Ссылка на аватар",
            "type": "string"
        },
        "type": {
            "description": "Тип места",
            "type": "string"
        },
        "address": {
            "description": "Адрес места",
            "type": "string"
        },
        "phone_number": {
            "description": "Контактный номер",
            "type": "string"
        },
        "area": {
            "description": "Площадь",
            "type": "number"
        },
        "equipment": {
            "description": "Список оборудования",
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "description": "Название оборудования",
                        "type": "string"
                    },
                    "amount": {
                        "description": "Количество оборудования",
                        "type": "number"
                    }
                },
                "required": ["name", "amount"]
            },
            "uniqueItems": true
        }
    },
    "required": ["user_id", "name", "creation_date", "last_edit_date", "avatar_uri", "type", "address", "phone_number", "area", "equipment"]
}

Суммарный объем данных: 1572 байт.


Коллекция ProducerAnnouncement

Назначение

Хранение информации об отношениях между создателями объявлений и объявлениями

{
    "title": "ProducerAnnouncement",
    "description": "Коллекция отношений между создателями объявлений и объявляениями"
}

Суммарный объем данных: 66 байт.


Коллекция Stars

Назначение

Хранение информации о поставленных звездах

{
    "title": "Stars",
    "description": "Коллекция звезд"
}

Суммарный объем данных: 41 байт.


Коллекция Static

Назначение

Хранение информации о статичных данных

{
    "title": "Static",
    "description": "Коллекция статичных данных",
    "properties": { 
        "equipment" : {
            "description": "Список доступного оборудования",
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true
        },
        "tags" : {
            "description": "Список доступных тегов",
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true
        },
        "talents" : {
            "description": "Список доступных талантов",
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true
        },
        "genres" : {
            "description": "Список доступных жанров",
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true
        }
    },
    "required": ["equipment", "tags", "talents", "genres"]
}

Суммарный объем данных: 8200 байт.


Коллекция User

Назначение

Хранение информации о пользователе

{
    "title": "User",
    "description": "Коллекция пользователей",
    "properties": { 
        "first_name": {
            "description": "Имя пользователя",
            "type": "string"
        },
        "last_name": {
            "description": "Фамилия пользователя",
            "type": "string"
        },
        "creation_date": {
            "description": "Дата создания",
            "type": "number"
        },
        "last_edit_date": {
            "description": "Дата последнего изменения",
            "type": "number"
        },
        "avatar_uri": {
            "description": "Ссылка на аватар",
            "type": "string"
        },
        "talents": {
            "description": "Список жанров группы",
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true
        }
    },
    "required": ["first_name", "first_name", "creation_date", "last_edit_date", "avatar_uri", "talents"]
}

Суммарный объем данных: 492 байт.


Коллекция UserGroup

Назначение

Хранение информации об отношениях между пользователями и группами

{
    "title": "UserGroup",
    "description": "Коллекция отношений между пользователями и группами",
    "properties": { 
        "join_date": {
            "description": "Дата присоединения пользователя к группе",
            "type": "number"
        }
    }
    "required": ["join_date"]
}

Суммарный объем данных: 32 байта.


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

В качестве переменной используется количество пользователей $U$.

Таблица Static не зависит от числа пользователей, хранится в единственном экземпляре и имеет размер 8200 байт.

Количество групп выразим через количество пользователей как $G = 0.6U$.

Для каждого пользователя приходится в среднем 2 таланта, 30 объявлений, 500 звезд суммарно, 50 комментариев, 2 места. У каждого места в среднем по 10 различных видов оборудования.

Для каждой группы приходится 30 объявлений и 2 жанра.

Тогда примерный объем модели можно выразить следующей формулой:

$V(U) = 8200 + U \cdot (492 + 30 \cdot (66 + 530) + 500 \cdot 41 + 50 \cdot 241 + 2 \cdot 1572) + 0.6 \cdot U \cdot (348 + 30 \cdot (66 + 530) + 32) = 8200 + 65022 \cdot U \text{ байт}$

Избыточность данных

Избытычность заключается в следующем:

  • В разных группах могут быть записаны одни и те же жанры
  • В разных местах может быть записано одно и то же оборудование
  • У разных пользователей могут быть записаны одни и те же таланты
  • Теги объявлений могут быть закодированы числом

Коэффицент избыточности:

$K = { 65022 \over 63998 } \cdot U = 1.016 \cdot U$

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

  1. Если растет количество документов, то растет число вершин в графе.
  2. Если растет количество связей между документами, то связность графа увеличивается.

Примеры данных

Коллекция User

[
  {
    "_key": "4769",
    "_id": "User/4769",
    "_rev": "_ioED4LW---",
    "first_name": "Andrey",
    "last_name": "Babenko",
    "creation_date": "2021-01-01",
    "last_edit_date": "2022-01-01",
    "avatar_uri": "assets/avatars/andrey.png",
    "talents": [
      "electric-guitar"
    ]
  },
  {
    "_key": "477",
    "_id": "User/477",
    "_rev": "_ioTzDnK---",
    "first_name": "Thomas",
    "last_name": "York",
    "creation_date": "2020-01-01",
    "last_edit_date": "2024-10-19T15:46:07.123Z",
    "avatar_uri": "assets/avatars/thomas-new.png",
    "talents": [
      "vocal",
      "acoustic-guitar",
      "electric-guitar"
    ]
  },
  {
    "_key": "863",
    "_id": "User/863",
    "_rev": "_ioDTZXm---",
    "first_name": "Egor",
    "last_name": "Letov",
    "creation_date": "2021-01-01",
    "last_edit_date": "2022-01-01",
    "avatar_uri": "assets/avatars/egor.png",
    "talents": [
      "vocal",
      "acoustic-guitar",
      "electric-guitar",
      "drums"
    ]
  }
]

Коллекция Announcement

[
  {
    "_key": "1553",
    "_id": "Announcement/1553",
    "_rev": "_ioDb1Ru---",
    "content": "Сегодня концерт!",
    "creation_date": "2024-10-18",
    "tag": "concert"
  },
  {
    "_key": "1593",
    "_id": "Announcement/1593",
    "_rev": "_ioDcOf2---",
    "content": "Пьяных не пускаем, даже по причине пятницы!",
    "creation_date": "2024-10-18",
    "tag": "concert"
  }
]

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

Текст запросов

  1. Самая популярная группа
FOR g in Group
  LET stars_amount = (
    FOR s IN Stars
      FILTER s._to == g._id
      COLLECT WITH COUNT INTO amount
      RETURN amount
  )[0]
  SORT stars_amount DESC
  LIMIT 1
  RETURN {
    _id: g._id,
    name: g.name,
    stars_amount: stars_amount
  }
  1. Места с типом "Концертная точка"
FOR p IN Place
  FILTER p.type == "Концертная точка"
  RETURN p
  1. Редактирование данных профиля пользователем
LET key = PARSE_IDENTIFIER("User/477").key
UPDATE key
WITH { 
  first_name: "Thomas",
  last_name: "York",
  last_edit_date: DATE_FORMAT(DATE_NOW(), "%yyyy-%mm-%ddT%hh:%ii:%ss.%fffZ"),
  avatar_uri: "assets/avatars/thomas-new.png"
} 
IN User
RETURN NEW
  1. Записи с тегом "концерт" (в порядке уменьшения звезд на них)
FOR a in Announcement
  LET stars_amount = (
    FOR s IN Stars
      FILTER s._to == a._id
      COLLECT WITH COUNT INTO amount
      RETURN amount
  )[0]
  SORT stars_amount DESC
  RETURN MERGE(a, {
    stars_amount: stars_amount
  })
  1. Все анонсы пользователя
FOR pa IN ProducerAnnouncement
  FILTER pa._from == @userId
  FOR a IN Announcement
    FILTER pa._to == a._id
    RETURN a
  1. Все комментарии пользователя
FOR c IN Comments
  FILTER c._from == @userId
  RETURN c
  1. Все авторы комментариев к определенному анонсу
FOR a IN Announcement
  FILTER a._id == @ann_id
  FOR c IN Comment
    FILTER c._to == a._id 
    FOR u IN User
      FILTER c._from == u._id
      RETURN u
  1. Все группы, чьи пользователи поставили звезду на определенный анонс
FOR s IN Star
  FILTER s._to == @ann_id
  FOR ug IN UserGrop
    FILTER ug._from == s._from
    FOR g in Group
      FILTER ug._to == g._id
      RETURN g

Реляционная модель

Графическое представление модели

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


Таблица User

Назначение

Информация о пользователе

Типы данных

  • id: INT NOT NULL
  • first_name: VARCHAR
  • last_name: VARCHAR
  • creation_data: DATETIME
  • last_edit_date: DATETIME
  • avatar_uri: VARCHAR

Суммарный объем данных: 785 байт.


Таблица UserStars

Назначение

Информация о полученных звездах пользователя

Типы данных

  • source_user_id: INT NOT NULL
  • destination_user_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица UserTalent

Назначение

Информация о музыкальных талантах пользователя

Типы данных

  • user_id: INT NOT NULL
  • talent_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица UserGroup

Назначение

Информация о группе, в которой состоит пользователь

Типы данных

  • user_id: INT NOT NULL
  • group_id: INT NOT NULL
  • join_date: DATETIME

Суммарный объем данных: 16 байт.


Таблица UserAnnouncement

Назначение

Информация об объявлении, которое получает пользователь

Типы данных

  • user_id: INT NOT NULL
  • announcement_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица Talent

Назначение

Информация о музыкальном таланте

Типы данных

  • id: INT NOT NULL
  • name: VARCHAR

Суммарный объем данных: 259 байт.


Таблица Group

Назначение

Информация о группе

Типы данных

  • id: INT NOT NULL
  • name: VARCHAR
  • creation_date: DATETIME
  • last_edit_date: DATETIME
  • avatar_uri: VARCHAR

Суммарный объем данных: 530 байт.


Таблица GroupAnnouncement

Назначение

Информация об объявлении группы

Типы данных

  • group_id: INT NOT NULL
  • announcement_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица GroupStars

Назначение

Информация о полученных звездах группы

Типы данных

  • source_user_id: INT NOT NULL
  • destination_group_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица GroupGenre

Назначение

Информация о жанрах группы

Типы данных

  • group_id: INT NOT NULL
  • genre_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица Genre

Назначение

Информация о всех жанрах

Типы данных

  • id: INT NOT NULL
  • name: VARCHAR

Суммарный объем данных: 259 байт.


Таблица Announcement

Назначение

Информация об объявлении

Типы данных

  • id: INT NOT NULL
  • tag_id: INT NOT NULL
  • content: VARCHAR
  • creation_date: DATETIME

Суммарный объем данных: 271 байт.


Таблица AnnouncementStars

Назначение

Информация о звездах объявление

Типы данных

  • source_user_id: INT NOT NULL
  • destination_announcement_id: INT NOT NULL

Суммарный объем данных: 8 байт.


Таблица Comment

Назначение

Информация о комментарии

Типы данных

  • id: INT NOT NULL
  • user_id: INT NOT NULL
  • announcement_id: INT NOT NULL
  • content: VARCHAR
  • creation_date: DATETIME

Суммарный объем данных: 275 байт.


Таблица Tag

Назначение

Информация о теге

Типы данных

  • id: INT NOT NULL
  • name: VARCHAR

Суммарный объем данных: 259 байт.


Таблица Place

Назначение

Информация о месте, репточке

Типы данных

  • id: INT NOT NULL
  • user_id: INT NOT NULL
  • name: VARCHAR
  • creation_date: DATETIME
  • last_edit_date: DATETIME
  • type: VARCHAR
  • address: VARCHAR
  • phone_number: VARCHAR
  • area: DOUBLE

Суммарный объем данных: 1052 байт.


Таблица Equipment

Назначение

Информация об оборудовании

Типы данных

  • id: INT NOT NULL
  • name: VARCHAR

Суммарный объем данных: 259 байт.


Таблица PlaceEquipment

Назначение

Информация об оборудовании, доступном на репитиционных точках

Типы данных

  • place_id: INT NOT NULL
  • equipment_id: INT NOT NULL
  • amount: INT

Суммарный объем данных: 12 байт.


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

В качестве переменной используется количество пользователей $U$.

Таблицы Tag, Talent, Equipment и Genre не зависят от числа пользователей (имеют 50, 20, 20 и 20 объектов соответственно) и имеют размеры 12950 байт, 5180 байт, 5180 байт и 5180 соответственно.

Количество групп выразим через количество пользователей как $G = 0.6U$.

Для каждого пользователя приходится в среднем 2 таланта, 30 объявлений, 500 звезд суммарно, 50 комментариев, 2 места. У каждого места в среднем по 10 различных видов оборудования.

Для каждой группы приходится 30 объявлений и 2 жанра.

Тогда примерный объем модели можно выразить следующей формулой:

$V(U) = 12950 + 5180 + 5180 + 5180 + U \cdot (785 + 2 \cdot 8 + 30 \cdot (8 + 271) + 500 \cdot 8 + 50 \cdot 275 + 2 \cdot (1052 + 10 * 12)) + 0.6 \cdot U \cdot (530 + 30 \cdot (8 + 271) + 2 * 8) = 28490 + 34560 \cdot U \text{ байт}$

Избыточность данных

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

Примеры данных

Таблица User

id first_name last_name creation_date last_edit_date avatar_url
1 Victor Tsoy 1982-06-06 00:00:00 1990-08-15 00:00:00 tsoy.png
2 Egor Letov 1982-11-11 00:00:00 2008-02-19 00:00:00 letov.png

Таблица Announcement

id tag_id content creation_date
123 1234 Сегодня концерт! 2024-10-18 00:00:00
124 1234 Пьяных не пускаем, даже по причине пятницы! 2024-10-18 00:00:00

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

Текст запросов

  1. Самая популярная группа
SELECT g.id, g.name, COUNT(gs.source_user_id) AS star_count
FROM Group g
LEFT JOIN GroupStars gs ON g.id = gs.destination_group_id
GROUP BY g.id, g.name
ORDER BY star_count DESC
LIMIT 1;
  1. Места с типом "Концертная точка"
SELECT *
FROM Places
WHERE type = "Концертная точка"
  1. Редактирование данных профиля пользователем
UPDATE User
SET
    first_name = NEW.first_name,
    last_name = NEW.last_name,
    creation_date = NEW.creation_date,
    last_edit_date = now(),
    avatar_url = NEW.avatar_url
WHERE id = NEW.id;
  1. Записи с тегом "концерт" (в порядке уменьшения звезд на них)
SELECT a.*, COUNT(as.id) AS star_count
FROM Announcements a
LEFT JOIN AnnouncementsStars as ON a.id = as.destination_announcements_id
WHERE a.tag_id = (SELECT id FROM Tags WHERE tag_name = 'концерт')
GROUP BY a.id
ORDER BY star_count DESC;
  1. Все объявления пользователя
SELECT Announcement.* FROM Announcement
JOIN UserAnnouncement ON Announcement.id = UserAnnouncement.announcement_id
WHERE UserAnnouncement.user_id = 0;
  1. Все комментарии пользователя
SELECT * FROM Comments
WHERE user_id = 0;
  1. Все авторы комментариев к определенному объявлению
SELECT DISTINCT User.* FROM User
JOIN Comment ON User.id = Comment.user_id
WHERE Comment.announcement_id = 0;
  1. Все группы, чьи пользователи поставили звезду к заданному объвлению
SELECT DISTINCT Group.* FROM Group
JOIN UserGroup ON UserGroup.group_id = Group.id
JOIN AnnouncementStars ON UserGroup.user_id = AnnouncementStars.source_user_id
WHERE AnnouncementStars.destination_announcement_id = 1;

Сравнение моделей

Удельный объем информации

NoSQL - 8200 + 65022 * U байт.

SQL - 28490 + 34560 * U байт.

NoSQL будет требовать значительно больше памяти, чем SQL-решение.

Запросы по отдельным юзкейсам

Количество запросов для совершения юзкейсов в зависимости от числа объектов в БД и прочих параметров

1. Самая популярная группа

  • NoSQL - 2 запроса.
  • SQL - 1 запрос.

2. Места с типом "Концертная точка"

  • NoSQL - 1 запрос.
  • SQL - 1 запрос.

3. Редактирование данных профиля пользователем.

  • NoSQL - 1 запрос.
  • SQL - 2 запроса.

4. Записи с тегом "концерт" (в порядке уменьшения звезд на них)

  • NoSQL - 2 запроса.
  • SQL - 1 запрос.

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

1. Самая популярная группа

  • NoSQL - 2 коллекции.
  • SQL - 2 таблицы.

2. Места с типом "Концертная точка"

  • NoSQL - 1 коллекция.
  • SQL - 1 таблица.

3. Редактирование данных профиля пользователем.

  • NoSQL - 1 коллекция.
  • SQL - 2 таблицы.

4. Записи с тегом "концерт" (в порядке уменьшения звезд на них)

  • NoSQL - 2 коллекции.
  • SQL - 2 таблицы.

Вывод

  • Удобнее использовать NoSQL так как необходимо реализовывать множество связей "многие ко многим".
  • NoSQL требует значительно больше памяти, чем SQL-решение.
  • Количество запросов и задействованных коллекций в NoSQL и SQL примерно равны.
Clone this wiki locally