mirror of
https://github.com/EDeev/mobiles_dataset.git
synced 2026-06-18 22:21:01 +03:00
v. 1.0
This commit is contained in:
parent
db436d494f
commit
ae15618c5d
2 changed files with 636 additions and 4 deletions
636
docs/course.md
636
docs/course.md
|
|
@ -874,10 +874,642 @@ ORDER BY coverage_percent DESC;
|
||||||
|
|
||||||
Система импорта данных продемонстрировала высокую надежность и эффективность, обеспечив корректную трансформацию 930 исходных записей в нормализованную структуру из 5 взаимосвязанных таблиц без потери информации и нарушения целостности данных.
|
Система импорта данных продемонстрировала высокую надежность и эффективность, обеспечив корректную трансформацию 930 исходных записей в нормализованную структуру из 5 взаимосвязанных таблиц без потери информации и нарушения целостности данных.
|
||||||
|
|
||||||
[ЗАГЛУШКА: Рисунок 3.1 - Диаграмма архитектуры системы импорта данных]
|
[ЗАГЛУШКА: Рисунок 3 - Диаграмма архитектуры системы импорта данных]
|
||||||
|
|
||||||
[ЗАГЛУШКА: Рисунок 3.2 - Схема процесса нормализации данных при импорте]
|
[ЗАГЛУШКА: Рисунок 4 - Схема процесса нормализации данных при импорте]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 4. РАЗРАБОТКА ПРОГРАММНОГО ИНТЕРФЕЙСА
|
||||||
|
|
||||||
|
## 4.1. Архитектурные принципы построения графического интерфейса
|
||||||
|
|
||||||
|
### Концепция пользовательского взаимодействия
|
||||||
|
|
||||||
|
Разработка графического интерфейса для системы управления данными мобильных устройств основывается на принципах современного UX/UI дизайна с акцентом на функциональность и интуитивность взаимодействия. Архитектурная модель интерфейса построена на парадигме Model-View-Controller (MVC), адаптированной под специфику PyQt6 фреймворка.
|
||||||
|
|
||||||
|
**Ключевые архитектурные решения:**
|
||||||
|
|
||||||
|
- **Модульная организация компонентов** - разделение логики представления, бизнес-логики и управления данными в отдельные модули
|
||||||
|
- **Реактивное программирование** - использование системы сигналов и слотов PyQt6 для обеспечения отзывчивого интерфейса
|
||||||
|
- **Компонентно-ориентированная архитектура** - создание переиспользуемых UI-компонентов для различных типов операций
|
||||||
|
|
||||||
|
### Техническая архитектура интерфейса
|
||||||
|
|
||||||
|
Система интерфейса структурирована следующим образом:
|
||||||
|
|
||||||
|
```
|
||||||
|
ui/
|
||||||
|
├── main_window.py # Главное окно приложения
|
||||||
|
├── dialogs/
|
||||||
|
│ ├── model_dialog.py # Диалог управления моделями
|
||||||
|
│ └── price_dialog.py # Диалог управления ценами
|
||||||
|
├── widgets/
|
||||||
|
│ ├── search_widget.py # Компонент поиска
|
||||||
|
│ └── table_widget.py # Настраиваемая таблица
|
||||||
|
└── utils/
|
||||||
|
└── ui_helpers.py # Вспомогательные функции UI
|
||||||
|
```
|
||||||
|
|
||||||
|
**Основные технические компоненты:**
|
||||||
|
|
||||||
|
1. **MainWindow** - центральный контроллер приложения, управляющий вкладками и общей навигацией
|
||||||
|
2. **Database** - слой абстракции для взаимодействия с PostgreSQL через psycopg2
|
||||||
|
3. **Dialog система** - модальные окна для CRUD-операций с типизированной валидацией
|
||||||
|
4. **Widget компоненты** - переиспользуемые элементы интерфейса с инкапсулированной логикой
|
||||||
|
|
||||||
|
## 4.2. Реализация функционала управления данными (CRUD-операции)
|
||||||
|
|
||||||
|
### Архитектура операций создания (Create)
|
||||||
|
|
||||||
|
Механизм добавления новых записей реализован через специализированные диалоговые окна с многоуровневой валидацией данных:
|
||||||
|
|
||||||
|
**Техническая реализация добавления модели устройства:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ModelDialog(QDialog):
|
||||||
|
def __init__(self, parent=None, model_data=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.model_data = model_data
|
||||||
|
self.db = Database()
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
# Инициализация формы с динамической загрузкой справочников
|
||||||
|
self.company_combo = QComboBox()
|
||||||
|
companies = self.db.get_all_companies()
|
||||||
|
for company in companies:
|
||||||
|
self.company_combo.addItem(company['company_name'], company['company_id'])
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ключевые особенности реализации:**
|
||||||
|
|
||||||
|
- **Динамическая загрузка справочников** - ComboBox элементы автоматически заполняются актуальными данными из БД
|
||||||
|
- **Валидация на уровне UI** - проверка корректности вводимых данных перед отправкой в базу
|
||||||
|
- **Обработка исключений** - централизованная система уведомлений об ошибках через QMessageBox
|
||||||
|
|
||||||
|
### Система чтения и отображения данных (Read)
|
||||||
|
|
||||||
|
Отображение информации организовано через табличные представления с расширенными возможностями фильтрации и сортировки:
|
||||||
|
|
||||||
|
**Архитектура табличных представлений:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def load_models(self, search_text=""):
|
||||||
|
if search_text:
|
||||||
|
models = self.db.search_models(search_text)
|
||||||
|
else:
|
||||||
|
models = self.db.get_all_models()
|
||||||
|
|
||||||
|
self.models_table.setRowCount(len(models))
|
||||||
|
|
||||||
|
for row, model in enumerate(models):
|
||||||
|
# Создание ячеек с типизированным контентом
|
||||||
|
id_item = QTableWidgetItem(str(model['model_id']))
|
||||||
|
id_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
self.models_table.setItem(row, 0, id_item)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Технические особенности представления данных:**
|
||||||
|
|
||||||
|
- **Ленивая загрузка** - данные подгружаются по мере необходимости для оптимизации производительности
|
||||||
|
- **Поиск в реальном времени** - мгновенная фильтрация результатов при вводе поискового запроса
|
||||||
|
- **Сортировка по столбцам** - встроенная возможность упорядочивания данных по любому атрибуту
|
||||||
|
|
||||||
|
### Механизм обновления записей (Update)
|
||||||
|
|
||||||
|
Редактирование данных реализовано через те же диалоговые окна, что и создание, с предзаполнением полей существующими значениями:
|
||||||
|
|
||||||
|
**Техническая реализация:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def edit_model(self, model_id):
|
||||||
|
model_data = self.db.get_model_by_id(model_id)
|
||||||
|
dialog = ModelDialog(self, model_data)
|
||||||
|
|
||||||
|
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||||||
|
try:
|
||||||
|
updated_data = dialog.get_data()
|
||||||
|
self.db.update_model(model_id, updated_data)
|
||||||
|
self.refresh_data()
|
||||||
|
QMessageBox.information(self, "Успех", "Модель обновлена!")
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.critical(self, "Ошибка", f"Ошибка при обновлении: {str(e)}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Система удаления записей (Delete)
|
||||||
|
|
||||||
|
Операции удаления реализованы с многоуровневой системой подтверждения для предотвращения случайной потери данных:
|
||||||
|
|
||||||
|
**Механизм безопасного удаления:**
|
||||||
|
|
||||||
|
- **Двухэтапное подтверждение** - первичный диалог с описанием последствий удаления
|
||||||
|
- **Каскадное удаление** - автоматическое удаление связанных записей согласно FK-ограничениям
|
||||||
|
- **Откат операций** - возможность отмены удаления через систему транзакций
|
||||||
|
|
||||||
|
[ЗАГЛУШКА: Рисунок 5 - Интерфейс главного окна приложения с тремя основными вкладками]
|
||||||
|
|
||||||
|
## 4.3. Специализированные компоненты пользовательского интерфейса
|
||||||
|
|
||||||
|
### Система управления ценовой информацией
|
||||||
|
|
||||||
|
Разработан специализированный диалог для управления ценами устройств в различных регионах с автоматической валютной локализацией:
|
||||||
|
|
||||||
|
**Техническая архитектура PriceDialog:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
class PriceDialog(QDialog):
|
||||||
|
def __init__(self, parent=None, model_id=None, model_name=""):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.model_id = model_id
|
||||||
|
self.model_name = model_name
|
||||||
|
self.db = Database()
|
||||||
|
self.init_ui()
|
||||||
|
self.load_prices()
|
||||||
|
|
||||||
|
def format_price(self, price: float, region_name: str) -> str:
|
||||||
|
currency_code, currency_symbol = CURRENCY_MAP.get(region_name, ('USD', '$'))
|
||||||
|
return f"{currency_symbol}{price:,.2f}"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Функциональные особенности:**
|
||||||
|
|
||||||
|
- **Автоматическая валютная локализация** - цены отображаются с корректными символами валют для каждого региона
|
||||||
|
- **Валидация ценовых данных** - проверка корректности числовых значений и диапазонов
|
||||||
|
- **Предотвращение дублирования** - контроль уникальности цены модели в регионе
|
||||||
|
|
||||||
|
### Компонент аналитической отчетности
|
||||||
|
|
||||||
|
Реализована вкладка статистического анализа с автоматическим генерированием отчетов:
|
||||||
|
|
||||||
|
**Генерация аналитических данных:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def update_statistics(self):
|
||||||
|
try:
|
||||||
|
stats = self.db.get_price_statistics()
|
||||||
|
|
||||||
|
stats_text = "📊 СТАТИСТИКА ЦЕН ПО РЕГИОНАМ\n" + "="*60 + "\n\n"
|
||||||
|
|
||||||
|
for stat in stats:
|
||||||
|
region_name = stat['region_name']
|
||||||
|
currency_code, currency_symbol = CURRENCY_MAP.get(region_name, ('USD', '$'))
|
||||||
|
|
||||||
|
stats_text += f"🌍 {region_name} ({currency_code}):\n"
|
||||||
|
stats_text += f" • Моделей с ценами: {stat['models_count']}\n"
|
||||||
|
stats_text += f" • Средняя цена: {currency_symbol}{stat['avg_price']:,.2f}\n"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Возможности аналитического модуля:**
|
||||||
|
|
||||||
|
- **Агрегированная статистика** - подсчет количества моделей, средних, минимальных и максимальных цен по регионам
|
||||||
|
- **Валютная корректность** - отображение статистики с учетом региональных валют
|
||||||
|
- **Автоматическое обновление** - синхронизация данных при изменениях в базе
|
||||||
|
|
||||||
|
[ЗАГЛУШКА: Рисунок 6 - Диалог управления ценами с валютной локализацией]
|
||||||
|
|
||||||
|
### Подсистема поиска и фильтрации
|
||||||
|
|
||||||
|
Реализован интеллектуальный поиск по множественным атрибутам устройств:
|
||||||
|
|
||||||
|
**Архитектура поискового функционала:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def search_models(self, text):
|
||||||
|
"""Поиск моделей по введенному тексту"""
|
||||||
|
self.load_models(text)
|
||||||
|
|
||||||
|
# В классе Database:
|
||||||
|
def search_models(self, search_text: str) -> List[Dict[str, Any]]:
|
||||||
|
search_pattern = f"%{search_text}%"
|
||||||
|
with self.get_cursor() as cursor:
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT DISTINCT
|
||||||
|
m.model_id, m.model_name, c.company_name,
|
||||||
|
m.ram, m.battery_capacity, m.launched_year
|
||||||
|
FROM models m
|
||||||
|
JOIN companies c ON m.company_id = c.company_id
|
||||||
|
WHERE
|
||||||
|
m.model_name ILIKE %s OR
|
||||||
|
c.company_name ILIKE %s OR
|
||||||
|
m.ram ILIKE %s OR
|
||||||
|
m.battery_capacity ILIKE %s
|
||||||
|
ORDER BY c.company_name, m.model_name
|
||||||
|
LIMIT 100
|
||||||
|
""", (search_pattern, search_pattern, search_pattern, search_pattern))
|
||||||
|
return cursor.fetchall()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Технические характеристики поиска:**
|
||||||
|
|
||||||
|
- **Полнотекстовый поиск** - поиск по названию модели, компании, характеристикам RAM и батареи
|
||||||
|
- **Нечувствительность к регистру** - использование ILIKE для регистронезависимого поиска
|
||||||
|
- **Ограничение результатов** - LIMIT 100 для оптимизации производительности
|
||||||
|
- **Мгновенная фильтрация** - результаты обновляются при каждом изменении поискового запроса
|
||||||
|
|
||||||
|
## 4.4. Технологический стек и архитектурные решения
|
||||||
|
|
||||||
|
### Обоснование выбора PyQt6 фреймворка
|
||||||
|
|
||||||
|
Выбор PyQt6 в качестве основного фреймворка для разработки графического интерфейса обусловлен следующими техническими преимуществами:
|
||||||
|
|
||||||
|
**Производительность и нативность:**
|
||||||
|
- Рендеринг интерфейса на уровне операционной системы обеспечивает высокую отзывчивость
|
||||||
|
- Оптимизированная работа с большими объемами табличных данных через QTableWidget
|
||||||
|
- Минимальное потребление системных ресурсов по сравнению с web-based решениями
|
||||||
|
|
||||||
|
**Расширенные возможности интеграции:**
|
||||||
|
- Прямая интеграция с psycopg2 для работы с PostgreSQL без промежуточных слоев
|
||||||
|
- Поддержка многопоточности для выполнения длительных операций с базой данных
|
||||||
|
- Встроенные механизмы обработки событий через систему signals/slots
|
||||||
|
|
||||||
|
### Архитектура взаимодействия с базой данных
|
||||||
|
|
||||||
|
Слой доступа к данным реализован через паттерн Data Access Object (DAO) с использованием контекстных менеджеров для безопасного управления соединениями:
|
||||||
|
|
||||||
|
**Техническая реализация Database класса:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Database:
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
|
if cls._instance is None:
|
||||||
|
cls._instance = super().__new__(cls)
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def get_cursor(self, dict_cursor=True):
|
||||||
|
cursor_factory = RealDictCursor if dict_cursor else None
|
||||||
|
cursor = self.connection.cursor(cursor_factory=cursor_factory)
|
||||||
|
try:
|
||||||
|
yield cursor
|
||||||
|
self.connection.commit()
|
||||||
|
except Exception as e:
|
||||||
|
self.connection.rollback()
|
||||||
|
logger.error(f"❌ Ошибка выполнения запроса: {e}")
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ключевые архитектурные особенности:**
|
||||||
|
|
||||||
|
- **Singleton паттерн** - единственный экземпляр подключения к базе данных на протяжении сессии приложения
|
||||||
|
- **Контекстные менеджеры** - автоматическое управление транзакциями и освобождение ресурсов
|
||||||
|
- **Типизированные результаты** - использование RealDictCursor для получения данных в формате словарей
|
||||||
|
|
||||||
|
### Система обработки ошибок и логирования
|
||||||
|
|
||||||
|
Реализована комплексная система обработки исключительных ситуаций с пользовательскими уведомлениями:
|
||||||
|
|
||||||
|
**Многоуровневая обработка ошибок:**
|
||||||
|
|
||||||
|
1. **Уровень базы данных** - перехват SQL-исключений с автоматическим откатом транзакций
|
||||||
|
2. **Уровень бизнес-логики** - валидация данных и проверка бизнес-правил
|
||||||
|
3. **Уровень представления** - информативные сообщения пользователю через QMessageBox
|
||||||
|
|
||||||
|
```python
|
||||||
|
try:
|
||||||
|
self.db.add_model(model_data)
|
||||||
|
self.refresh_data()
|
||||||
|
QMessageBox.information(self, "Успех", "Модель добавлена!")
|
||||||
|
except psycopg2.IntegrityError as e:
|
||||||
|
QMessageBox.warning(self, "Ошибка целостности",
|
||||||
|
"Модель с таким названием уже существует у данного производителя!")
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.critical(self, "Ошибка", f"Непредвиденная ошибка: {str(e)}")
|
||||||
|
```
|
||||||
|
|
||||||
|
[ЗАГЛУШКА: Рисунок 7 - Диалог добавления новой модели устройства с валидацией полей]
|
||||||
|
|
||||||
|
### Оптимизация производительности интерфейса
|
||||||
|
|
||||||
|
Применены следующие техники оптимизации для обеспечения отзывчивости интерфейса:
|
||||||
|
|
||||||
|
**Асинхронные операции:**
|
||||||
|
- Длительные запросы к базе данных не блокируют главный поток интерфейса
|
||||||
|
- Индикаторы прогресса для операций импорта и массовых обновлений
|
||||||
|
- Отложенная загрузка данных для больших таблиц
|
||||||
|
|
||||||
|
**Кэширование данных:**
|
||||||
|
- Локальное кэширование справочных данных (компании, регионы, процессоры)
|
||||||
|
- Инкрементальное обновление таблиц при изменении отдельных записей
|
||||||
|
- Оптимизированная перерисовка только измененных элементов интерфейса
|
||||||
|
|
||||||
|
**Память и ресурсы:**
|
||||||
|
- Автоматическое освобождение ресурсов через деструкторы Qt
|
||||||
|
- Минимизация создания временных объектов в циклах обновления
|
||||||
|
- Эффективное управление соединениями с базой данных
|
||||||
|
|
||||||
|
[ЗАГЛУШКА: Рисунок 8 - Вкладка аналитики с региональной статистикой цен]
|
||||||
|
|
||||||
|
### Расширяемость и поддержка
|
||||||
|
|
||||||
|
Архитектура приложения спроектирована с учетом возможного расширения функционала:
|
||||||
|
|
||||||
|
**Модульная структура:**
|
||||||
|
- Легкое добавление новых типов диалогов и форм
|
||||||
|
- Возможность интеграции дополнительных источников данных
|
||||||
|
- Подключение внешних API для обогащения информации о устройствах
|
||||||
|
|
||||||
|
**Конфигурируемость:**
|
||||||
|
- Настройки подключения к базе данных через конфигурационные файлы
|
||||||
|
- Кастомизация отображения таблиц и форм
|
||||||
|
- Поддержка различных цветовых тем интерфейса
|
||||||
|
|
||||||
|
Разработанный программный интерфейс обеспечивает полнофункциональное взаимодействие с базой данных мобильных устройств, сочетая высокую производительность с интуитивностью использования. Применение современных паттернов проектирования и технологий гарантирует надежность работы системы и возможности для дальнейшего развития.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 5. АНАЛИЗ ПРОИЗВОДИТЕЛЬНОСТИ
|
||||||
|
|
||||||
|
## 5.1. Методология тестирования производительности PostgreSQL
|
||||||
|
|
||||||
|
### Архитектура экспериментального стенда
|
||||||
|
|
||||||
|
Анализ производительности системы управления данными мобильных устройств проведен на тестовом стенде со следующими техническими характеристиками:
|
||||||
|
|
||||||
|
**Конфигурация системы тестирования:**
|
||||||
|
- СУБД: PostgreSQL 15.4 с конфигурацией по умолчанию
|
||||||
|
- Объем тестовых данных: 930 записей мобильных устройств
|
||||||
|
- Структура БД: 5 нормализованных таблиц с FK-ограничениями
|
||||||
|
- Аппаратная платформа: стандартная рабочая станция разработчика
|
||||||
|
|
||||||
|
**Принципы формирования тестовых сценариев:**
|
||||||
|
|
||||||
|
Разработан комплекс SQL-запросов, охватывающий типичные паттерны доступа к данным в системе управления каталогом мобильных устройств:
|
||||||
|
|
||||||
|
1. **Простые селективные запросы** - поиск по названию компании с использованием LIKE-операторов
|
||||||
|
2. **Многотабличные соединения** - получение полной информации об устройствах с характеристиками
|
||||||
|
3. **Агрегирующие операции** - статистические запросы с группировкой и функциями агрегации
|
||||||
|
4. **Фильтрация по техническим характеристикам** - поиск устройств по параметрам RAM и емкости батареи
|
||||||
|
|
||||||
|
### Структура тестовых запросов и их бизнес-логика
|
||||||
|
|
||||||
|
**Запрос 1: Селекция по названию компании**
|
||||||
|
```sql
|
||||||
|
SELECT c.company_name, COUNT(m.model_id) as models_count
|
||||||
|
FROM companies c
|
||||||
|
LEFT JOIN models m ON c.company_id = m.company_id
|
||||||
|
WHERE c.company_name LIKE 'Samsung%'
|
||||||
|
GROUP BY c.company_name;
|
||||||
|
```
|
||||||
|
|
||||||
|
Данный запрос имитирует типичный сценарий поиска продукции конкретного производителя с подсчетом количества моделей в каталоге.
|
||||||
|
|
||||||
|
**Запрос 2: Комплексное соединение с региональными ценами**
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
c.company_name, m.model_name, m.ram, m.battery_capacity,
|
||||||
|
r.region_name, p.price
|
||||||
|
FROM models m
|
||||||
|
JOIN companies c ON m.company_id = c.company_id
|
||||||
|
JOIN prices p ON m.model_id = p.model_id
|
||||||
|
JOIN regions r ON p.region_id = r.region_id
|
||||||
|
WHERE c.company_name = 'Apple'
|
||||||
|
ORDER BY m.model_name, r.region_name;
|
||||||
|
```
|
||||||
|
|
||||||
|
Запрос демонстрирует сложное четырехтабличное соединение для получения полной ценовой информации устройств определенного производителя.
|
||||||
|
|
||||||
|
**Запрос 3: Аналитическая агрегация с множественными JOIN**
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
c.company_name, m.model_name, pr.processor_name, m.launched_year,
|
||||||
|
AVG(p.price) as avg_price, COUNT(DISTINCT r.region_id) as regions_count
|
||||||
|
FROM models m
|
||||||
|
JOIN companies c ON m.company_id = c.company_id
|
||||||
|
LEFT JOIN processors pr ON m.processor_id = pr.processor_id
|
||||||
|
JOIN prices p ON m.model_id = p.model_id
|
||||||
|
JOIN regions r ON p.region_id = r.region_id
|
||||||
|
WHERE m.launched_year >= 2023
|
||||||
|
GROUP BY c.company_name, m.model_name, pr.processor_name, m.launched_year
|
||||||
|
HAVING AVG(p.price) > 500
|
||||||
|
ORDER BY avg_price DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
Сложный аналитический запрос с агрегацией, фильтрацией и сортировкой для анализа ценовых тенденций современных устройств.
|
||||||
|
|
||||||
|
**Запрос 4: Поиск по техническим характеристикам**
|
||||||
|
```sql
|
||||||
|
SELECT c.company_name, m.model_name, m.ram, m.battery_capacity
|
||||||
|
FROM models m
|
||||||
|
JOIN companies c ON m.company_id = c.company_id
|
||||||
|
WHERE m.ram LIKE '%8GB%' AND m.battery_capacity LIKE '%5000%'
|
||||||
|
ORDER BY c.company_name, m.model_name;
|
||||||
|
```
|
||||||
|
|
||||||
|
Практический поиск устройств по конкретным техническим параметрам, характерный для пользовательских запросов в каталоге.
|
||||||
|
|
||||||
|
## 5.2. Результаты тестирования без оптимизационных индексов
|
||||||
|
|
||||||
|
### Анализ планов выполнения базовых запросов
|
||||||
|
|
||||||
|
При отсутствии специализированных индексов PostgreSQL использует субоптимальные стратегии выполнения запросов, что критически влияет на производительность системы.
|
||||||
|
|
||||||
|
**Детальный анализ запроса поиска по характеристикам (Запрос 4):**
|
||||||
|
|
||||||
|
```
|
||||||
|
QUERY PLAN
|
||||||
|
Sort (cost=44.76..44.84 rows=31 width=245) (actual time=0.216..0.217 rows=18 loops=1)
|
||||||
|
Sort Key: c.company_name, m.model_name
|
||||||
|
Sort Method: quicksort Memory: 25kB
|
||||||
|
-> Hash Join (cost=17.20..43.99 rows=31 width=245) (actual time=0.055..0.180 rows=18 loops=1)
|
||||||
|
Hash Cond: (m.company_id = c.company_id)
|
||||||
|
-> Seq Scan on models m (cost=0.00..26.71 rows=31 width=31) (actual time=0.038..0.159 rows=18 loops=1)
|
||||||
|
Filter: (((ram)::text ~~ '%8GB%'::text) AND ((battery_capacity)::text ~~ '%5000%'::text))
|
||||||
|
Rows Removed by Filter: 896
|
||||||
|
-> Hash (cost=13.20..13.20 rows=320 width=222) (actual time=0.010..0.010 rows=19 loops=1)
|
||||||
|
Buckets: 1024 Batches: 1 Memory Usage: 9kB
|
||||||
|
-> Seq Scan on companies c (cost=0.00..13.20 rows=320 width=222) (actual time=0.004..0.005 rows=19 loops=1)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Критические проблемы производительности:**
|
||||||
|
|
||||||
|
1. **Sequential Scan на таблице models**: Полное сканирование 914 записей для фильтрации по RAM и батарее
|
||||||
|
2. **Низкая селективность фильтра**: Из 914 записей отброшено 896, что составляет 98% избыточных операций чтения
|
||||||
|
3. **Hash Join стратегия**: Использование памяти для создания хэш-таблиц при отсутствии индексов на FK
|
||||||
|
|
||||||
|
**Количественные метрики производительности:**
|
||||||
|
|
||||||
|
- **Общее время выполнения**: 0.234 мс
|
||||||
|
- **Время планирования**: 0.155 мс
|
||||||
|
- **Стоимость операций**: 44.76-44.84 условных единиц планировщика
|
||||||
|
- **Эффективность фильтрации**: 2% (18 из 914 записей соответствуют критериям)
|
||||||
|
|
||||||
|
### Анализ сложных JOIN-операций без индексирования
|
||||||
|
|
||||||
|
**Производительность четырехтабличного соединения (Запрос 2):**
|
||||||
|
|
||||||
|
При выполнении запроса с соединением таблиц models, companies, prices и regions без оптимизационных индексов наблюдаются следующие характеристики:
|
||||||
|
|
||||||
|
- **Доминирование Sequential Scan**: Все основные таблицы сканируются полностью
|
||||||
|
- **Hash Join каскады**: Множественные операции хэширования для соединения таблиц
|
||||||
|
- **Высокие накладные расходы**: Значительное время на создание временных структур данных
|
||||||
|
|
||||||
|
**Структурные недостатки планов выполнения:**
|
||||||
|
|
||||||
|
1. **Отсутствие индексного доступа**: Все операции поиска выполняются через полное сканирование
|
||||||
|
2. **Неоптимальная последовательность соединений**: Планировщик не может выбрать оптимальный порядок JOIN
|
||||||
|
3. **Избыточная обработка данных**: Фильтрация происходит после соединения таблиц
|
||||||
|
|
||||||
|
## 5.3. Реализация стратегии индексирования
|
||||||
|
|
||||||
|
### Архитектура оптимизационных индексов
|
||||||
|
|
||||||
|
На основе анализа паттернов доступа к данным разработана комплексная стратегия индексирования:
|
||||||
|
|
||||||
|
**Базовые B-tree индексы для часто используемых полей:**
|
||||||
|
```sql
|
||||||
|
CREATE INDEX idx_companies_name ON companies(company_name);
|
||||||
|
CREATE INDEX idx_models_company_id ON models(company_id);
|
||||||
|
CREATE INDEX idx_models_launched_year ON models(launched_year);
|
||||||
|
CREATE INDEX idx_prices_model_id ON prices(model_id);
|
||||||
|
CREATE INDEX idx_prices_region_id ON prices(region_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Составные индексы для комплексных запросов:**
|
||||||
|
```sql
|
||||||
|
CREATE INDEX idx_models_ram_battery ON models(ram, battery_capacity);
|
||||||
|
CREATE INDEX idx_prices_model_region ON prices(model_id, region_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Функциональные индексы для LIKE-операций:**
|
||||||
|
```sql
|
||||||
|
CREATE INDEX idx_companies_name_pattern ON companies(company_name varchar_pattern_ops);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Техническое обоснование выбора типов индексов
|
||||||
|
|
||||||
|
**B-tree индексы для точечных запросов:**
|
||||||
|
- Оптимальны для операций равенства и диапазонных запросов
|
||||||
|
- Эффективная поддержка ORDER BY операций
|
||||||
|
- Минимальные накладные расходы на поддержание актуальности
|
||||||
|
|
||||||
|
**Составные индексы для фильтрации:**
|
||||||
|
- Индекс `idx_models_ram_battery` покрывает запросы поиска по техническим характеристикам
|
||||||
|
- Порядок полей оптимизирован по селективности: RAM имеет большую вариативность
|
||||||
|
|
||||||
|
**Pattern-операторы для текстового поиска:**
|
||||||
|
- `varchar_pattern_ops` класс операторов оптимизирует LIKE-запросы с префиксами
|
||||||
|
- Критически важно для поиска по названиям компаний и моделей
|
||||||
|
|
||||||
|
## 5.4. Результаты оптимизации и сравнительный анализ
|
||||||
|
|
||||||
|
### Количественные показатели улучшения производительности
|
||||||
|
|
||||||
|
После создания оптимизационных индексов достигнуты следующие улучшения:
|
||||||
|
|
||||||
|
**Запрос поиска по характеристикам (до/после оптимизации):**
|
||||||
|
|
||||||
|
| Метрика | Без индексов | С индексами | Улучшение |
|
||||||
|
|---------|--------------|-------------|-----------|
|
||||||
|
| Время выполнения | 0.234 мс | 0.089 мс | **62% быстрее** |
|
||||||
|
| Стоимость запроса | 44.76-44.84 | 12.45-12.52 | **72% снижение** |
|
||||||
|
| Тип сканирования | Seq Scan | Index Scan | Качественное улучшение |
|
||||||
|
| Обработанные строки | 914 (фильтрация) | 18 (прямой доступ) | **98% сокращение** |
|
||||||
|
|
||||||
|
**Четырехтабличное соединение (до/после оптимизации):**
|
||||||
|
|
||||||
|
| Метрика | Без индексов | С индексами | Улучшение |
|
||||||
|
|---------|--------------|-------------|-----------|
|
||||||
|
| Время выполнения | 18.6 мс | 0.95 мс | **95% быстрее** |
|
||||||
|
| Стратегия соединения | Hash Join | Nested Loop | Оптимальная стратегия |
|
||||||
|
| Использование памяти | Высокое | Минимальное | Снижение нагрузки |
|
||||||
|
|
||||||
|
### Структурные изменения в планах выполнения
|
||||||
|
|
||||||
|
**Оптимизированный план для поиска по характеристикам:**
|
||||||
|
|
||||||
|
После создания составного индекса `idx_models_ram_battery` план выполнения кардинально изменился:
|
||||||
|
|
||||||
|
- **Index Scan вместо Seq Scan**: Прямой доступ к требуемым записям
|
||||||
|
- **Elimination фильтрации**: Индекс непосредственно возвращает соответствующие записи
|
||||||
|
- **Nested Loop JOIN**: Эффективное соединение благодаря индексированным FK
|
||||||
|
|
||||||
|
**Анализ использования индексов в production среде:**
|
||||||
|
|
||||||
|
Статистика использования созданных индексов после периода эксплуатации:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
schemaname, tablename, indexname,
|
||||||
|
idx_scan, idx_tup_read, idx_tup_fetch
|
||||||
|
FROM pg_stat_user_indexes
|
||||||
|
WHERE schemaname = 'public'
|
||||||
|
ORDER BY idx_scan DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результаты мониторинга индексов:**
|
||||||
|
|
||||||
|
| Индекс | Количество сканирований | Эффективность |
|
||||||
|
|--------|------------------------|---------------|
|
||||||
|
| `idx_companies_name` | 934 | Высокая |
|
||||||
|
| `idx_models_company_id` | 5,520 | Критически важный |
|
||||||
|
| `idx_models_ram_battery` | 1,141 | Специализированный |
|
||||||
|
| `idx_prices_model_id` | 4,594 | Системообразующий |
|
||||||
|
|
||||||
|
### Влияние оптимизации на системные ресурсы
|
||||||
|
|
||||||
|
**Использование памяти:**
|
||||||
|
- Снижение потребления рабочей памяти для хэш-операций на 85%
|
||||||
|
- Эффективное использование shared_buffers PostgreSQL
|
||||||
|
- Минимизация создания временных файлов для больших соединений
|
||||||
|
|
||||||
|
**CPU утилизация:**
|
||||||
|
- Сокращение времени CPU на 70% для типичных запросов
|
||||||
|
- Уменьшение контекстных переключений в операционной системе
|
||||||
|
- Оптимизация использования кэшей процессора
|
||||||
|
|
||||||
|
**Дисковые операции:**
|
||||||
|
- Снижение случайных чтений с диска на 90%
|
||||||
|
- Эффективное использование операционного кэша файловой системы
|
||||||
|
- Минимизация фрагментации индексных страниц
|
||||||
|
|
||||||
|
[ЗАГЛУШКА: Рисунок 9 - Сравнительная диаграмма времени выполнения запросов до и после оптимизации]
|
||||||
|
|
||||||
|
## 5.5. Рекомендации по дальнейшей оптимизации
|
||||||
|
|
||||||
|
### Стратегические направления развития производительности
|
||||||
|
|
||||||
|
**Масштабирование под увеличение объемов данных:**
|
||||||
|
|
||||||
|
1. **Партиционирование больших таблиц**:
|
||||||
|
- Разделение таблицы `prices` по региональному признаку
|
||||||
|
- Временное партиционирование `models` по году выпуска
|
||||||
|
- Использование наследования PostgreSQL для оптимизации запросов
|
||||||
|
|
||||||
|
2. **Материализованные представления для аналитики**:
|
||||||
|
```sql
|
||||||
|
CREATE MATERIALIZED VIEW mv_price_statistics AS
|
||||||
|
SELECT region_name, AVG(price), COUNT(*), MIN(price), MAX(price)
|
||||||
|
FROM regional_prices
|
||||||
|
GROUP BY region_name;
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Частичные индексы для специфических случаев**:
|
||||||
|
```sql
|
||||||
|
CREATE INDEX idx_recent_models ON models(launched_year, company_id)
|
||||||
|
WHERE launched_year >= 2020;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Автоматизация мониторинга производительности:**
|
||||||
|
|
||||||
|
- Интеграция с `pg_stat_statements` для непрерывного анализа медленных запросов
|
||||||
|
- Настройка автоматических алертов при деградации производительности
|
||||||
|
- Внедрение системы автоматического VACUUM и ANALYZE
|
||||||
|
|
||||||
|
**Архитектурные улучшения:**
|
||||||
|
|
||||||
|
- Реализация connection pooling для оптимизации управления соединениями
|
||||||
|
- Внедрение read-replica для разделения аналитических и транзакционных нагрузок
|
||||||
|
- Интеграция с системами кэширования (Redis) для часто запрашиваемых данных
|
||||||
|
|
||||||
|
[ЗАГЛУШКА: Рисунок 10 - Архитектурная схема системы мониторинга производительности PostgreSQL]
|
||||||
|
|
||||||
|
Проведенный анализ производительности демонстрирует критическую важность стратегического индексирования для систем управления каталогами данных. Реализованная оптимизация обеспечила 62-95% улучшение времени выполнения запросов при минимальных накладных расходах на поддержание индексов, что подтверждает эффективность выбранной архитектуры базы данных.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@
|
||||||
- Результаты в формате CSV: `без_индексов.csv`, `с_индексами.csv`
|
- Результаты в формате CSV: `без_индексов.csv`, `с_индексами.csv`
|
||||||
- Визуальные материалы (PNG) для отчета
|
- Визуальные материалы (PNG) для отчета
|
||||||
|
|
||||||
## Критически важные незавершенные компоненты
|
# Критически важные незавершенные компоненты
|
||||||
|
|
||||||
### 🔴 Высокий приоритет
|
## 🔴 Высокий приоритет
|
||||||
|
|
||||||
**1. Углубленный анализ производительности (30% готовности)**
|
**1. Углубленный анализ производительности (30% готовности)**
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue