BA & SA | 10000 Interview questions
10.2K subscribers
172 photos
14 videos
342 links
Вопросы и задачи, которые задают на собеседованиях на позицию Бизнес и Системного аналитика. По вопросам сотрудничества- @DeliveryManager7
Download Telegram
Объяснение:

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

Что такое CQRS?
CQRS разделяет модели чтения и записи. У вас появляется отдельный сервис/модуль для команд (изменение данных) и отдельный — для запросов (чтение). Для чтения можно использовать специально оптимизированные хранилища: денормализованные таблицы, кэш (Redis), поисковый движок (Elasticsearch) или даже read-реплики основной БД. Запись идёт в нормализованное хранилище, а затем изменения асинхронно проецируются в модель чтения.

Применительно к кейсу:

Запрос на главную страницу (список фильмов с рейтингом) идёт в оптимизированную модель чтения — например, в Redis, где данные уже денормализованы и лежат в виде готовых страниц.
Генерация аналитического отчёта (например, распределение жанров по годам) идёт в ту же модель чтения или даже в отдельное аналитическое хранилище (clickhouse, колоночная БД). При этом нагрузка на основную операционную БД (которая принимает команды) практически отсутствует.

Почему не подходят другие паттерны?

A (Микросервисы) — помогают разнести команды и запросы по разным сервисам, но сами по себе не решают проблему производительности запросов, если внутри каждого микросервиса одна БД. CQRS — это более глубокий принцип организации данных.

C (Event Sourcing) — часто используется вместе с CQRS, но это отдельный паттерн хранения истории изменений. Без CQRS он не ускорит запросы.

D (Saga) — паттерн для распределённых транзакций, не про производительность чтения.
Реальный кейс:

В одном онлайн-кинотеатре после внедрения CQRS время отклика главной страницы сократилось с 1.2 сек до 50 мс (за счёт кэша), а аналитики перестали жаловаться на блокировки отчётных запросов, потому что их выделили на отдельную read-реплику. Проекция изменений (из командной модели в read-модель) происходила через брокер сообщений (Kafka) с задержкой менее 1 секунды.

Что должен сделать аналитик:

Зафиксировать требования к производительности для разных типов запросов (интерактивные vs аналитические).
Предложить архитектурное решение CQRS на этапе проектирования.
Определить, допустима ли задержка между записью и чтением (eventual consistency).
Согласовать с командой, какие модели чтения нужны (кэш, реплика, отдельное хранилище).

Вывод: CQRS — это не усложнение ради усложнения, а способ решить реальную проблему роста нагрузки на чтение и запись одновременно. Аналитик, понимающий CQRS, может вовремя предложить его вместо «купим сервер побольше».
🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
ПРОМТ, КОТОРЫЙ СОЗДАЁТ КРУТОЙ ОФФЕР В ЛЮБОЙ ИИ

А ещё …

- нормально сегментирует ЦА, а не пишет «женщины 30+»
- подскажет, как улучшить упаковку продукта


О том, какие каналы классического перформанс-маркетинга всё ещё хорошо работают в 2026 году, рассказали в свежем посте.

В одной ПАПКЕ с топовыми каналами по бизнесу, маркетингу и AI

▪️Юрист 2.0
▪️ Константин Сизов. Давайте об IT
▪️Как в IT повысить грейд, доход и удовлетворение от работы - Психолог с научным подходом Иван Ремизов

…. и ещё много полезных каналов, из которых вы получите

- нейросети, которые генерят контент за минуты, ведут переписки и приводят новых клиентов
- набор топовых инструментов для IT
- небанальные связки по привлечению трафика

Добавляйте ПАПКУ и забирайте

❗️через 3 дня удалю пост

ПОПАСТЬ В ПОДБОРКУ КАНАЛОВ
№4764 категория вопросов: #SQL
4764. таблице logs 100 млн записей. Запрос SELECT * FROM logs WHERE user_id = 123 ORDER BY created_at DESC LIMIT 10 выполняется 5 секунд, хотя есть индекс на (user_id, created_at). В чём вероятная причина медленной работы?
Anonymous Quiz
28%
Индекс не используется из-за ORDER BY
39%
Индекс не покрывает все поля, и происходят случайные чтения из таблицы (lookup)
21%
Нужен индекс на (created_at, user_id)
13%
Нужно удалить индекс и сделать партиционирование
Объяснение:

Индекс (user_id, created_at) идеально подходит для фильтрации по user_id и сортировки по created_at. Почему же запрос медленный?

Проблема: индекс не является покрывающим (covering index) для этого запроса. В индексе есть столбцы user_id и created_at, но в SELECT * запрашиваются все столбцы таблицы. Поэтому СУБД вынуждена:

Найти в индексе 10 нужных строк (быстро).
Для каждой строки выполнить случайное чтение (random I/O) из основной таблицы, чтобы получить остальные поля (message, ip, и т.д.).
Если эти 10 записей разбросаны по разным блокам диска (что почти всегда так), будет 10 случайных чтений. При большом объёме таблицы эти чтения могут быть очень дорогими.
Почему не другие варианты?

A — индекс используется, ORDER BY не мешает, потому что created_at идёт вторым столбцом после фильтрации.
C — индекс (created_at, user_id) будет хуже, так как сначала придётся фильтровать по диапазону дат, что не нужно.
D — партиционирование может помочь, но не отменяет случайных чтений; индекс всё равно нужен.

Как ускорить?
Создать покрывающий индекс, включив в него все поля, которые запрашиваются в SELECT (или хотя бы самые частые). Например, (user_id, created_at) INCLUDE (message, ip, level). Тогда СУБД сможет ответить на запрос, читая только индекс, не обращаясь к таблице.

Реальный кейс:
В одной системе мониторинга запрос на последние 10 действий пользователя выполнялся 3 секунды при индексе (user_id, created_at). После замены на покрывающий индекс с полями action, metadata время упало до 5 мс.

Вывод для аналитика:
При проектировании схемы учитывайте, что частые запросы с SELECT * или большим набором полей могут быть медленными даже с правильным индексом. Если производительность критична, требуйте от команды покрывающих индексов или оптимизации запросов (выбирайте только нужные поля). 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
4
№4765 категория вопросов: #SQL
4765. В таблице orders 10 млн записей, в таблице refunds 2 млн записей. Нужно найти заказы, у которых нет возвратов. Какой запрос выполнится быстрее всего?
Anonymous Quiz
24%
SELECT * FROM orders WHERE order_id NOT IN (SELECT order_id FROM refunds)
33%
SELECT * FROM orders WHERE NOT EXISTS SELECT 1 FROM refunds WHERE refunds.order_id = orders.order_id
33%
SELECT * FROM orders LEFT JOIN refunds ON orders.order_id = refunds.order_id
10%
Все варианты выполнятся одинаково
📈 Маркетологи, которые делают результат, а не «красивые отчёты»

Сохрани папку, пока она открыта.

Здесь не про теорию.
Здесь — про реальные кейсы, цифры и рост.

📌 Как привлекать клиентов, а не просто «лить трафик»
📌 Что нужно, чтобы Telegram приносил реальные продажи
📌 Мощный курс по личному бренду
📌 Инструменты, которые экономят бюджет и время

Никакой магиитолько стратегии, которые дают результат.

Если ты маркетолог, предприниматель или просто хочешь понимать, как продают в 2026 — тебе сюда.

Добавляй папку, чтобы не потерять👇

https://t.me/addlist/KJwPBSB44eg5NTli
Объяснение:

Это классический пример оптимизации запросов с анти-соединением (anti-join). Хотя все три запроса логически эквивалентны, производительность их может кардинально различаться в зависимости от СУБД и объёмов данных.

Почему NOT EXISTS (B) — оптимальнее?

СУБД может выполнять NOT EXISTS как анти-соединение (anti-join), которое останавливается при первом же совпадении в подзапросе для каждой строки orders.
Планировщик способен использовать индекс на refunds.order_id и для каждого заказа делать очень быстрый поиск — как только нашёлся хотя бы один возврат, проверка прекращается.
Не требуется формировать весь результат подзапроса в памяти.
Почему NOT IN (A) — часто медленнее?

Если в подзапросе встретится NULL, весь запрос вернёт пустой результат (из-за трёхзначной логики). Это логическая ошибка, но даже если NULL нет, СУБД может материализовать весь подзапрос (все 2 млн order_id) во временную таблицу, а затем проверять каждый заказ из orders.
При наличии NULL в refunds.order_id запрос (A) не вернёт ни одной строки, даже если возвратов нет — частая ошибка.
Почему LEFT JOIN ... WHERE NULL (C) — компромисс?

В некоторых СУБД (например, PostgreSQL) этот план может быть таким же эффективным, как NOT EXISTS, но часто требует полного сканирования соединения, если индексы не покрывают все столбцы.
Создаёт промежуточный результат из всех строк orders и refunds, потом отсеивает те, у которых refunds.order_id IS NOT NULL. При больших объёмах это может быть тяжело.

Реальный кейс:
В системе учёта возвратов один из разработчиков использовал NOT IN, и запрос выполнялся 25 секунд. После замены на NOT EXISTS время сократилось до 0.3 секунды. Причина оказалась в том, что в refunds.order_id были NULL (технические возвраты без привязки к заказу), из-за чего NOT IN всегда возвращал пустой результат, но СУБД честно обрабатывала все 10 млн строк.

Что должен знать аналитик:

NOT EXISTS — наиболее безопасный и производительный способ проверить отсутствие связанных записей в большинстве СУБД.
Избегать NOT IN на столбцах, которые могут содержать NULL.
Требовать от команды использования NOT EXISTS в регламенте написания запросов.

Вывод: Даже простой логический запрос может работать по-разному из-за нюансов оптимизатора и наличия NULL. Аналитик, понимающий эти различия, помогает писать не только правильные, но и быстрые запросы. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
БОЛЬШИНСТВО AI & IT КАНАЛОВ, НА КОТОРЫЕ ТЫ ПОДПИСАН — МАЛО ПОЛЕЗНЫ …

Одни пересказывают новости — другие копируют посты друг у друга. Ты читаешь десятки каналов, но новых идей почти нет.

Сегодня главная ценность - не количество информации, а сильные и качественные источники. Люди, которые действительно работают с технологиями и делятся практикой, а не пересказами.

Эта ПОДБОРКА для тебя, где нет пересказчиков. Только те, кто реально работает с AI & IT сам - руками, а не перьями. Внутри авторы, которые разбирают новые AI-инструменты, технологии и продукты, стартапы, вайб-кодинг и реальные ИИ кейсы. Это экономит время - не нужно искать хорошие каналы по одному.

Делимся знаниями и аудиторией - растём вместе ⚡️ Забирай бесплатно ПАПКУ с Каналами от лучших авторов.

Твой доступ к подборке и бонусам:
⬆️ Просто добавь ПАПКУ - никаких смс или регистраций. Отписаться можно в любой момент. Остаться — тоже ✔️ * Ссылка - https://t.me/addlist/6jvq2ugAARVhNjc0
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥1
ИИ - УЖЕ НЕ «ПОТОМ». ОН ПРЯМО СЕЙЧАС ПЕРЕПИСЫВАЕТ ПРАВИЛА ...

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

Вопрос давно не в том, заменит ли ИИ людей.
Вопрос в том, кто обгонит тебя, пока ты думаешь.

Хочешь быть среди первых, кто использует нейросети в полную силу?

ПОДБОРКА сильных экспертов по Нейросетям и ИИ — забирай, пока другие скролят новости:
Остаться или отписаться сможешь в любой момент ✔️ * Ссылка - https://t.me/addlist/6jvq2ugAARVhNjc0
🔥2👍1
№4766 категория вопросов: #DBMS
4766. В глобальном чат-приложении сообщения хранятся в таблице messages. Топ-запрос: «показать последние 100 сообщений в диалоге между пользователями A и B». Какой первичный ключ обеспечит лучшую производительность при шардировании?
Anonymous Quiz
21%
(message_id) — глобальный автоинкрементный идентификатор
47%
(user_a_id, user_b_id, created_at)
25%
(dialog_id, created_at)
7%
(created_at, message_id)
Объяснение:

1. Суть проблемы

При огромном объёме данных (миллиарды сообщений) неизбежно горизонтальное масштабирование (шардирование). Ключевой принцип: данные, которые часто запрашиваются вместе, должны лежать на одном шарде. В чате все сообщения одного диалога запрашиваются вместе (лента переписки). Если эти сообщения разбросаны по разным шардам, каждый запрос «последние 100 сообщений диалога» превратится в сложный distributed join и сборку результатов, что приведёт к высоким задержкам.

2. Почему (dialog_id, created_at) — оптимально?

dialog_id — уникальный идентификатор пары собеседников (например, хеш от min(user_id, peer_id) + max(...)).

Все сообщения одного диалога попадают в один шард (шардирование по dialog_id).
created_at обеспечивает сортировку внутри диалога и уникальность в составе ключа.
Запрос «последние 100 сообщений» читает данные с одного шарда, по одному индексу, в отсортированном порядке — максимально быстро.

3. Почему другие варианты плохи?

A (message_id) — глобальный автоинкремент не подходит для шардирования: сообщения одного диалога попадают в разные шарды (последовательные ID распределяются по серверам). Запрос за 100 сообщениями диалога затронет все шарды, соберёт их, потом отсортирует и обрежет — очень дорого.

B ((user_a_id, user_b_id, created_at)) — семантически близко к dialog_id, но занимает больше места и требует фиксированного порядка двух ID (нужно сортировать, чтобы гарантировать одинаковый ключ для диалога A–B и B–A). dialog_id — это уже свертка, удобнее.

D ((created_at, message_id)) — шардирование по времени размажет один диалог по многим шардам (сообщения за разные даты). Запрос последних сообщений диалога снова соберёт все шарды.

4. Реальный кейс

Telegram, WhatsApp, VK используют похожую схему: ключ = (chat_id, message_id), где message_id возрастает внутри чата.

Шардирование по chat_id. Благодаря этому даже при миллиардах сообщений открыть любой диалог можно за миллисекунды.

Что должен зафиксировать аналитик:

Ключ шардирования = dialog_id.
Кластерный индекс = (dialog_id, created_at).
Для уникальности можно добавить message_id как автоинкремент внутри диалога (но вторичный ключ).

Вывод: Выбор первичного ключа и ключа шардирования — не техническая деталь, а архитектурное решение, влияющее на масштабируемость и пользовательский опыт. Аналитик, понимающий паттерны доступа к данным, помогает проектировать схему БД, которая не сломается под миллиардами записей. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
№4767 категория вопросов: #BROKER
4767. В системе заказов используется Kafka. Один из консьюмеров обрабатывает события и обновляет базу данных. После перезапуска консьюмера некоторые события были обработаны дважды, что привело к дубликатам в БД. Какое требование к интеграции было упущено?
Anonymous Quiz
2%
Увеличение количества партиций
85%
Идемпотентность обработки сообщений
8%
Синхронный коммит смещений
5%
Настройка retention в топике
Объяснение:|

В Kafka (и других брокерах) семантика доставки сообщений по умолчанию — at‑least‑once. Это значит, что сообщение может быть доставлено потребителю более одного раза. Например, консьюмер прочитал сообщение, начал его обрабатывать (обновлять БД), но в этот момент произошёл сбой, и смещение (offset) не было зафиксировано. После перезапуска консьюмер прочитает то же сообщение снова — и обработает его повторно. Это приводит к дубликатам.

Как решается проблема?
Требование идемпотентности на стороне потребителя: обработка одного и того же сообщения несколько раз должна давать тот же результат, что и однократная. Для этого можно:

Хранить уникальный идентификатор сообщения (например, messageId) и проверять его наличие в БД перед обработкой.
Использовать атомарные операции (например, INSERT ... ON CONFLICT DO NOTHING).
Вести отдельную таблицу обработанных ID с TTL.
Пример кода (идемпотентный консьюмер на Python):

```python
import redis
cache = redis.Redis()

def process_message(msg):
msg_id = msg['id']
# Проверяем, не обрабатывали ли уже
if cache.exists(msg_id):
print(f"Дубликат {msg_id}, пропускаем")
return
# Блокируем ID на время жизни (например, 24 часа)
cache.setex(msg_id, 86400, "done")
# Основная бизнес-логика (обновление БД)
update_database(msg)
```

Почему не подходят другие варианты:

A (больше партиций) — увеличивает параллелизм, но не решает дублирование.
C (синхронный коммит) — уменьшает риск потери сообщений, но не устраняет повторную обработку при сбое.
D (retention) — влияет на время хранения сообщений, а не на дублирование.

Реальный кейс:
В платёжном сервисе после перезапуска консьюмера дважды списывались средства с некоторых пользователей. Причина — отсутствие идемпотентности. После внедрения проверки уникальных ID транзакций проблема ушла.

Вывод для аналитика:
В требованиях к интеграции через брокеры сообщений обязательно нужно указывать, что потребители должны быть идемпотентными, если повторная обработка может нанести ущерб (списания, отправка уведомлений, создание заказов). Это требование должно проверяться приёмными тестами. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
№4768 категория вопросов: #BROKER
4768. При падении потребителя после обработки сообщения, но до отправки подтверждения,
сообщение возвращается в очередь и обрабатывается снова. Какая гарантия доставки обеспечивается в этом сценарии?
Anonymous Quiz
17%
Exactly‑once
79%
At‑least‑once
3%
At‑most‑once
1%
No guarantee
☀️Объяснение:

В RabbitMQ (и многих других брокерах) используется модель с подтверждениями: потребитель явно отправляет basic.ack после успешной обработки сообщения. Если потребитель упал до того, как отправил ack, брокер считает сообщение недоставленным и снова ставит его в очередь для другого потребителя или при перезапуске.

Что это даёт?

· Сообщение точно не будет потеряно (если брокер сохранил его на диск).
· Но оно может быть обработано более одного раза (например, если после обработки, но до ack случился сбой). Это называется at‑least‑once (как минимум один раз).

Почему не exactly‑once (A)?
Exactly‑once требует идемпотентной обработки и часто дополнительных механизмов (транзакции брокера, idempotent producer). Простой ack даёт только at‑least‑once.

Почему не at‑most‑once (C)?
At‑most‑once означал бы, что сообщение может потеряться. Здесь же брокер будет повторять доставку.

Реальный кейс:
В сервисе уведомлений использовали авто-ack (подтверждение сразу после получения, до обработки). При падении потребителя сообщения терялись — это at‑most‑once. Перешли на ручной ack после обработки — получили at‑least‑once, но иногда были дубликаты писем. Затем добавили идемпотентность на стороне потребителя (проверку по ID сообщения) и достигли exactly‑once.

Что должен знать аналитик:

· Гарантии доставки — это компромисс между надёжностью и производительностью.
· At‑least‑once подходит для большинства бизнес-сценариев, если потребитель идемпотентен.
· Если дубликаты недопустимы (финансы), требуйте exactly‑once или проектируйте идемпотентность.

Вывод: При описании интеграций аналитик должен явно указывать требуемую гарантию доставки и стратегию подтверждений. Это влияет на надёжность системы.
🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Сейчас в IT ощущается переломная фаза: компании уже не просто «закрывают вакансию аналитика», а ищут людей, которые умеют говорить и на языке бизнеса, и на языке продукта, и на языке разработки, без лишней воды и формализма.
Это хороший знак: рынок перестаёт довольствоваться «человеком‑исполнителем» и всё больше ценит тех, кто понимает, зачем нужен каждый документ, схема и требование, и как всё это связано в одну систему.


Собрали папку, в которую складываем именно то, что реально помогает вникнуть в бизнес‑анализ и IT‑среду, а не просто «заполнить ленту».

Тут: разборы задач, примеры документов, чек‑листы, ссылки на качественные каналы и инструменты, которые помогают разобраться в профессии и не тонуть в потоке.

Сохранить папку себе 📨