Оптимизация структуры хранения данных в базе данныхPython

Программы на Python
Anonymous
Оптимизация структуры хранения данных в базе данных

Сообщение Anonymous »

Стек: Python 3.12, PostgreSQL 15, SQLAlchemy 2.0
Существует несколько таблиц, описывающих объекты, с разными полями (кроме id и is_available).< /p>
Под «объектами» я просто подразумеваю несколько различных моделей в приложении, например: «Опубликовать» и «Комментарий», «Книга» и «Обзор» и тому подобное. Просто чтобы понять, что комбинировать их нельзя.
из sqlalchemy.orm import DeclarativeBase
из sqlalchemy.orm import Mapped, mapped_column

Код: Выделить всё

class Base(DeclarativeBase):
__abstract__ = True

class User(Base):
__tablename__ = "users"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
name: Mapped[str]

class ObjectBase(Base):
__abstract__ = True

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
is_available: Mapped[bool] = mapped_column(default=True)

class ObjectA(ObjectBase):
__tablename__ = "object_a"

field_1: Mapped[str]
field_2: Mapped[int]

class ObjectB(ObjectBase):
__tablename__ = "object_b"

field_3: Mapped[float]
field_4: Mapped[str]
Мне нужны таблицы с жалобами на описанные выше объекты, а также таблица, в которой хранятся удаленные объекты, также из числа описанных выше объектов.
Поле is_available позволяет нам хранить удаленные объекты, но не показывать их, однако помимо факта удаления нам нужны еще детали, которые нецелесообразно хранить в самих таблицах, например причина , delete_by_id, delete_at, а что касается жалоб, то их вообще может быть несколько на один объект, поэтому даже это реализовать невозможно.
Возможные решения, в на мой взгляд, заключаются в следующем:
  • Создание таблицы для каждого объекта

Код: Выделить всё

from sqlalchemy import DateTime, ForeignKey
from sqlalchemy.sql import func

class ObjectAReport(Base):
__tablename__ = "object_a_reports"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
object_id: Mapped[int] = mapped_column(ForeignKey("object_a.id"))
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))  # User who sent the complaint
reason: Mapped[str] = mapped_column(nullable=False)
sent_at: Mapped[DateTime] = mapped_column(DateTime(timezone=True), server_default=func.now())

class ObjectBReport(Base):
__tablename__ = "object_b_reports"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
object_id: Mapped[int] = mapped_column(ForeignKey("object_b.id"))
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))  # User who sent the complaint
reason: Mapped[str] = mapped_column(nullable=False)
sent_at: Mapped[DateTime] = mapped_column(DateTime(timezone=True), server_default=func.now())

class DeletedObjectA(Base):
__tablename__ = "deleted_object_a"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
object_id: Mapped[int] = mapped_column(ForeignKey("object_a.id"))
deleted_by_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
reason: Mapped[str] = mapped_column(nullable=False)
deleted_at: Mapped[DateTime] = mapped_column(DateTime(timezone=True), server_default=func.now())

class DeletedObjectB(Base):
__tablename__ = "deleted_object_b"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
object_id: Mapped[int] = mapped_column(ForeignKey("object_b.id"))
deleted_by_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
reason: Mapped[str] = mapped_column(nullable=False)
deleted_at: Mapped[DateTime] = mapped_column(DateTime(timezone=True), server_default=func.now())
Мне не очень нравится такая реализация, потому что при создании нового объекта для него приходится создавать 2 дополнительные таблицы, поэтому база данных сильно разрастется.
  • Создание общей таблицы для всех объектов

Код: Выделить всё

from sqlalchemy import DateTime, ForeignKey
from sqlalchemy.sql import func

class ObjectReport(Base):
__tablename__ = "object_reports"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
object_id: Mapped[int]
object_type: Mapped[str]  # "object_a" or "object_b".  Also, a more robust option is to create an ObjectType model, but this is just an example in this case.
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))  # User who sent the complaint
reason: Mapped[str] = mapped_column(nullable=False)
sent_at: Mapped[DateTime] = mapped_column(DateTime(timezone=True), server_default=func.now())

class DeletedObject(Base):
__tablename__ = "deleted_objects"

id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
object_id: Mapped[int]
object_type: Mapped[str]  # "object_a" or "object_b".
deleted_by_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
reason: Mapped[str] = mapped_column(nullable=False)
deleted_at: Mapped[DateTime] = mapped_column(DateTime(timezone=True), server_default=func.now())
Мне такая реализация не нравится, потому что страдает целостность данных, и ее приходится обеспечивать дополнительно на уровне приложения, а также путем создания триггеров, которые приходится пересоздавать при появлении нового объекта создан.
Мои вопросы следующие:
  • Являются ли эти примеры правильным решением, и если да, то какое какой лучше использовать?
  • Есть ли другие варианты решения этой проблемы?


Подробнее здесь: https://stackoverflow.com/questions/786 ... e-database

Вернуться в «Python»