-
Notifications
You must be signed in to change notification settings - Fork 0
Модель данных

Users:
reviews:
authorId: objectId, V = 12b
authorName: string, V = 30b
score: int (int64), V = 8b
content: string, V = 200b
createdAt: timestamp, 8b
Итого: 12 + 30 + 8 + 200 + 8 = 258b
profiles:
role: enum, V = 15b
rating: double, V = 8b
description: string, V = 500b
createdAt: timestamp, 8b
updatedAt: timestamp, 8b
reviews: array[object], V = NR ⋅ 258b, где NR – количество отзывов
Итого: 15 + 8 + 500 + 8 + 8 + NR ⋅ 258 = (539 + NR ⋅ 258)b
В среднем на профиль приходится 10 отзывов, тогда V = 3119b
users:
_id: objectId, V = 12b
displayName: string, V = 30b
email: string, V = 30b
password: string, V = 60b
balance: int (int64), V = 8b
systemRole: enum, V = 10b
profiles: array[object], V = NP ⋅ 3119b, где NP – количество профилей. NP = 2 (фрилансер и заказчик), поэтому V = 6238b
active: bool, V = 1b
createdAt: timestamp, 8b
updatedAt: timestamp, 8b
Фактический объём коллекции users: 12 + 30 + 30 + 60 + 8 + 10 + 6238 + 1 + 8 + 8 = 6405b
Orders:
statuses:
title: enum, V = 15b
content: string, V = 100b
createdAt: timestamp, 8b
Итого: 15 + 100 + 8 = 123b
responses:
freelancerName: string, V = 30b
freelancerId: objectId, V = 12b
chatId: objectId, V = 12b
coverLetter: string, V = 500b
active: bool, V = 1b
createdAt: timestamp, 8b
updatedAt: timestamp, 8b
Итого: 30 + 12 + 12 + 500 + 1 + 8 + 8 = 571b
orders:
_id: objectId, V = 12b
clientId: objectId, V = 12b
title: string, 50b
description: string, 1000b
completionTime: int (int64), V = 8b
cost: int (int64), V = 8b
active: bool, V = 1b
responses: array[object], V = NRes ⋅ 571b, где NRes – количество откликов. В среднем NRes = 5, поэтому V = 2855b
freelancerId: objectId, V = 12b
budget: int (int64), V = 8b
statuses: array[object], V = NS ⋅ 123b, где NS – количество статусов. В среднем NS = 5, поэтому V = 615b
createdAt: timestamp, 8b
updatedAt: timestamp, 8b
Фактический объём коллекции orders: 12 + 12 + 50 + 1000 + 8 + 8 + 1 + 2855 + 12 + 8 + 615 + 8 + 8 = 4597b
Chats:
client:
id: objectId, V = 12b
publicName: string, V = 30b
Итого: 12 + 30 = 42b
messages:
createdAt: timestamp, 8b
sender: enum, V = 15b
content: string, V = 500b
Итого: 8 + 15 + 500 = 523b
freelancer:
id: objectId, V = 12b
publicName: string, V = 30b
Итого: 12 + 30 = 42b
chats:
_id: objectId, V = 12b
client: object, V = 42b
orderId: objectId, V = 12b
active: bool, V = 1b
freelancer: object, V = 42b
createdAt: timestamp, 8b
updatedAt: timestamp, 8b
messages: array[object], V = NM ⋅ 523b, где M – количество сообщений. В среднем NM = 50, поэтому V = 26150b
Фактический объём коллекции chats: 12 + 42 + 12 + 1 + 42 + 8 + 8 + 26150 = 26275b
Фактический объём модели: NU ⋅ 6405 + NO ⋅ 4597 + NC ⋅ 26275, где NU – количество пользователей, NO – количество заказов, NC – количество чатов.
Выразим всё через количество заказов: на 1 заказ в среднем приходится 0.5 пользователей (так как заказчики размещают и фрилансеры выполняют более одного заказа) и в среднем 3 чата (считая чаты откликов), поэтому:
V(NO) = (86625 ⋅ NO)bytes
Для вычисления «чистого» объёма данных исключим из расчетов дублирующуюся и служебную информацию, тогда:
Users:
reviews:
score: int (int64), V = 8b
content: string, V = 200b
Итого: 200 + 8 = 208b
profiles:
role: enum, V = 15b
rating: double, V = 8b
description: string, V = 500b
reviews: array[object], V = NR ⋅ 208b, где NR – количество отзывов, в среднем NR = 10
Итого: 15 + 8 + 500 + 10 ⋅ 208 = 2603b
users:
displayName: string, V = 30b
email: string, V = 30b
password: string, V = 60b
balance: int (int64), V = 8b
systemRole: enum, V = 10b
profiles: array[object], V = NP ⋅ 2603b, где NP – количество профилей. NP = 2 (фрилансер и заказчик), поэтому V = 5206b
«Чистый» объём коллекции users: 30 + 30 + 60 + 8 + 10 + 5206 = 5344b
Orders:
statuses:
title: enum, V = 15b
content: string, V = 100b
Итого: 115b
responces:
coverLetter: string, V = 500b
Итого: 500b
orders:
title: string, 50b
description: string, 1000b
completionTime: int (int64), V = 8b
cost: int (int64), V = 8b
responses: array[object], V = NRes ⋅ 500b, где NRes – количество откликов. В среднем NRes = 5, поэтому V = 2500b
budget: int (int64), V = 8b
statuses: array[object], V = NS ⋅ 115b, где NS – количество статусов. В среднем NS = 5, поэтому V = 575b
«Чистый» объём коллекции orders: 50 + 1000 + 8 + 8 + 2500 + 8 + 575 = 4149b
Chats:
messages:
sender: enum, V = 15b
content: string, V = 500b
Итого: 515b
chats:
messages: array[object], V = NM ⋅ 515b, где NM – количество сообщений. В среднем NM = 50, поэтому V = 25750b
«Чистый» объём коллекции chats: 25750b
«Чистый» объём данных: NU ⋅ 5344 + NO ⋅ 4149 + NC ⋅ 25750, где NU – количество пользователей, NO – количество заказов, NC – количество чатов.
Выразим всё через количество заказов:
Vc(NO) = (84071 ⋅ NO)bytes
Избыточность:
R(NO) = V(NO) / Vc(NO) = 86625 ⋅ NO / 84071 ⋅ NO = 1.03
При увеличении количества объектов любой из сущностей модель будет расти линейно.
{
"_id": ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"),
"displayName": "Иван Иванов",
"email": "ivanov@example.com",
"password": "hash1",
"balance": 1000,
"systemRole": "user",
"profiles": [
{
"role": "client",
"rating": 4.5,
"description": "Заказчик Иван",
"createdAt": ISODate("2023-10-01T10:00:00Z"),
"updatedAt": ISODate("2023-10-01T10:00:00Z"),
"reviews": []
}
],
"active": true,
"createdAt": ISODate("2023-10-01T10:00:00Z"),
"updatedAt": ISODate("2023-10-01T10:00:00Z")
}
{
"_id": ObjectId("64a1b2c3d4e5f6a7b8c9d0e2"),
"clientId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"),
"title": "Разработка сайта",
"description": "Создание лендинга",
"completionTime": 1000000000,
"cost": 1000,
"active": true,
"responses": [
{
"freelancerName": "Петр Петров",
"freelancerId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e3"),
"chatId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e4"),
"coverLetter": "Готов взяться на проект!",
"active": true,
"createdAt": ISODate("2023-10-01T10:00:00Z"),
"updatedAt": ISODate("2023-10-01T10:00:00Z")
}
],
"freelancerId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e3"),
"budget": 1000,
"statuses": [
{
"title": "beginning",
"content": "Заказ создан",
"createdAt": ISODate("2023-10-01T10:00:00Z")
}
],
"createdAt": ISODate("2023-10-01T10:00:00Z"),
"updatedAt": ISODate("2023-10-01T10:00:00Z")
}\
{
"_id": ObjectId("64a1b2c3d4e5f6a7b8c9d0e4"),
"client": {
"id": ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"),
"publicName": "Иван Иванов"
},
"orderId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e2"),
"active": true,
"freelancer": {
"id": ObjectId("64a1b2c3d4e5f6a7b8c9d0e3"),
"publicName": "Петр Петров"
},
"createdAt": ISODate("2023-10-01T10:00:00Z"),
"updatedAt": ISODate("2023-10-01T10:00:00Z"),
"messages": [
{
"createdAt": ISODate("2023-10-01T10:00:00Z"),
"sender": "client",
"content": "Здравствуйте!"
},
{
"createdAt": ISODate("2023-10-01T10:05:00Z"),
"sender": "freelancer",
"content": "Добрый день!"
}
]
}
Основной сценарий:
Проверка уникальности email:
db.users.findOne({ email: "ivanov@example.com" });
- Количество запросов: 1
-
Задействованные коллекции:
users
Создание нового пользователя:
db.users.insertOne({
displayName: "Иван Иванов",
email: "ivanov@example.com",
password: "hash1",
balance: 1000,
systemRole: "user",
profiles: [
{
role: "client",
rating: 4.5,
description: "Заказчик Иван",
createdAt: new Date(),
updatedAt: new Date(),
reviews: []
}
],
active: true,
createdAt: new Date(),
updatedAt: new Date()
});
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 2
-
Задействованные коллекции:
users
Основной сценарий:
Проверка пользователя:
db.users.findOne({ email: "ivanov@example.com" });
- Количество запросов: 1
-
Задействованные коллекции:
users
Получение профиля пользователя:
db.users.findOne(
{ email: "ivanov@example.com" },
{ "profiles.role": 1 }
);
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 2
-
Задействованные коллекции:
users
Основной сценарий:
Обновление данных пользователя:
db.users.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e1") },
{ $set: { displayName: "Иван Иванович" } }
);
- Количество запросов: 1
-
Задействованные коллекции:
users
Обновление данных профиля:
db.users.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"), "profiles.role": "client" },
{ $set: { "profiles.$.description": "Новое описание" } }
);
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 2
-
Задействованные коллекции:
users
Основной сценарий:
Обновление роли в профиле:
db.users.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"), "profiles.role": "client" },
{ $set: { "profiles.$.role": "freelancer" } }
);
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
users
Основной сценарий:
Создание заказа:
db.orders.insertOne({
clientId: ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"),
title: "Разработка сайта",
description: "Создание лендинга",
completionTime: 1000000000,
cost: 1000,
active: true,
responses: [],
statuses: [
{
title: "beginning",
content: "Заказ создан",
createdAt: new Date()
}
],
createdAt: new Date(),
updatedAt: new Date()
});
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Обновление данных заказа:
db.orders.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e2") },
{ $set: { title: "Обновленный проект", description: "Новое описание" } }
);
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Обновление статуса заказа:
db.orders.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e2") },
{ $push: { statuses: { title: "negotiation", content: "Условия согласованы", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Добавление сообщения в чат:
db.chats.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e4") },
{ $push: { messages: { sender: "client", content: "Здравствуйте!", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
chats
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
chats
Основной сценарий:
Обновление статуса заказа:
db.orders.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e2") },
{ $push: { statuses: { title: "finished", content: "Заказ завершен", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Добавление отзыва:
db.users.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e3"), "profiles.role": "freelancer" },
{ $push: { "profiles.$.reviews": { authorId: ObjectId("64a1b2c3d4e5f6a7b8c9d0e1"), authorName: "Иван Иванов", score: 5, content: "Отлично!", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
users
Основной сценарий:
Получение откликов исполнителя:
db.orders.find({ "responses.freelancerId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e3") });
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Обновление активности отклика:
db.orders.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e2"), "responses.freelancerId": ObjectId("64a1b2c3d4e5f6a7b8c9d0e3") },
{ $set: { "responses.$.active": false } }
);
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Добавление сообщения в чат:
db.chats.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e4") },
{ $push: { messages: { sender: "freelancer", content: "Добрый день!", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
chats
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
chats
Основной сценарий:
Добавление системного сообщения о согласовании:
db.chats.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e4") },
{ $push: { messages: { sender: "system", content: "Условия согласованы.", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
chats
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
chats
Основной сценарий:
Добавление системного сообщения о согласовании:
db.chats.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e4") },
{ $push: { messages: { sender: "system", content: "Условия согласованы.", createdAt: new Date() } } }
);
- Количество запросов: 1
-
Задействованные коллекции:
chats
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
chats
Основной сценарий:
Получение количества заказов:
db.orders.countDocuments();
- Количество запросов: 1
-
Задействованные коллекции:
orders
Получение количества пользователей:
db.users.countDocuments();
- Количество запросов: 1
-
Задействованные коллекции:
users
Получение количества споров:
db.chats.countDocuments({ "messages.sender": "system", "messages.content": { $regex: /Спор/ } });
- Количество запросов: 1
-
Задействованные коллекции:
chats
Итого:
- Количество запросов: 3
-
Задействованные коллекции:
orders,users,chats
Основной сценарий:
Получение списка активных заказов:
db.orders.find({ active: true });
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Создание отклика:
db.orders.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e2") },
{
$push: {
responses: {
freelancerName: "Петр Петров",
freelancerId: ObjectId("64a1b2c3d4e5f6a7b8c9d0e3"),
chatId: ObjectId("64a1b2c3d4e5f6a7b8c9d0e4"),
coverLetter: "Готов взяться на проект!",
active: true,
createdAt: new Date(),
updatedAt: new Date()
}
}
}
);
- Количество запросов: 1
-
Задействованные коллекции:
orders
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
Обновление баланса пользователя:
db.users.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c9d0e3") },
{ $inc: { balance: -500 } }
);
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
users
Основной сценарий:
Экспорт данных:
db.users.find();
db.profiles.find();
db.orders.find();
db.chats.find();
db.messages.find();
db.responses.find();
db.reviews.find();
db.statuses.find();
- Количество запросов: 8
- Задействованные коллекции: Все коллекции
Итого:
- Количество запросов: 8
- Задействованные коллекции: Все коллекции
Основной сценарий:
Импорт данных:
db.users.insertOne({
displayName: "Новый Пользователь",
email: "newuser@example.com",
password: "hash4",
balance: 0,
systemRole: "user",
profiles: [],
active: true,
createdAt: new Date(),
updatedAt: new Date()
});
- Количество запросов: 1
-
Задействованные коллекции:
users
Итого:
- Количество запросов: 1
-
Задействованные коллекции:
users

Users:
reviews:
id: serial, V = 4b
author_id: integer, V = 4b
profile_id: integer, V = 4b
score: enum, V = 1b
content: text, V = 200b
created_at: timestamp, V = 8b
Итого: 4 + 4 + 4 + 1 + 200 + 8 = 221b
profiles:
id: serial, V = 4b
user_id: integer, V = 4b
role: enum, V = 15b
rating: real, V = 4b
description: text, V = 500b
created_at: timestamp, V = 8b
updated_at: timestamp, V = 8b
Итого: 4 + 4 + 15 + 4 + 500 + 8 + 8 = 543b
users:
id: serial, V = 4b
email: varchar(256), V = 30b
public_name: varchar(64), V = 30b
password: varchar(256), V = 60b
balance: integer, V = 4b
system_role: enum, V = 15b
is_active: boolean, V = 1b
created_at: timestamp, V = 8b
updated_at: timestamp, V = 8b
Итого: 4 + 30 + 30 + 60 + 4 + 15 + 1 + 8 + 8 = 160b
Фактический объём users: NR ⋅ 221 + NP ⋅ 543 + NU ⋅ 160, где NR – количество отзывов, NP – количество профилей, NU – количество пользователей.
Так как в среднем на профиль приходится 10 отзывов, а на пользователя – 2 профиля (фрилансер и заказчик), то объём: NU ⋅ (20 ⋅ 221 + 2 ⋅ 543 + 160) = (NU ⋅ 5666)b
Chats:
messages:
id: serial, V = 4b
chat_id: integer, V = 4b
sender_id: integer, V = 4b
is_system: boolean, V = 1b
text: text, V = 500b
created_at: timestamp, V = 8b
Итого: 4 + 4 + 4 + 1 + 500 + 8 = 521b
chats:
id: serial, V = 4b
order_id: integer, V = 4b
client_id: integer, V = 4b
freelancer_id: integer, V = 4b
is_active: boolean, V = 1b
created_at: timestamp, V = 8b
updated_at: timestamp, V = 8b
Итого: 4 + 4 + 4 + 4 + 1 + 8 + 8 = 33b
Фактический объём chats: NM ⋅ 521 + NC ⋅ 33, где NM – количество сообщений, NC – количество чатов.
Так как в среднем на чат приходится 50 сообщений, то объём: NC ⋅ (50 ⋅ 521 + 33) = (NC ⋅ 26083)b
Orders:
statuses:
order_id: integer, V = 4b
sequential_number: integer, V = 4b
title: enum, V = 15b
extra_info: jsonb, V = 20b
created_at: timestamp, V = 8b
Итого: 4 + 4 + 15 + 20 + 8 = 51b
responses:
order_id: integer, V = 4b
freelancer_id: integer, V = 4b
chat_id: integer, V = 4b
is_active: boolean, V = 1b
created_at: timestamp, V = 8b
updated_at: timestamp, V = 8b
Итого: 4 + 4 + 4 + 1 + 8 + 8 = 29b
orders:
id: serial, V = 4b
client_id: integer, V = 4b
title: varchar(128), V = 50b
description: text, V = 1000b
completion_time: bigint, V = 8b
cost: integer, V = 4b
is_active: boolean, V = 1b
freelancer_id: integer, V = 4b
budget: integer, V = 4b
created_at: timestamp, V = 8b
updated_at: timestamp, V = 8b
Итого: 4 + 4 + 50 + 1000 + 8 + 4 + 1 + 4 + 4 + 8 + 8 = 1095b
Фактический объём orders: NS ⋅ 51 + NRes ⋅ 29 + NO ⋅ 1095, где NS – количество статусов, NRes – количество откликов, NO – количество заказов.
Так как в среднем на заказ приходится 5 откликов и 5 статусов, то объём: NO ⋅ (5 ⋅ 51 + 5 ⋅ 29 + 1095) = (NO ⋅ 1495)b
Фактический объём модели: NU ⋅ 5666 + NO ⋅ 1495 + NC ⋅ 26083, где NU – количество пользователей, NO – количество заказов, NC – количество чатов.
Выразим всё через количество заказов аналогично нереляционной модели:
V(NO) = (82577 ⋅ NO)bytes
Для вычисления «чистого» объёма данных исключим из расчетов дублирующуюся и служебную информацию, тогда:
Users:
reviews:
score: enum, V = 1b
content: text, V = 200b
Итого: 201b
profiles:
role: enum, V = 15b
rating: real, V = 4b
description: text, V = 500b
Итого: 519b
users:
email: varchar(256), V = 30b
public_name: varchar(64), V = 30b
password: varchar(256), V = 60b
balance: integer, V = 4b
system_role: enum, V = 15b
Итого: 30 + 30 + 60 + 4 + 15 = 139b
«Чистый» объём users: NR ⋅ 201 + NP ⋅ 519 + NU ⋅ 139, где NR – количество отзывов, NP – количество профилей, NU – количество пользователей.
Так как в среднем на профиль приходится 10 отзывов, а на пользователя – 2 профиля (фрилансер и заказчик), то объём: NU ⋅ (20 ⋅ 201 + 2 ⋅ 519 + 139) = (NU ⋅ 5197)b
Chats:
messages:
is_system: boolean, V = 1b
text: text, V = 500b
Итого: 501b
chats:
is_active: boolean, V = 1b
Итого: 1b
«Чистый» объём chats: NM ⋅ 501 + NC ⋅ 1, где NM – количество сообщений, NC – количество чатов.
Так как в среднем на чат приходится 50 сообщений, то объём: NC ⋅ (50 ⋅ 501 + 1) = (NC ⋅ 25051)b
Orders:
statuses:
title: enum, V = 15b
extra_info: jsonb, V = 20b
Итого: 35b
responses:
is_active: boolean, V = 1b
Итого: 1b
orders:
title: varchar(128), V = 50b
description: text, V = 1000b
completion_time: bigint, V = 8b
cost: integer, V = 4b
budget: integer, V = 4b
Итого: 50 + 1000 + 8 + 4 + 4 = 1066b
«Чистый» объём orders: NS ⋅ 35 + NRes ⋅ 1 + NO ⋅ 1066, где NS – количество статусов, NRes – количество откликов, NO – количество заказов.
Так как в среднем на заказ приходится 5 откликов и 5 статусов, то объём: NO ⋅ (5 ⋅ 35 + 5 ⋅ 1 + 1066) = (NO ⋅ 1246)b
«Чистый» объём модели: NU ⋅ 5197 + NO ⋅ 1246 + NC ⋅ 25051, где NU – количество пользователей, NO – количество заказов, NC – количество чатов.
Выразим всё через количество заказов аналогично нереляционной модели:
Vc(NO) = (78998 ⋅ NO)bytes
Избыточность:
R(NO) = V(NO) / Vc(NO) = 82577 / 78998 = 1.045
При увеличении количества объектов любой из сущностей модель будет расти линейно.
| id | public_name | password | balance | system_role | is_active | created_at | updated_at | |
|---|---|---|---|---|---|---|---|---|
| 1 | ivanov@example.com | Иван Иванов | hash1 | 1000 | user | true | 2023-10-01 10:00:00 | 2023-10-01 10:00:00 |
| 2 | petrov@example.com | Петр Петров | hash2 | 500 | user | true | 2023-10-01 10:05:00 | 2023-10-01 10:05:00 |
| 3 | admin@example.com | Админ Админов | hash3 | 0 | admin | true | 2023-10-01 10:10:00 | 2023-10-01 10:10:00 |
| id | user_id | role | rating | description | created_at | updated_at |
|---|---|---|---|---|---|---|
| 1 | 1 | client | 4.5 | Заказчик Иван | 2023-10-01 10:00:00 | 2023-10-01 10:00:00 |
| 2 | 2 | freelancer | 4.7 | Фрилансер Петр | 2023-10-01 10:05:00 | 2023-10-01 10:05:00 |
| id | client_id | title | description | completion_time | cost | is_active | freelancer_id | budget | created_at | updated_at |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 | Разработка сайта | Создание лендинга | 1000000000 | 1000 | true | 2 | 1000 | 2023-10-01 10:00:00 | 2023-10-01 10:00:00 |
| id | order_id | client_id | freelancer_id | is_active | created_at | updated_at |
|---|---|---|---|---|---|---|
| 1 | 1 | 1 | 2 | true | 2023-10-01 10:00:00 | 2023-10-01 10:00:00 |
| id | chat_id | sender_id | is_system | text | created_at |
|---|---|---|---|---|---|
| 1 | 1 | 1 | false | Здравствуйте! | 2023-10-01 10:00:00 |
| 2 | 1 | 2 | false | Добрый день! | 2023-10-01 10:05:00 |
| order_id | freelancer_id | chat_id | is_active | created_at | updated_at |
|---|---|---|---|---|---|
| 1 | 2 | 1 | true | 2023-10-01 10:00:00 | 2023-10-01 10:00:00 |
| id | author_id | profile_id | score | content | created_at |
|---|---|---|---|---|---|
| 1 | 1 | 2 | 5 | Отлично! | 2023-10-01 10:00:00 |
| order_id | sequential_number | title | extra_info | created_at |
|---|---|---|---|---|
| 1 | 1 | beginning | {} | 2023-10-01 10:00:00 |
Основной сценарий:
-
Проверка уникальности email:
SELECT id FROM users WHERE email = 'ivanov@example.com';
-
Количество запросов: 1
-
Задействованные коллекции:
users
-
-
Создание нового пользователя:
INSERT INTO users (email, public_name, password, system_role, is_active) VALUES ('ivanov@example.com', 'Иван Иванов', 'hash1', 'user', true);
-
Количество запросов: 1
-
Задействованные коллекции:
users
-
-
Создание профиля пользователя:
INSERT INTO profiles (user_id, role, description) VALUES (1, 'client', 'Заказчик Иван');
-
Количество запросов: 1
-
Задействованные коллекции:
profiles
-
Итого:
-
Количество запросов: 3
-
Задействованные коллекции:
users,profiles
Основной сценарий:
-
Проверка пользователя:
SELECT id, password FROM users WHERE email = 'ivanov@example.com';
-
Количество запросов: 1
-
Задействованные коллекции:
users
-
-
Получение профиля пользователя:
SELECT role FROM profiles WHERE user_id = 1;
-
Количество запросов: 1
-
Задействованные коллекции:
profiles
-
Итого:
-
Количество запросов: 2
-
Задействованные коллекции:
users,profiles
Основной сценарий:
-
Обновление данных пользователя:
UPDATE users SET public_name = 'Иван Иванович' WHERE id = 1;
-
Количество запросов: 1
-
Задействованные коллекции:
users
-
-
Обновление данных профиля:
UPDATE profiles SET description = 'Новое описание' WHERE user_id = 1;
-
Количество запросов: 1
-
Задействованные коллекции:
profiles
-
Итого:
-
Количество запросов: 2
-
Задействованные коллекции:
users,profiles
Основной сценарий:
-
Обновление роли в профиле:
UPDATE profiles SET role = 'freelancer' WHERE user_id = 1;
-
Количество запросов: 1
-
Задействованные коллекции:
profiles
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
profiles
Основной сценарий:
-
Создание заказа:
INSERT INTO orders (client_id, title, description, completion_time, cost, is_active) VALUES (1, 'Разработка сайта', 'Создание лендинга', 1000000000, 1000, true);
-
Количество запросов: 1
-
Задействованные коллекции:
orders
-
-
Создание статуса заказа:
INSERT INTO statuses (order_id, sequential_number, title) VALUES (1, 1, 'beginning');
-
Количество запросов: 1
-
Задействованные коллекции:
statuses
-
Итого:
-
Количество запросов: 2
-
Задействованные коллекции:
orders,statuses
Основной сценарий:
-
Обновление данных заказа:
UPDATE orders SET title = 'Обновленный проект', description = 'Новое описание' WHERE id = 1;
-
Количество запросов: 1
-
Задействованные коллекции:
orders
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
-
Обновление статуса заказа:
INSERT INTO statuses (order_id, sequential_number, title) VALUES (1, 2, 'negotiation');
-
Количество запросов: 1
-
Задействованные коллекции:
statuses
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
statuses
Основной сценарий:
-
Добавление сообщения в чат:
INSERT INTO messages (chat_id, sender_id, text) VALUES (1, 1, 'Здравствуйте!');
-
Количество запросов: 1
-
Задействованные коллекции:
messages
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
messages
Основной сценарий:
-
Обновление статуса заказа:
INSERT INTO statuses (order_id, sequential_number, title) VALUES (1, 3, 'finished');
-
Количество запросов: 1
-
Задействованные коллекции:
statuses
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
statuses
Основной сценарий:
-
Добавление отзыва:
INSERT INTO reviews (author_id, profile_id, score, content) VALUES (1, 2, 5, 'Отлично!');
-
Количество запросов: 1
-
Задействованные коллекции:
reviews
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
reviews
Основной сценарий:
-
Получение откликов исполнителя:
SELECT * FROM responses WHERE freelancer_id = 2;
-
Количество запросов: 1
-
Задействованные коллекции:
responses
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
responses
Основной сценарий:
-
Обновление активности отклика:
UPDATE responses SET is_active = false WHERE order_id = 1 AND freelancer_id = 2;
-
Количество запросов: 1
-
Задействованные коллекции:
responses
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
responses
Основной сценарий:
-
Добавление сообщения в чат:
INSERT INTO messages (chat_id, sender_id, text) VALUES (1, 2, 'Добрый день!');
-
Количество запросов: 1
-
Задействованные коллекции:
messages
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
messages
Основной сценарий:
-
Добавление системного сообщения о согласовании:
INSERT INTO messages (chat_id, is_system, text) VALUES (1, true, 'Условия согласованы.');
-
Количество запросов: 1
-
Задействованные коллекции:
messages
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
messages
Основной сценарий:
-
Добавление системного сообщения о согласовании:
INSERT INTO messages (chat_id, is_system, text) VALUES (1, true, 'Условия согласованы.');
-
Количество запросов: 1
-
Задействованные коллекции:
messages
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
messages
Основной сценарий:
-
Получение количества заказов:
SELECT COUNT(*) FROM orders;
-
Количество запросов: 1
-
Задействованные коллекции:
orders
-
-
Получение количества пользователей:
SELECT COUNT(*) FROM users;
-
Количество запросов: 1
-
Задействованные коллекции:
users
-
-
Получение количества споров:
SELECT COUNT(*) FROM messages WHERE is_system = true AND text LIKE '%Спор%';
-
Количество запросов: 1
-
Задействованные коллекции:
messages
-
Итого:
-
Количество запросов: 3
-
Задействованные коллекции:
orders,users,messages
Основной сценарий:
-
Получение списка активных заказов:
SELECT * FROM orders WHERE is_active = true;
-
Количество запросов: 1
-
Задействованные коллекции:
orders
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
orders
Основной сценарий:
-
Создание отклика:
INSERT INTO responses (order_id, freelancer_id, chat_id, is_active) VALUES (1, 2, 1, true);
-
Количество запросов: 1
-
Задействованные коллекции:
responses
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
responses
Основной сценарий:
-
Обновление баланса пользователя:
UPDATE users SET balance = balance - 500 WHERE id = 2;
-
Количество запросов: 1
-
Задействованные коллекции:
users
-
Итого:
-
Количество запросов: 1
-
Задействованные коллекции:
users
Основной сценарий:
-
Экспорт данных:
SELECT * FROM users; SELECT * FROM profiles; SELECT * FROM orders; SELECT * FROM chats; SELECT * FROM messages; SELECT * FROM responses; SELECT * FROM reviews; SELECT * FROM statuses;
-
Количество запросов: 8
-
Задействованные коллекции: Все таблицы
-
Итого:
- Количество запросов: 8
| Параметр | Нереляционная модель | Реляционная модель |
|---|---|---|
| "Грязный" объём | 86625 ⋅ NO | 82577 ⋅ NO |
| "Чистый" объём | 84071 ⋅ NO | 78998 ⋅ NO |
| Избыточность | 1.03 | 1.045 |
| № | Название | Нереляционная, запросы | Реляционная, запросы | Нереляционная, коллекции | Реляционная, коллекции |
|---|---|---|---|---|---|
| 1 | Регистрация пользователя | 2 | 3 | 1 (users) |
2 (users, profiles) |
| 2 | Авторизация пользователя | 2 | 2 | 1 (users) |
2 (users, profiles) |
| 3 | Редактирование профиля | 1 | 2 | 1 (users) |
2 (users, profiles) |
| 4 | Смена роли | 1 | 1 | 1 (users) |
1 (profiles) |
| 5 | Заказчик публикует новый заказ | 1 | 2 | 1 (orders) |
2 (orders, statuses) |
| 6 | Заказчик редактирует заказ | 1 | 1 | 1 (orders) |
1 (orders) |
| 7 | Стороны согласовали условия и работа началась | 1 | 1 | 1 (orders) |
1 (statuses) |
| 8 | Стороны общаются в процессе выполнения заказа | 1 | 1 | 1 (orders) |
1 (messages) |
| 9 | Завершение заказа | 1 | 1 | 1 (orders) |
1 (statuses) |
| 10 | Стороны оставляют отзывы | 1 | 1 | 1 (users) |
1 (reviews) |
| 11 | Исполнитель смотрит свои отклики | 1 | 1 | 1 (orders) |
1 (responses) |
| 12 | Исполнитель отзывает отклик | 1 | 1 | 1 (orders) |
1 (responses) |
| 13 | Исполнитель общается в чате до согласования | 1 | 1 | 1 (chats) |
1 (messages) |
| 14 | Заказчик согласовывает условия в чате | 1 | 1 | 1 (chats) |
1 (messages) |
| 15 | Исполнитель согласовывает условия в чате | 1 | 1 | 1 (chats) |
1 (messages) |
| 16 | Подсчёт статистики | 3 | 3 | 3 (orders, users, chats) |
3 (orders, users, messages) |
| 17 | Исполнитель ищет заказы | 1 | 1 | 1 (orders) |
1 (orders) |
| 18 | Исполнитель откликается на заказ | 1 | 1 | 1 (orders) |
1 (responses) |
| 19 | Исполнитель выводит средства | 1 | 1 | 1 (users) |
1 (users) |
Нереляционная модель требует больше объёма, чем реляционная. Количество запросов к нереляционной немного меньше, чем к реляционной (в основном по всем юзкейсам требуется один запрос, кроме регистрации/авторизации). Избыточность у реляционной немногим меньше, чем у нереляционной. В целом, что SQL, что noSQL одинаково хорошо подходят к задаче. Здесь мало слабоструктурированных данных (только сообщения в переписке).