Есть ли способ оптимизировать get_or_create(), чтобы сделать программу быстрее?

Функциональность, которую я хочу реализовать, заключается в создании нового класса и импорте пользователей. Поскольку я не хочу, чтобы один и тот же пользователь импортировался несколько раз, а пользователь может присоединяться к разным классам, я использовал get_or_create(). Однако я заметил, что программа становится медленной при импорте большого количества пользователей одновременно (использую CSV для импорта пользователей).

 def post(self, request):
        class_data = request.data
        class_data["start_time"] = dateutil.parser.parse(class_data["start_time"])
        class_data["end_time"] = dateutil.parser.parse(class_data["end_time"])
        class_data["created_by"] = request.user

        if class_data["end_time"] <= class_data["start_time"]:
            return self.error("Start time must occur earlier than end time")

        user_data = class_data.pop("users")  # Retrieve user data and remove it from the class data

        try:
            with transaction.atomic():
                if Class.objects.filter(title=class_data["title"]).exists():
                    return self.error("Class with the same title already exists")

                class_obj = Class.objects.create(**class_data)  # Create the class object

                # Add the creator to the class members
                if not class_obj.users.filter(id=request.user.id).exists():
                    class_obj.users.add(request.user)

                for data in user_data:
                    if len(data) != 4 or len(data[1]) > 32:
                        return self.error(f"Error occurred while processing data '{data}'")

                    username = data[1]
                    user, created = User.objects.get_or_create(username=username, defaults={
                        "password": make_password(data[1]),
                        "college": data[3],
                        "student_number": data[1]
                    })
                    if created:
                        profile = UserProfile(user=user, real_name=data[2])
                        profile.save()

                    # class_obj.users.add(user)
                    if not class_obj.users.filter(id=user.id).exists():
                        class_obj.users.add(user)
            return self.success(ClassAdminSerializer(class_obj).data)
        except IntegrityError as e:
            return self.error(str(e).split("\n")[1])

Я выявил три области, которые замедляют работу программы. Во-первых, операция get_or_create() занимает много времени, поскольку она проверяет существование каждого пользователя в отдельности. Во-вторых, операция profile.save() вставляет данные по одному, что приводит к значительным затратам времени. И наконец, операция class_obj.users.add(user) для вставки данных в таблицу ассоциаций между моделями Class и User также занимает значительное время. Вот модели для моих User и Class:

class User(AbstractBaseUser):
    id = models.BigAutoField(primary_key=True)

    username = models.TextField(unique=True)
    email = models.TextField(blank=True, null=True)
    # ADD
    college = models.TextField(default=College.COMMUNICATION_COLLEGE)
    student_number = models.TextField(null=True)
    major = models.TextField(null=True)


    create_time = models.DateTimeField(auto_now_add=True, null=True)
    # One of UserType
    admin_type = models.TextField(default=AdminType.REGULAR_USER)
    problem_permission = models.TextField(default=ProblemPermission.NONE)
    reset_password_token = models.TextField(null=True)
    reset_password_token_expire_time = models.DateTimeField(null=True)
    # SSO auth token
    auth_token = models.TextField(null=True)
    two_factor_auth = models.BooleanField(default=False)
    tfa_token = models.TextField(null=True)
    session_keys = JSONField(default=list)
    # open api key
    open_api = models.BooleanField(default=False)
    open_api_appkey = models.TextField(null=True)
    is_disabled = models.BooleanField(default=False)

    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = []

    objects = UserManager()

    def is_admin(self):
        return self.admin_type == AdminType.ADMIN

    def is_super_admin(self):
        return self.admin_type == AdminType.SUPER_ADMIN

    def is_admin_role(self):
        return self.admin_type in [AdminType.ADMIN, AdminType.SUPER_ADMIN]

    def can_mgmt_all_problem(self):
        return self.problem_permission == ProblemPermission.ALL

    def is_contest_admin(self, contest):
        return self.is_authenticated and (contest.created_by == self or self.admin_type == AdminType.SUPER_ADMIN)

    def is_Class_admin(self, class_obj):
        return self.is_authenticated and (class_obj.created_by == self or self.admin_type == AdminType.SUPER_ADMIN)

    class Meta:
        db_table = "user"


class Class(models.Model):
    title = models.TextField()
    start_time = models.DateTimeField()

    end_time = models.DateTimeField()
    create_time = models.DateTimeField(auto_now_add=True)
    
    # show real time rank or cached rank
    real_time_rank = models.BooleanField(default=True)

    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='created_classes')

    users = models.ManyToManyField(User, related_name='enrolled_classes')


    @property
    def status(self):
        if self.start_time > now():
            return ClassStatus.CLASS_NOT_START
        elif self.end_time < now():
            return ClassStatus.CLASS_ENDED
        else:
            return ClassStatus.CLASS_UNDERWAY

    def problem_details_permission(self, user):
        return self.status == ClassStatus.CLASS_ENDED or \
                user.is_authenticated and user.is_Class_admin(self) or \
                self.real_time_rank

    class Meta:
        db_table = "Class"
        ordering = ("-start_time",)

Это мой первый опыт работы с моделями Django, и я не уверен, как решить эту проблему. Я хотел бы попросить вас подсказать, как изменить мой код. Не могли бы вы посоветовать мне необходимые изменения?


Первая правка: Я внес следующие изменения в код.

def post(self, request):
        class_data = request.data
        class_data["start_time"] = dateutil.parser.parse(class_data["start_time"])
        class_data["end_time"] = dateutil.parser.parse(class_data["end_time"])
        class_data["created_by"] = request.user

        if class_data["end_time"] <= class_data["start_time"]:
            return self.error("Start time must occur earlier than end time")

        user_data = class_data.pop("users")  # Retrieve user data and remove it from the class data

        try:
            with transaction.atomic():
                if Class.objects.filter(title=class_data["title"]).exists():
                    return self.error("Class with the same title already exists")

                class_obj = Class.objects.create(**class_data)  # Create the class object
                # To add the creator to the class members
                class_obj.users.add(request.user)

                # Bulk create users
                # To import users and add them to class
                usernames = [data[1] for data in user_data]

                # To check if a user already exists
                existing_users = User.objects.filter(username__in=usernames)
                existing_usernames = set(existing_users.values_list('username', flat=True))

                users_to_create = []
                users_to_add = []

                for data in user_data:
                    if len(data) != 4 or len(data[1]) > 32:
                        return self.error(f"Error occurred while processing data '{data}'")

                    username = data[1]

                    if username not in existing_usernames:
                        # If the user does not exist, create a new user
                        user = User(username=username, password=make_password(data[1]),
                                    college=data[3], student_number=data[1])
                        users_to_create.append(user)
                        users_to_add.append(user)
                    else:
                        # If the user already exists, add them to the class 
                        user = existing_users.get(username=username)
                        if not class_obj.users.filter(id=user.id).exists():
                            users_to_add.append(user)

                User.objects.bulk_create(users_to_create)

                # Bulk create user profiles
                profiles_to_create = [UserProfile(user=user, real_name=data[2]) for user, data in zip(users_to_create, user_data)]
                UserProfile.objects.bulk_create(profiles_to_create)

                # Bulk add users to class
                class_obj.users.add(*users_to_add)

            return self.success(ClassAdminSerializer(class_obj).data)

        except IntegrityError as e:
            return self.error(str(e).split("\n")[1])

Я заметил, что когда я импортирую пользователей и все они уже существуют в базе данных, процесс создания класса происходит очень быстро. Однако когда большинство пользователей нужно создать заново, между операциями SELECT и INSERT возникает задержка примерно в одну минуту, как показано на следующей диаграмме. Incomplete screenshot Я не уверен в том, что вызывает эту проблему, и даже подозреваю, что она может быть связана с недостаточным аппаратным обеспечением моего компьютера. Есть ли способ решить эту проблему?

Вернуться на верх