Удалите все объекты в Django, кроме последних N (N - большое, около 1000)
Какой самый быстрый способ удалить все объекты, кроме последней 1000?
Я могу сделать это медленно:
last_events = Event.objects.filter(user=user).order_by('-created')[:1000].values_list('id', flat=True)
Event.objects.filter(user=user).exclude(id__in=list(last_events)).delete()
Но я бы не хотел загружать такой длинный запрос в мою БД.
Я думал, что не могу найти ID элемента границы и удалить все объекты перед этим элементом:
last_events = Event.objects.filter(user=user).order_by('-created')[:1000].last()
Но получил:
TypeError: Cannot reverse a query once a slice has been taken.
Я также пробовал:
last_events = Event.objects.filter(user=user).order_by('-created')[:1000][-1]
Но получил:
AssertionError: Negative indexing is not supported.
Вам просто нужно изменить порядок, используемый для построения SQL, и использовать первые 1000 вместо последних, например, так:
last_events = Event.objects.filter(user=user).order_by('+created')[:1000]
Event.objects.filter(user=user).exclude(id__in=list(last_events)).delete()
То, что вы попробовали сначала, является правильным способом. Иногда delete()
может работать медленно. Вы можете избежать его медлительности, если вас не волнует следующее:
- Django должен обеспечить правильное функционирование каскадного удаления, таким образом, ища ссылки на внешние ключи ваших моделей .
- Django должен обрабатывать сигналы до и после сохранения для ваших моделей .
Если вам удобно работать с ними, вы можете использовать _raw_delete()
начиная с Django 1.5+. Поскольку это приватный метод, мне не очень нравится вызывать эти методы.
Вторым ответом может быть необработанный SQL-запрос, такой как:
delete from table_events
where user_id={user_id}
and id not in (
select id
from table_events
where user_id={user_id}
order by created desc
offset {N}
)
Перед использованием обоих способов следует хорошо подумать. Отношения и функциональные возможности Django под капотом будут для вас неприемлемы. Вы должны позаботиться об этих проблемах самостоятельно.