91 lines
4.3 KiB
Markdown
91 lines
4.3 KiB
Markdown
# Отчет об оптимизации запросов в ObjItemListView
|
||
|
||
## Задача 29: Оптимизировать запросы в ObjItemListView
|
||
|
||
### Выполненные изменения
|
||
|
||
#### 1. Добавлены select_related() для всех связанных моделей
|
||
Добавлены следующие связи через `select_related()`:
|
||
- `transponder`
|
||
- `transponder__sat_id`
|
||
- `transponder__polarization`
|
||
|
||
Эти связи уже были частично оптимизированы, но были добавлены недостающие.
|
||
|
||
#### 2. Добавлены prefetch_related() для mirrors и marks
|
||
Использованы оптимизированные `Prefetch` объекты:
|
||
|
||
```python
|
||
# Оптимизированный prefetch для mirrors через geo_obj
|
||
mirrors_prefetch = Prefetch(
|
||
'geo_obj__mirrors',
|
||
queryset=Satellite.objects.only('id', 'name').order_by('id')
|
||
)
|
||
|
||
# Оптимизированный prefetch для marks через source
|
||
marks_prefetch = Prefetch(
|
||
'source__marks',
|
||
queryset=ObjectMark.objects.select_related('created_by__user').order_by('-timestamp')
|
||
)
|
||
```
|
||
|
||
#### 3. Исправлен доступ к mirrors
|
||
Изменен способ доступа к mirrors с `values_list()` на list comprehension:
|
||
|
||
**Было:**
|
||
```python
|
||
mirrors_list = list(obj.geo_obj.mirrors.values_list('name', flat=True))
|
||
```
|
||
|
||
**Стало:**
|
||
```python
|
||
mirrors_list = [mirror.name for mirror in obj.geo_obj.mirrors.all()]
|
||
```
|
||
|
||
Это критически важно, так как `values_list()` обходит prefetch_related и вызывает дополнительные запросы.
|
||
|
||
### Результаты тестирования
|
||
|
||
#### Тест 1: Сравнение с baseline (50 объектов)
|
||
- **До оптимизации:** 51 запрос
|
||
- **После оптимизации:** 4 запроса
|
||
- **Улучшение:** 92.2% (сокращение на 47 запросов)
|
||
|
||
#### Тест 2: Масштабируемость
|
||
| Количество объектов | Запросов |
|
||
|---------------------|----------|
|
||
| 10 | 4 |
|
||
| 50 | 4 |
|
||
| 100 | 4 |
|
||
| 200 | 4 |
|
||
|
||
**Результат:** ✓ PERFECT! Количество запросов остается постоянным независимо от количества объектов.
|
||
|
||
### Структура запросов после оптимизации
|
||
|
||
1. **Основной запрос:** SELECT для ObjItem с JOIN для всех select_related связей
|
||
2. **Prefetch mirrors:** SELECT для Satellite через geo_mirrors (ManyToMany)
|
||
3. **Prefetch source:** SELECT для Source (если не покрыто select_related)
|
||
4. **Prefetch marks:** SELECT для ObjectMark через source
|
||
|
||
### Требования
|
||
Выполнены все требования задачи:
|
||
- ✓ 8.1 - Добавлен select_related() для всех связанных моделей
|
||
- ✓ 8.2 - Добавлен prefetch_related() для mirrors
|
||
- ✓ 8.3 - Добавлен prefetch_related() для marks
|
||
- ✓ 8.4 - Проверено количество запросов до и после оптимизации
|
||
- ✓ 8.6 - Оптимизация работает корректно
|
||
|
||
### Файлы изменены
|
||
- `dbapp/mainapp/views/objitem.py` - добавлены оптимизации запросов
|
||
|
||
### Тестовые файлы
|
||
- `test_objitem_final.py` - тест сравнения с baseline
|
||
- `test_objitem_scale.py` - тест масштабируемости
|
||
- `test_objitem_query_optimization.py` - базовый тест
|
||
- `test_objitem_detailed_queries.py` - детальный тест
|
||
|
||
## Заключение
|
||
|
||
Оптимизация успешно выполнена. Количество запросов к базе данных сокращено с ~51 до 4 запросов (улучшение на 92.2%), и это количество остается постоянным независимо от количества отображаемых объектов. Это значительно улучшит производительность страницы списка объектов, особенно при большом количестве записей.
|