DON'T STOP AND CODE
92 subscribers
41 photos
1 video
1 file
109 links
Мой путь в программировании
#python

Для связи: @avagners
Download Telegram
Сейчас в парке Зарядье на II Фестивале юношеских оркестров мира.
[Другие проекты Apache, связанные с Hadoop]

Hadoop не существует в одиночку. Он окружён целым рядом проектов Apache, которые расширяют его возможности и предоставляют дополнительные инструменты для работы с большими данными.

Apache Hive:
Hive — это инструмент для выполнения SQL-запросов на данных, хранящихся в Hadoop. Он был разработан для того, чтобы аналитики и разработчики могли использовать привычный им язык SQL для работы с большими объёмами данных, хранящихся в HDFS. Hive отлично подходит для анализа структурированных данных и выполнения сложных запросов.

Apache HBase:
HBase — это распределённая, масштабируемая база данных NoSQL, которая работает поверх HDFS. Она предназначена для работы с большими объёмами данных в режиме реального времени и поддерживает как чтение, так и запись данных. HBase используется для хранения данных, требующих быстрой записи и доступа.

Apache Ambari:
Ambari — это инструмент для управления и мониторинга кластеров Hadoop. Он предоставляет простой и удобный веб-интерфейс для установки, настройки и управления кластерами Hadoop. С помощью Ambari можно отслеживать производительность системы, управлять конфигурациями и автоматизировать задачи администрирования.

Apache Tez:
Tez — это фреймворк, который оптимизирует выполнение заданий в Hadoop. Он был разработан как замена для MapReduce и позволяет выполнять сложные цепочки задач более эффективно и с меньшими задержками. Tez поддерживает выполнение DAG (Directed Acyclic Graph) задач, что делает его более гибким и производительным для различных аналитических приложений.

Apache Spark:
Spark — это мощный фреймворк для обработки данных, который может работать как самостоятельное решение, так и поверх Hadoop. В отличие от MapReduce, Spark поддерживает обработку данных в оперативной памяти, что делает его значительно быстрее для многих задач. Spark также поддерживает широкий спектр рабочих нагрузок, включая обработку в режиме реального времени, машинное обучение и анализ графов, что делает его универсальным инструментом для анализа данных.

Apache ZooKeeper:
ZooKeeper — это централизованная служба для управления конфигурацией, синхронизации распределённых приложений и обслуживания групповых служб. Он играет важную роль в обеспечении отказоустойчивости и управлении кластерами Hadoop.

Apache Sqoop:
Sqoop — это инструмент для передачи данных между Hadoop и реляционными базами данных. Он позволяет импортировать и экспортировать данные между HDFS и базами данных, такими как MySQL, PostgreSQL и другие.

———
Эти проекты, работающие вместе с Hadoop, создают мощную и гибкую экосистему для решения самых разнообразных задач, связанных с большими данными.

#BigData #Hadoop #HDFS #MapReduce #YARN #Hive #HBase #Ambari #Tez #Spark #ZooKeeper #Sqoop #IT
Начинаю знакомство с Java)
Завершил чтение книги Аниче Маурисио "Простое объектно-ориентированное проектирование: чистый и гибкий код." — СПб.: Питер, 2025. — 224 с.

Хорошая книга. Обобщает практические советы ООП-проектирования, помогающие сохранять простоту кодовой базы.

Не могу сказать что материал для меня оказался новым. Данная книга в любом случае обобщила и систематизировала те знания, которые я получил ранее.

Книгу легко читать. Рекомендую.

———
#coder #coding #programmer #stepbystep #шагзашагом #учусьпрограммировать #учусь #book
Please open Telegram to view this post
VIEW IN TELEGRAM
OSI (The Open Systems Interconnection model)

Сетевая модель OSI (The Open Systems Interconnection model)
— сетевая модель стека (магазина) сетевых протоколов OSI/ISO. Посредством данной модели различные сетевые устройства могут взаимодействовать друг с другом. Модель определяет различные уровни взаимодействия систем. Каждый уровень выполняет определённые функции при таком взаимодействии.

OSI состоит из двух основных частей:
- абстрактная модель сетевого взаимодействия (семиуровневая модель);
- набор специализированных протоколов взаимодействия;

Концепция семиуровневой модели была описана в работе Чарльза Бахмана. Данная модель подразделяет коммуникационную систему на уровни абстракции (англ. "abstraction layers"). В модели OSI средства взаимодействия делятся на семь уровней: прикладной, представления, сеансовый, транспортный, сетевой, канальный и физический.

Каждый уровень:
- имеет дело с совершенно определенным аспектом взаимодействия сетевых устройств;
- обслуживает уровень, находящийся непосредственно над ним, и обслуживается уровнем, находящимся под ним;
[Тренажерный зал]

Незаметно для себя у меня появилась сильная привычка ходить в тренажерный зал. Если пропускаю пару дней, то чувствую себя не очень).

Последние пол года посещаю зал практически ежедневно. Вечером, после работы.

Первые пол года ходил с тренером. Учился. Последние 7 месяцев хожу сам.

Хожу в зал просто так. Без каких-либо глобальных целей.
Сначала стремился толкнуть 100 кг в жиме лежа. Сейчас спокойно подхожу к штанге 110 кг. Для моих физических данных (рост - 190см, вес - 83кг, возраст - 32 года) считаю довольно достойным результатом.

Большим качком быть не хочу. Ничего дополнительно не употребляю (ну прям вообще ничего).
Для меня походы в зал - это прежде всего поддержание физической формы (с ментальной формой тоже помогает очень хорошо).

Сейчас я очень доволен своей физической формой. Последние несколько месяцев регулярно начал получать похвалу и комплименты в зале. Каждая тренировка начинается с беговой дорожки, заканчивается упражнениями на пресс. Также не забываю про день ног (это прям база).

Благодаря залу стал лучше прислушиваться к организму. Стал лучше спать.
В зале организм сразу дает понять, если ты что-то сделал неправильно накануне. 

___
Как у вас обстоят дела со спортом? Делитесь своими результатами/достижениями?
[Знакомство с DDD]

Начал проходить обучение по DDD (Domain Driven Design).
Крайне интересная тема.

Ниже прикладываю ссылку на статью как можно реализовать Value Object в Python.

https://dddinpython.hashnode.dev/value-objects-in-python
[Entity и Value Object в DDD]

Привет! В DDD сразу встречаешь два ключевых понятия — Entity и Value Object. Оба вроде как про данные, но ведут себя по-разному.

Что такое `Entity`?
Entity — это объект, который имеет уникальный идентификатор и жизненный цикл. Его идентичность важна, и она сохраняется на протяжении всего времени существования объекта. Например, пользователь в системе (User) — это Entity, потому что у него есть уникальный ID, и даже если его имя или email изменятся, это все равно будет тот же самый пользователь.

from dataclasses import dataclass, field
import uuid

@dataclass
class User:
name: str
email: str
id: uuid.UUID = field(default_factory=uuid.uuid4, init=False)

def __eq__(self, other):
if isinstance(other, User):
return self.id == other.id
return False

# Пример использования:
user1 = User("Иван", "ivan@example.com")
user2 = User("Иван", "ivan@example.com")

print(user1) # User(name='Иван', email='ivan@example.com', id=...)
print(user2) # User(name='Иван', email='ivan@example.com', id=...)
print(user1 == user2) # False, потому что ID разные


Что такое `Value Object`?
Value Object, в отличие от Entity, не имеет идентичности. Он определяется своими атрибутами, и если все атрибуты одинаковы, то два Value Object считаются равными. Value Object обычно неизменяемы (immutable), что делает их более предсказуемыми и безопасными в использовании.

from dataclasses import dataclass
import re

@dataclass(frozen=True)
class EmailAddress:
value: str

def __post_init__(self):
if not self._is_valid_email(self.value):
raise ValueError(f"Некорректный email: {self.value}")

@staticmethod
def _is_valid_email(email: str) -> bool:
pattern = r"^[\w\.-]+@[\w\.-]+\.\w+$"
return re.match(pattern, email) is not None

# Пример использования:
try:
email1 = EmailAddress("valid.email@example.com")
print(email1) # EmailAddress(value='valid.email@example.com')

email2 = EmailAddress("invalid-email") # Ошибка валидации!
except ValueError as e:
print(e)


Когда что использовать?
- Если объект уникален сам по себе — это Entity.
- Если важны только его значения — это Value Object.

Фишка DDD:
Хорошая практика — делать Value Objects иммутабельными и использовать их для инкапсуляции логики. Например, не просто string для email, а EmailAddress, который сразу валидирует значение.

Entity и Value Object — это мощные концепции, которые помогают структурировать код и делать его более предсказуемым. В Python их реализация может быть элегантной с использованием dataclasses.

#DDD #Python #Entity #ValueObject #Программирование
[Агрегаты в DDD: Организация сложности через границы]

В Domain-Driven Design (DDD) работа с сложными доменными моделями требует четкой структуры, чтобы избежать хаоса.
Агрегат (Aggregate) — один из ключевых паттернов DDD, который помогает управлять целостностью данных и упрощает взаимодействие с моделью.

Что такое Aggregate?

Агрегат — это кластер связанных объектов, рассматриваемых как единое целое.

Он объединяет:
1) Корень агрегата (Aggregate Root) — единственная точка входа для внешних взаимодействий.

2) Внутренние сущности (Entity) и value-объекты (ValueObject) — элементы, которые могут изменяться только через корень.

По своей сути агрегат - это тоже Entity.

Зачем нужны агрегаты?

- Консистентность данных
Агрегат гарантирует, что изменения внутри него соответствуют бизнес-правилам. Например, нельзя добавить OrderItem с отрицательной ценой — корень проверяет это.

- Границы транзакций
Изменения в рамках одного агрегата обычно выполняются в одной транзакции. Это упрощает управление конкурентным доступом.

- Сокрытие сложности
Внешние системы не знают о внутренней структуре агрегата — они работают только с корнем.

Ключевые принципы проектирования:

- Единый корень
Все внешние запросы идут через корень. Если нужно изменить дочерний объект — делайте это через методы корня.

- Инварианты внутри границ
Правила целостности (например, «максимум 10 товаров в заказе») должны соблюдаться внутри агрегата.

- Ссылки только на корни других агрегатов
Агрегаты не должны хранить ссылки на внутренние объекты чужих агрегатов — только на их корни (через идентификаторы).

Пример:
Агрегат Заказ (корень) включает элементы заказа (OrderItem), адрес доставки и методы для добавления/удаления товаров. Внешние системы обращаются только к Order, а не к OrderItem напрямую.

Ошибки при работе с агрегатами:

- Слишком большие агрегаты
Если агрегат включает десятки сущностей, это усложняет транзакции и повышает риск конфликтов.
Решение: Дробите агрегаты, ориентируясь на бизнес-контекст.

- Нарушение инкапсуляции
Прямое изменение дочерних объектов в обход корня ломает целостность.
Решение: Скрывайте внутренние структуры (private поля, методы только для корня).

Как определить границы агрегата?
- Ищите транзакционные границы — что должно изменяться атомарно?
- Анализируйте бизнес-инварианты — какие правила связывают объекты?
- Избегайте «анаемичных» агрегатов — они должны содержать логику, а не быть просто набором данных.

———
Итого

Агрегаты в DDD — это не просто группировка классов, а способ защитить целостность домена и управлять сложностью.

Правильно выбранные границы агрегатов делают код:
- Более понятным,
- Устойчивым к ошибкам,
- Легким для масштабирования.

Главное правило:
Если сомневаетесь — делайте агрегаты меньше. Четкие границы спасут в долгосрочной перспективе!

P.s.
Полезная ссылка про агрегаты: https://dddinpython.hashnode.dev/mastering-aggregates-in-domain-driven-design

#DDD #Python #Aggregate #Entity #ValueObject #Программирование
[Domain Services в DDD: Логика, которая не принадлежит агрегатам]
(Когда и зачем использовать доменные сервисы?)

Продолжаю знакомиться с DDD. Следующий паттерн Domain Services.

Domain Service - это класс, который реализует бизнес-правила, выходящие за рамки одного агрегата.

В Domain-Driven Design (DDD) не вся бизнес-логика уместна внутри агрегатов или сущностей.
Иногда операции:
- Затрагивают несколько агрегатов,
- Зависят от внешних систем (например, проверка кредитного рейтинга),
- Не имеют естественного места в какой-то одной сущности.

Для такой логики создают Domain Services (доменные сервисы).

Отличия от других сервисов в DDD
Domain Service — содержит только бизнес-логику, не зависит от инфраструктуры.
Application Service — оркестрирует вызовы Domain-сервисов и инфраструктуры (например, «создать заказ → сохранить в БД → отправить уведомление»).
Infrastructure Service — технические детали (отправка почты, запросы к API).

Когда использовать Domain Service?
Логика требует нескольких агрегатов.
Зависит от доменных правил, но не принадлежит ни одной сущности (например, проверка сложных условий).
Чистая бизнес-логика без инфраструктурных деталей.

Не используйте, если:
- Логика относится к одному агрегату (лучше поместить в агрегат).
- Нужен доступ к БД, API и т.д. (это Application/Infrastructure Service).

✔️ Плюсы:
- Четкое разделение ответственности.
- Удобство тестирования (чистая логика без побочных эффектов).

Минусы:
- Риск превращения в "God Object" (если сервис делает слишком много).

Domain Services — это мост между агрегатами для сложной доменной логики.

P.s.
Полезная ссылка по теме:
https://enterprisecraftsmanship.com/posts/domain-vs-application-services/

#DDD #DomainServices #CleanArchitecture
120 кг в жиме лёжа;
(мой вес 82,5 кг)

Недели 3 назад сделал несколько безуспешных попыток. Далее сказал себе, что не подойду к этому весу пока не буду уверенно работать со штангой 110 кг.

И вот позавчера (31 марта) впервые взял этот вес.

Получил много эмоций от достижения очередного результата)

#gym #life
[Памятка: как делать правильные тесты]

Раньше я писал юнит-тесты как будто "на автомате" — просто покрывал методы, проверял, что возвращается нужное значение, и считал, что всё ок.

Но это не совсем правильно. Тестировать методы ради покрытия — выглядит логично, но часто оказывается поверхностным и ненадёжным.

Например, я тестирую имплементацию, а не поведение.
Но при рефакторинге метод может быть переписан — и старый тест либо ломается (хотя логика осталась верной), либо ничего не заметит, если баг спрятался глубже.

Невозможно быстро понять по тестам, что именно гарантирует система.
Тесты по методам не объясняют, что система должна делать — только что она делает сейчас.

А свойства — это живое описание инвариантов кода. И это крайне важно.

Правильный подход — тестировать свойства поведения фичи, которые должны сохраняться независимо от реализации.

Вот что я теперь делаю:

1) Останавливаюсь и думаю: что вообще значит "правильно работает"?
Не метод за методом, а вся фича в целом.

2) Формулирую свойства корректности:
Например, "если policy создана — она должна быть доступна", "удаление policy делает её недоступной", и т.д.

3) Для каждого свойства выбираю способ тестирования:
Если можно покрыть юнит-тестами — пишу их. Если нужно — делаю фаззинг или просто руками проверяю.

4) Пишу тесты, которые проверяют именно эти свойства, а не случайные детали реализации.

Что изменилось?

- Тесты стало проще поддерживать: они не ломаются из-за мелких рефакторингов.
- Я лучше понимаю, зачем вообще эта фича нужна, а не просто "чтобы метод не падал".
- Реже ловлю баги в проде — потому что я реально проверяю смысл, а не поведение "по случайке".

#unittests #python #testdesign #tests
[Репозитории в DDD: как правильно работать с данными в доменном слое]

Привет! Сегодня разберём ещё одну важную концепцию Domain-Driven Design — Репозитории (Repositories). Когда я только начал изучать DDD, репозитории казались мне просто "прослойкой над базой данных". Давайте разберёмся, зачем они нужны и как их правильно использовать!

Репозиторий (Repository) — это абстракция, которая:
✔️ Инкапсулирует доступ к данным (БД, API, файлы и т. д.).
✔️ Предоставляет "коллекцию" доменных объектов (как если бы они хранились в памяти).
✔️ Работает только с Aggregate Roots (не с отдельными Entity или Value Object!).

Пример из жизни:
Если Order — это агрегат, то OrderRepository позволяет:
- Сохранять заказ (save).
- Загружать заказ по ID (find_by_id).
- Искать заказы по критериям (find_all_by_customer).

Но он НЕ даёт прямого доступа к OrderItem — только через корень (Order).

Ниже пример кода.
from abc import ABC, abstractmethod
from uuid import UUID
from typing import List, Optional

from .order import Order # Агрегат

class OrderRepository(ABC):
"""Абстракция репозитория"""
@abstractmethod
def save(self, order: Order) -> None:
pass

@abstractmethod
def find_by_id(self, order_id: UUID) -> Optional[Order]:
pass

@abstractmethod
def find_all_by_customer(self, customer_id: UUID) -> List[Order]:
pass


from sqlalchemy.orm import Session

class SQLOrderRepository(OrderRepository):
"""SQL реализация (через SQLAlchemy)"""
def __init__(self, session: Session):
self.session = session

def save(self, order: Order) -> None:
self.session.add(order)
self.session.commit()

def find_by_id(self, order_id: UUID) -> Optional[Order]:
return self.session.query(Order).filter_by(order_id=order_id).first()

def find_all_by_customer(self, customer_id: UUID) -> List[Order]:
return self.session.query(Order).filter_by(customer_id=customer_id).all()


Почему репозитории — это важно?

1) Отделение домена от инфраструктуры
Домен не знает, как хранятся данные (БД, API, CSV и т. д.).

2) Гибкость
Можно легко поменять базу данных, не трогая доменную логику.

3) Соблюдение DDD-принципов
Работа только с агрегатами, а не с отдельными таблицами БД.

Где должны находиться репозитории в структуре проекта?

Репозитории относятся к инфраструктурному слою, но их интерфейсы (абстракции) определяются в доменном слое.

Ниже пример классической структуры проекта по слоям DDD.
```bash
src/
├── domain/
│ ├── models/
│ ├── repositories/
│ └── services/

├── infrastructure/
│ ├── db/
│ ├── repositories/
│ └── caching/

├── application/
│ └── services/

└── presentation/

```

Типичные ошибки
Репозиторий для каждой Entity
Репозиторий должен быть только для Aggregate Root!

Возвращение DTO вместо доменных объектов
Репозиторий должен возвращать Order, а не OrderData.

Нарушение CQRS
Для запросов (Read) иногда лучше использовать отдельные запросы в cлое приложения, а не репозитории.

P.s.
Полезные ссылки по теме:
1) https://dddinpython.hashnode.dev/implementing-the-repository-pattern
2) https://dddinpython.hashnode.dev/implementing-the-repository-pattern-using-sqlalchemy

#DDD #Repository #DomainDrivenDesign #Программирование #Python
[Use Case в DDD: как проектировать сценарии взаимодействия с системой]

Привет! Сегодня поговорим про Use Case (Сценарии использования) — один из ключевых элементов DDD и чистой архитектуры.

1. Что такое Use Case?
Use Case (Сценарий использования) — это:
✔️ Описание конкретного бизнес-действия (например, "Оформление заказа", "Отмена бронирования").
✔️ Изолированная логика, которая координирует работу домена и инфраструктуры.
✔️ Мост между presentation (API/UI) и domain (бизнес-правила).

Примеры:
CreateOrderUseCase → создание заказа.
CancelBookingUseCase → отмена бронирования.
ProcessPaymentUseCase → обработка платежа.

2. Где находятся Use Case в структуре проекта?

Они относятся к application-слою (слое приложения):
src/
├── domain/
├── application/ # Use Cases + Application Services/CQS
│ ├── use_cases/
│ │ ├── commands/
│ │ └── queries/
│ └── services/
├── infrastructure/
└── api/


3. Пример use case "Создание заказа"
# /delivery/core/application/use_cases/commands/create_order/create_order_handler.py
from dataclasses import dataclass

from core.domain.model.order_aggregate.order import Order
from core.domain.model.shared_kernel.location import Location
from core.application.use_cases.commands.create_order.create_order_command import CreateOrderCommand
from infrastructure.adapters.postgres.unit_of_work import UnitOfWork


@dataclass
class CreateOrderCommandHandler:
unit_of_work: UnitOfWork

def handle(self, massege: CreateOrderCommand) -> None:

# Получаем геопозицию из Geo (пока ставим рандомное значение)
location = Location.create_random_location()

# Создаем заказ
order = Order(
order_id=massege.basket_id, # ID заказа совпадает с ID корзины
location=location
)

# Сохраняем
with self.unit_of_work as uow:
uow.orders.add(order)


4. Почему Use Case — это важно?
- Чёткое разделение ответственности
Presentation-слой (API/CLI) не должен содержать бизнес-логику.
Domain-слой не должен знать о внешних сервисах (API, БД).

- Упрощение тестирования
Use Case можно тестировать изолированно, подменяя репозитории на заглушки.

- Гибкость
Один Use Case может быть вызван из разных мест: API, CLI, фоновой задачи.

- Документирование системы
Названия Use Cases (CreateOrder, CancelBooking) явно описывают, что делает система.

5. Типичные ошибки

Use Case = "God Object"
Не нужно пихать всю логику в один Use Case. Разбивайте на мелкие сценарии.

Логика в контроллерах
Код вида if user.is_admin: ... должен быть в Use Case или домене, не в API.

#DDD #UseCase #CleanArchitecture #Python
[Input Adapters в DDD: как внешний мир общается с приложением]

Привет! Сегодня про Input Adapters — элемент гексагональной архитектуры (и DDD), который отвечает за преобразование внешних запросов (HTTP, CLI, события) в команды приложения.

1. Что это такое?

Input Adapter — это не только про REST-эндпоинты, а это единая точка входа для всех внешних взаимодействий.

Он:
- Парсит входящие данные (JSON, protobuf, CLI-аргументы).
- Валидирует их (например, через Pydantic).
- Вызывает Use Case (Command или Query).
- Не содержит бизнес-логики (это задача домена).

Примеры Input Adapters:
- REST API (FastAPI, Django View).
- CLI-команды (Click, Typer).
- Обработчики событий (Kafka Consumer).
- WebSocket-хэндлеры.

Ниже пример REST API
# presentation/api/rest/order_adapters.py
from fastapi import APIRouter, Depends

from application.commands import CreateOrderCommand
from presentation.schemas import OrderCreateRequest

router = APIRouter()

@router.post("/orders")
async def create_order(
request: OrderCreateRequest, # Pydantic-модель для валидации
command: CreateOrderCommand = Depends(), # Use Case
):
# Преобразуем запрос в DTO (без бизнес-логики!)
order_id = command.execute(
user_id=request.user_id,
items=[item.to_domain() for item in request.items]
)
return {"order_id": order_id}


2. Где находятся Input Adapters в структуре проекта?

Они относятся к presentation-слою, но могут выноситься в отдельный модуль для сложных сценариев:

src/
├── domain/
├── application/
├── infrastructure/
└── presentation/ # Input Adapters
├── api/ # HTTP-адаптеры
│ ├── rest/ # REST (FastAPI)
│ └── graphql/ # GraphQL
├── cli/ # CLI-адаптеры (Click)
└── events/ # Обработчики событий (Kafka, RabbitMQ)


3. Почему Input Adapters — это важно?

- Изоляция домена
Домен не знает, откуда пришёл запрос (HTTP, Kafka или CLI).

- Гибкость
Можно добавить новый адаптер (например, gRPC), не меняя Use Case.

- Тестируемость
Адаптеры легко тестировать в изоляции (например, мокая Use Case).

- Согласованность
Все входные данные проходят одинаковую валидацию перед передачей в Use Case.

4. Типичные ошибки

Бизнес-логика в адаптерах
Код вида if user.role == "admin" должен быть в домене, а не в REST-хэндлере.

Прямая работа с репозиториями
Адаптер вызывает только Use Case, не лезет в БД напрямую.

5. Вывод
Input Adapters — это "входные ворота" приложения, которые:
🔹 Преобразуют внешние запросы в команды/запросы.
🔹 Не содержат логики (только парсинг и валидацию).
🔹 Делают систему гибкой к изменениям протоколов.

#DDD #CleanArchitecture #InputAdapters #Python
[📌 Кейс из практики: как я восстановил работу таблицы в HDFS]

Порой я не знаю о чем написать. Рабочие моменты кажутся скучными. Но в этот раз я решил поделиться поучительной историей.

📉 Пришли с проблемой: отчёт в Power BI больше не работает — запросы просто падают по таймауту.

🔍 Начал разбираться и выяснил, что таблица в HDFS содержит более 75 000 мелких файлов на 477 партиций.
Причина — неудачная логика записи: в каждую партицию складывалось множество крошечных файлов.
Также полностью отсутствовала статистика по таблице.

Почему это проблема:

- Каждый файл — это нагрузка на NameNode. Когда их десятки тысяч, планирование и выполнение запросов начинают страдать.
- Без статистики оптимизатор не может строить адекватные планы выполнения — особенно в системах вроде Hive или Presto.
- Мелкие файлы хуже сжимаются. Компрессия эффективнее на крупных блоках, поэтому итоговый объём данных на диске получается больше, чем при хранении тех же данных в виде агрегированных файлов.

Решения и результаты:

1. Пересчитал статистику по таблице.
ANALYZE TABLE имя_таблицы COMPUTE STATISTICS;


После этого таблица "ожила" — запросы перестали падать, выполнялись за ~220 секунд. Уже хорошо. Пользователь уже был очень доволен.

2. Провёл частичную компакцию (объединение файлов).
Сократил количество файлов до 1900 (на 477 партиций), пересчитал статистику повторно — и запрос начал выполняться за 120 секунд.

3. Запустил полную компакцию.
Сделал по одному файлу на каждую партицию (итого 477 файлов). После очередного пересчёта статистики:

- Первый запуск запроса — 58 секунд
- Повторный — 17 секунд!
- В Trino — практически мгновенное выполнение

💾 Также заметно уменьшился размер таблицы на диске — компрессия начала работать в полную силу.

💡 Выводы:

🔹 Мелкие файлы = деградация производительности + перерасход хранилища.
🔹 Регулярная компакция + расчет статистики = must-have для стабильной работы.
🔹 Даже простые меры могут дать существенный прирост производительности и повысить удовлетворённость пользователей.

Теперь в этой таблице порядок, запросы работают стабильно и быстро, пользователь в полном восторге.😊

#bigdata #hdfs #datalake #hive #dataengineering #hadoop
[💪Соревнования по жиму лежа и новый личный рекорд]

Продолжаю ходить в тренажерный зал. Есть новые результаты:
1) Занял 2-е место в местных соревнованиях по жиму лежа с результатом 120 кг (для меня это первое подобное мероприятие);
2) Побил личный рекорд, взяв 125 кг (правда эта попытка была уже вне конкурса);

P.s. собственный вес 83,8 кг.

#gym #life