Как удалить 200 000 записей с помощью DJango?
Ситуация: У меня есть модель отношения 1-1, образец:
class User(models.Model):
user_namme = models.CharField(max_length=40)
type = models.CharField(max_length=255)
created_at = models.DatetimeField()
...
class Book(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
У меня около 200 000 записей.
- Язык: Python
- Framework: Django
- База данных: Postgres
Вопрос:
- Как удалить 200 000 записей с минимальными затратами?
Решение, которое я пробовал:
user_ids = Users.objects.filter(type='sample', created_date__gte='2022-11-15 08:00', created_date__lt="2022-11-15 08:30").values_list('id',flat=True)[:200000] # Fetch 200,000 user ids.
for i, _ in enumerate(user_ids[:: 1000]):
with transaction.atomic():
batch_start = i * self.batch_size
batch_end = batch_start + self.batch_size
_, deleted = Users.objects.filter(id__in=user_ids[batch_start,batch_end]
При таком решении мой сервер использует около:
- 600MB CPU
- 300MB RAM
- Потребуется более 15 минут для завершения работы.
Интересно, есть ли у кого-нибудь лучшее решение?
По первым принципам, ничто не сравнится с сырым (Django query) SQL по скорости, потому что он работает ближе всего к базе данных!
cursor.execute("DELETE FROM DB WHERE Column = %s")
Или же вы можете сделать это следующим образом:
Variable = Model.objects.filter(variable=variable)
if Variable.exists():
Variable.delete()
Спасибо всем. Я попробовал решение с помощью RawQuery
user_ids = Users.objects.filter(type='sample', created_date__gte='2022-11-15 08:00', created_date__lt="2022-11-15 08:30").values_list('id',flat=True)[:200000] # Fetch 200,000 user ids.
for i in range(0, 3):
user_ids_str = ""
for user_id in user_ids.iterator(chunk_size=5000):
user_ids_str += f"{user_id},"
query = f"""
DELETE FROM "user" WHERE "user"."id" IN ({user_ids_str});
DELETE FROM "book" WHERE "user"."id" IN ({user_ids_str});
"""
with transaction.atomic():
with connection.cursor() as c:
c.execute("SET statement_timeout = '10min';")
c.execute(query)
Этот может удалить 600000 записей и занимает около 10 минут. А сервер использует около:
- CPU: 50MB
- RAM: 200MB