PPC для сверхразумов | Александр Хитро
前往频道在 Telegram
13 лет в рекламе @podorozhnik_ppc Автор t.me/ppc_bigbrain/865 Меню t.me/ppc_bigbrain/1191 Чат t.me/+IAE-w7o7tZtjOTNi Подписка t.me/ppc_bigbrain/1496 t.me/ppc_bigbrain/1497 Отзывы t.me/ppc_bigbrain/1004 t.me/ppc_bigbrain/1249 Комбайн t.me/ppc_bigbrain/1582
显示更多3 909
订阅者
+224 小时
+27 天
+530 天
帖子存档
От наболевшего до реализации — за 4 недели.
Упорядочил в сквозном пайплайне из 7 скиллов Claude всё самое важное за 13 лет карьеры в маркетинге и 3 года ведения платного закрытого канала:
🔣 Выполняемое моими руками.
🔣 Выполняемое всеми подрядчиками и агентствами, с которыми когда-либо взаимодействовал.
🔣 Всё, на что не хватало времени, знаний, опыта, людей, денег.
Чтобы нейронка учитывала и делала всё сразу, уложил в инструкциях по автоматизаци:
нейтронка хитронка три тыщи.
———
✅ План работ с учётом актуальных инструментов под нужные гео, язык и проект.
✅ Без хардкода сервисов и инструментов — только универсальная методология, которая адаптирует всё под указанные вводные параметры.
✅ Каждая из 7 фаз выполняется сама за 20–30 минут.
✅ Результат каждой фазы — 20–50 листов А4.
✅ Автосохранение промежуточных результатов на важных чекпоинтах, чтобы не терять контекстное окно.
———
Что выполняется само:
———
🔸 Анализ сайта (если есть): структура, UX/UI, удобство, интерактивные, графические, конверсионные элементы, вёрстка, упаковка, меню, секции и т.д. + лучшие мировые практики.
🔸 Сбор категорий, подкатегорий, сегментов.
🔸 Сбор, скоринг, фильтрация конкурентов.
🔸 Мои + лучшие мировые практики анализа сайтов конкурентов.
🔸Подготовка к быстрому сбору и фильтрации семантики (привет, bi-комбайн).
🔸 Сбор отзывов из различных источников, их систематизация, категоризация, выявление болей, довольств аудитории.
🔸 Подготовка, проведение интервью с отделом продаж, сотрудниками, покупателями бизнеса, систематизация и категоризация вопросов и ответов.
🔸 Выявление проблем аудитории, решений, отличий от конкурентов, формирование оффера, ёмких тезисов, измеримых выгод.
🔸 Учёт законодательства, правовых ограничений, новостей и сдвигов рынка, правил и требований сервисов, языков анализа и ревью, регионов-исключений.
🔸 Выявление недостающих атрибутов на сайте, создание новых уникальных для индустрии, учёт прототипов в Figma, создание структуры сайта.
🔸 Вывод результатов в Word, Excel, Power Point.
🔸 Анализ продаж, CRM, воронки, сегментов, проблем и точек роста, возражений, скриптов звонков и переписок, лучшие мировые практики аналитики и визуализации данных, оптимизации отдела продаж.
🔸 Сбор актуальных инструментов, приоритизация видов работ.
🔸 Мои + лучшие мировые практики составления плана работ, интерактивной калькуляции трудозатрат, презентации с КП клиенту для продажи услуг на много денег и месяцев.
🔸 Множество правил копирайтинга, типографики, очеловечивания и оживления текстов, составления контент-плана по лучшим мировым практикам под любые каналы и площадки.
🔸 Создание нескольких версий страниц и квизов под выбранную CMS или конструктор.
🔸 Лучшие практики адаптивной вёрстки, повышения производительности, дизайна, интерактива, графики, тестировки фронтенда, веб-аналитики + готовые скрипты.
🔸 Лучшие мировые практики многослойной защиты от фрода и ботов + скоринг юзеров + готовые скрипты + ТЗ на подготовку.
🔸 Лучшие мировые практики SEO, брифы, аудиты, чеклисты, план работ, оптимизация под нейровыдачу.
———
Результаты пайплайна из 7 скиллов:
➕ 10–15 файлов анализа.
➕ 100–200 страниц А4.
➕ 1–3 версий сайта со всем необходимым.
Чем больше и точнее данные на входе — тем точнее результат каждого скилла.
———
Личные кабинеты — следующий этап.
———
➕ 235 часов систематизации карьеры и архитектуры скиллов. ➕ 20+ собственных руководств, планов работ, КП, брифов, презентаций, статей. ➕ 500+ авторитетных актуальных на момент анализа источников лучших мировых практик по всем задачам и этапам. ➕ 7 скиллов (этапов). ➕ 11 скриптов. ➕ 153 файла. ➕ 479 связей между файлами. ➕ 219 листов А4. ➕ 98 тысяч слов. ➕ 746 тысяч символов.——— Получилась универсальная
На своём аккаунте уже сейчас готов запускать анализ "как есть" на ваших проектах. Пишите: 💊 @podorozhnik_ppc Всю необходимую от вас инфу, детализацию анализа и цену обсудим лично. Для полноты картины нужны: 1️⃣ Выгрузка сделок из CRM. 2️⃣ Статистика контекста, таргета. 3️⃣ Запросы из органики. Учту любые ваши пожелания по доработке.via @ppc_bigbrain
+2
эмэйзинг нейродрисня
когда пытаешься вправить нейтронке мозги из задницы в процессор, создав ей пачку скиллов с сотней руководств по тому, как думать, а она всё ещё тупорылая шопездец
via @ppc_bigbrain
маркетологи, как вам портрет платежеспособной аудитории? сохраняем или осуждаем?
via @ppc_bigbrain
Что вы попробовали в своей карьере из любых родов деятельности один раз и сразу поняли, что это не для вас?
Начну с себя.
Меня за 13 лет в контекстной рекламе хватило на один раз в жизни:
- На настройку 1 смарт кампании в Google Ads.
- На настройку 1 мастера кампаний в Яндекс Директе.
- На 1 разговор с менеджером Гугла об аудите моего аккаунта Google Ads.
- На 1 разговор с менеджером Яндекса об аудите моего аккаунта Директа.
Расскажите о своём незабываемом опыте, рот которого вы шатали.
via @ppc_bigbrain
шта? абисните плес, я прост с деревни
шёл 8к26 век, впнологи щщщетали цену клика калкурентов через время появления ремаркетинга
песдос
есус, дай им мозгов
пишите в элэс, пащщетаю в калбайне цену клика ваших калкурентов через разницу в градусах между вашим углом стояния раком при настройке МК и восьмым козырем бубной в четверг
via @ppc_bigbrain
«а мы агентство, которое скликивает рекламу по заказу яндекса»
кулстори от того, кто умеет делать хорошо и кому нет причин не доверять
via @ppc_bigbrain
+3
когда бог директа раздавал хромосомы, но не хватило на целую индустрию
via @ppc_bigbrain
я как бы ни на что не намекаю, но люди интересуются
via @ppc_bigbrain
изучайте портреты ца, говорили они
фильтруйте интенты запросов, говорили они
сегментируйте семантику, говорили они
пишите релевантные заголовки, говорили они
via @ppc_bigbrain
Меня жизнь к такому не готовила.
Как реагировать на то, что легенда веб-аналитики, на книгах и статьях которого выучилось всё русскоязычное сообщество интернет-маркетинга, советует меня своим ученикам?
Для этого существует какая-то специальная медалька в списке карьерных ачивок? А в форме подорожника есть?
via @ppc_bigbrain
Что изучать для BI-разработки и работы с данными.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных. 9. Смерть производительности. Часть 1. 10. Смерть производительности. Часть 2. 11. Плохие и хорошие примеры. 12. Когда в PQ сортировать данные. 13. Параметризация переменными. 14. Что учесть перед созданием кодаЧто развивать и изучать для обработки данных? ✅ Образное мышление: — Как пример из других кейсов применить к моим данным. — Какие операции выполнить с разными столбцами. — Если нужных полей в этом датасете нет, а в другом — есть, как их можно объединить. — Какие проблемы можно обнаружить, имея в датасете нужные столбцы. — Как их создать. — Как данные из кастомных столбцов применить в дашбордах как критерии: а) Группировки. б) Сегментации. в) Фильтрации. — Какие куски кода параметризировать, чтобы применять его на других проектах. — Как реализовать гибкость и управляемость обработкой данных, чтобы не хардкодить пользовательские значения текстом в коде, а обращаться к динамическим спискам: а) Умным таблицам. б) Именованным диапазонам. в) Папкам с файлами. — Какие проблемы и задачи универсальны для всех проектов. — Как подготовить общие (глобальные) библиотеки данных, которыми можно пользоваться в любом проекте. — Какие проблемы и задачи являются частными для каждого проекта. — Как подготовить локальные библиотеки данных, которые в каждом проекте будут свои. — Как заранее предусмотреть конфликты значений в локальных и глобальных библиотеках, т.е. реализовать поэтапную проверку условий. ✅ Получение данных: — Откуда и что получать. — Какие поля. — В каких группировках. — С какой детализацией. — С какими фильтрами. — За какой период. — Каков объём данных. — Не "ляжет" ли получение данных из-за их объёма. ✅ Если это вручную заполняемые данные (CRM, Google Sheets): — В каком виде данные находятся в источнике. — Плоская ли это таблица (в столбцах — названия полей, в строках — значения). — Какие манипуляции с данными нужно произвести для их преобразования в плоскую таблицу. — Кем заполняются данные. — Какие поля нужно автоматически валидировать (проверять, исправлять, изменять). — Какие нужно обрабатывать частные случаи. — Как это автоматизировать. ✅ Хранение данных: — Каков объём исторических данных. — Частота их обновления. — Интенсивность их обновления, т.е. насколько много новых данных появляется ежедневно. ✅ Среду разработки: — Возможности интерфейса. — Возможности и ограничения языка. — Синтаксис. — Библиотеки. — Типы объектов. — Кастомные функции. — Архитектуру. — Исправление ошибок. ✅ Создание модели данных: — Нормализация модели данных. — Как не раздувать модель данных. — Как обработанные данные собрать в нужные столбцы и таблицы для удобных и полезных дашбордов. — Как позаботиться о масштабируемости модели данных. ✅ Вычисляемые поля: — Как вычислить ту или иную сущность в модели данных. — Почему вычисления метрик лучше делать в модели данных, а не на этапе ETL-процесса перед загрузкой в модель. ✅ Визуализацию данных: — Бесконечный простор нажатия галочек, которые пока сам все не понажимаешь и не используешь, не поймешь, что они делают, и не запомнишь, где они находятся. ✅ Фильтры: — Что нужно иметь в источнике данных или вычислить в коде, чтобы это отобразить удобно и понятно. — Локальная фильтрация листа. — Сквозная фильтрация всего отчёта. ✅ Параметры в дашбордах: — Как визуальные элементы дашборда (фильтры, значения, поля в таблице) сделать автоматически пересчитываемыми, чтобы не городить много вкладок, отличающихся одним полем или метрикой. — Как параметризировать часто используемые элементы. — Как уместить всё самое важное на один холст отчёта. — Как выбирать необходимые визуализации в 1 клик.
Вот для чего создавался комбайн: — ч.1 — ч.2 Чтобы не суецыднуться от ежедневных инсультов при работе с любым проектом на любом языке.via @ppc_bigbrain
Что учесть перед созданием кода
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных. 9. Смерть производительности. Часть 1. 10. Смерть производительности. Часть 2. 11. Плохие и хорошие примеры. 12. Когда в PQ сортировать данные. 13. Параметризация переменными.⚫️ В какие типы объектов преобразовать те или иные данные для ускорения их обработки. ⚫️ Нужна ли сортировка и на каком этапе: 😶 По каким атрибутам: текстовым, числовым. 😶 В каком порядке. 😶 Как получить списки этих полей динамически. ⚫️ На каком этапе получать список список уникальных значений: 😶 Удалением дублей в таблице и по каким столбцам:
Table.Distinct.
😶 Получением списка и удаления дублей в нём:
List.Distinct(Table1[Column1])
😶 Группировкой таблицы и по каким столбцам: Table.Group.
😶 Как сгруппировать остальные столбцы:
🥷 С текстом: List.Sort, List.Distinct, Text.Combine.
🥷 С числами: List.Max, List.Sum, List.Min.
😶 Что вы собираетесь делать с этими данными дальше.
⚫️ На каком этапе значения null заменить на 0. Потому что нейронка не знает, что вы текущий кусок кода через 10 этапов преобразований будете группирований с суммированием, а суммирование null вернёт ошибку.
⚫️ На каком этапе преобразований и в каком столбце указать какой тип данных.
😶 Если в столбце с числовыми значениями будет ошибочно указан текстовый тип данных, агрегатные функции List.Max, List.Sum, List.Min вернут ошибку.
😶 При сцепке (конкатенации) двух столбцов, в одном из которых тип данных — текст, а в другом — целое число, эта операция вернёт ошибку. Сцеплять можно только текст с текстом.
😶 Оборачивание столбца с числами в функцию Text.From преобразует их в текст для последующих текстовых преобразований.
⚫️ Какие функции не использовать, т.к. они очень дорогостоящие, чем их заменить, чтобы они выполнялись мгновенно.
⚫️ Использовать аналоги векторной обработки (всего столбца сразу как единого массива), а не каждой строки по отдельности.
⚫️ Как отфильтровать исходный массив, чтобы вхолостую не применять тяжёлые операции преобразований к строкам, в которых даже нет искомых данных.
😶 По каким условиям фильтровать.
😶 Как получить этот список условий динамически.
⚫️ Как не перегрузить модель данных нормализацией и снежинкой, чтобы визуальный слой быстро обновлялся.
Что изучать для BI-разработки и работы с данными — в следующем посте.
via @ppc_bigbrainПараметризация кода переменными под разные проекты.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных. 9. Смерть производительности. Часть 1. 10. Смерть производительности. Часть 2. 11. Плохие и хорошие примеры. 12. Когда в PQ сортировать данные.✅ Примеры функций для получения динамических списков — в предыдущих постах: — Раз. — Два. ✅ При фильтрации по списку условий во избежание хардкода
{"X", "Y", "Z"} фильтруемых значений, вам придётся придумать логику получения этого списка динамически:
⚫️ Если это статический список (одинаковый для всех итераций обновления данных), можно, например, получить их с листа Excel из умной таблицы или именованного диапазона, и при последующих обновлениях запроса он всегда будет неизменным.
⚫️ Если это динамический список (в каждом проекте свои значения, список и количество которых постоянно меняется):
😶 Либо вам придётся самим придумывать логику их получения динамически.
😶 Либо попросите нейронку вам подсказать, как получить их динамически, возможно, из этого что-то толковое и получится.
⚫️ Любой список разнородных значений указать в столбик и рядом в разных столбцах разметить нужные характеристики всех значений как критерии и порядок группировки, сортировки и фильтрации.
⚫️ Все эти критерии передать в код через весь пайплайн обработки данных как динамические списки.
————
Ничего конкретного показывать и рассказывать не буду, ибо на этом основана вся суть комбайна, в котором я всё это просто охерел придумывать, как всё это реализовать, и как из этого сделать универсальный инструмент под все существующие сценарии работы ппсшника в любых рекламных системах на любых языках.
Полезно разбираться в языке, на котором вы вайбкодите, чтобы явно указывать нейронке, что нужно сделать в той или иной ситуации.
Иногда нейронки генерят производительный код, но инструкции должны быть с явным указанием требований к оптимизации, а иногда даже на платных тарифах даже с подробными промптами и явным указанием, что делать, городят полнейшую дичь.
Вайбкодинг без знания даже основ языка, на котором вы что-то генерите — ещё большее усложнение себе жизни.
О чём подумать перед созданием кода — в следующем посте.
via @ppc_bigbrainКогда сортировать данные можно и нельзя.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных. 9. Смерть производительности. Часть 1. 10. Смерть производительности. Часть 2. 11. Плохие и хорошие примеры.Выносим сортировку из ETL-процесса в Power Query на уровень отчета в следующих случаях: 1️⃣ Для визуального представления. Если сортировка нужна только для того, чтобы видеть таблицу красиво (по алфавиту, по убыванию цены). Excel и Power BI сортируют данные в визуальных элементах (графиках, матрицах) мгновенно, используя оптимизированные движки, не нагружая процесс обновления данных. 2️⃣ Для интерактивности. Если хотим иметь возможность менять порядок сортировки (кликом по заголовку столбца). Жесткая сортировка в Power Query лишает отчет гибкости. 3️⃣ При использовании Top-N фильтров в Power BI. Движок VertiPaq (DAX) вычисляет "Топ-10" в визуализациях быстрее, чем Power Query готовит пред-отсортированную таблицу. ———— Оставляем сортировку в Power Query только если она влияет на логику расчетов: 1️⃣ Для вычисления индекса строки (Index Column). 2️⃣ Для расчета нарастающего итога (Running Total). 3️⃣ Для функций заполнения (Fill Down, Fill Up). В этих случаях обязательно используем
Table.Buffer после сортировки.
Во всех остальных случаях сортировка в Power Query — ошибка и излишняя нагрузка.
————
⚫️ Не сортируем, если можем агрегировать.
Всегда проверяем, можно ли получить результат через Max, Min, Sum или Group. Это золотой стандарт оптимизации.
⚫️ Ранняя фильтрация.
Никогда не сортируем данные до фильтрации. Сначала используем Table.SelectRows, чтобы отсечь все лишнее, и уменьшить количество строк. Сортировка 1000 строк в 100 раз быстрее, чем сортировка 100.000 строк (спасибо, кэп).
⚫️ Используем буферизацию с умом.
Если отсортировали таблицу для сложного расчета и многократного обращения к результатам, берём этот шаг в Table.Buffer. Иначе Power Query может выполнять сортировку заново для каждой последующей строки вычислений.
⚫️ Разделяем данные и представление.
Если сортировка нужна только для презентации, делаем её в модели данных или элементах визуализации данных, а не в ETL.
⚫️ Query Folding — приоритет (но не поддерживается при работе с локальными файлами на ПК, а только с базой данных).
Table.Sort при работе с SQL часто прерывает Query Folding — свертывание запросов. Если сортировка неизбежна и данные не лежат на ПК, выполняем её на стороне сервера, а не в памяти Power BI.
Итого: ➕ Нужно Макс/Мин значение? Используем List.Max, List.Min (вместо Sort+First). ➕ Нужен Топ-N? Используем List.MaxN (вместо Sort+FirstN). ➕ Нужен уникальный список? Используем List.Distinct (вместо Sort+RemoveDuplicates). ➕ Нужно найти соответствие? Используем Table.Join (вместо SelectRows внутри AddColumn). ➕ Нужна красота в отчете? Сортируем в Excel/Power BI, а не в Power Query.✅ Хороший код Power Query: — Выполняется за секунды или минуты, а не часы. — Работает за время O(n) или O(n+m). — Масштабируется с тысяч до миллионов строк. ❌ Плохой код Power Query: — Сортирует "на всякий случай". — Сортирует в циклах. — Сортирует ради отображения. — Отдаёт ошибку нехватки памяти. Для использования самых быстрых альтернатив сортировки, спрашиваем у нейросети:
Как по каждому значению столбца X получить значение из столбца Y, которое соответствует наибольшему значению метрики Z, но: — Не используя при этом сортировок. — Используя функцию, которая сразу возьмёт максимальное значение.В каждом промпте про оптимизацию скорости кода обязательно явно указываем на минимизацию количества вычислений из «Big O» нотации:
1. Используй операции с вычислительной сложностью: O(1), O(log n), O(n), O(n + m), но как можно меньшее из них. 2. Не используй операции вычислительной сложностью: O(n log n), O(n × m), O(n²), O(nᵏ), O(2ⁿ), O(n!).В следующем посте — о параметризации кода переменными для его использования в разных проектах. via @ppc_bigbrain
Плохо vs хорошо — сравнение сложности вычислений.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных. 9. Смерть производительности. Часть 1. 10. Смерть производительности. Часть 2.Рассмотрим альтернативы сортировки и сложность их вычислений. Пример 1: Найти максимальное значение. ❌ Плохо: Отсортировать таблицу по убыванию -> Взять первую строку. Функции:
Table.Sort + Table.First.
Сложность: O(n log n).
Почему плохо: сортируются сотни тысяч строк ради одной.
✅ Хорошо: Использовать функцию поиска максимума.
Функции: List.Max или Table.Max.
Сложность: O(n).
Результат: В разы быстрее.
————
Пример 2: Найти топ-10 самых дорогих товаров.
❌ Плохо: Сортировка всей таблицы -> Взять первые 10 строк.
Функции: Table.Sort + Table.FirstN.
Сложность: O(n log n).
✅ Хорошо: Использовать функцию частичной выборки.
Функции: List.MaxN или Table.MaxN.
Сложность: O(n) или O(n log k), где k — это всего 10 строк.
Результат: Экономия памяти, не нужно упорядочивать "хвост" таблицы.
————
Пример 3: Найти последнюю продажу для каждого клиента (внутри группы).
❌ Плохо: Группировка -> Внутри каждой группы. Сортировка -> Взять первую строку.
Функции: Table.Group + (each Table.Sort -> Table.First).
Сложность: O(n²) или O(n log n).
Катастрофически медленно на больших данных.
✅ Хорошо: Группировка -> Внутри группы поиск максимума.
Функции: Table.Group + (each List.Max).
Сложность: O(n).
Результат: Линейное выполнение за один проход.
————
Пример 4: Проверка наличия значения в списке.
❌ Плохо: Сортировка списка -> Бинарный поиск.
Функции: List.Sort + List.Contains.
Сложность: O(n log n).
✅ Хорошо: Прямой поиск или преобразование в запись (Hash set).
Функции: List.Contains или List.Buffer + Record.FromList.
Сложность: O(n).
————
Пример 5: Поиск соответствий (аналог ВПР или VLOOKUP).
❌ Плохо: Добавление столбца с фильтрацией внутри.
Функции: Table.AddColumn + (each Table.SelectRows).
Сложность: O(n × m). Квадратичная сложность (Nested Loop).
✅ Хорошо: Объединение таблиц (Merge).
Функции: Table.NestedJoin или Table.Join.
Сложность: O(n + m). Использует Hash Match.
————
Пример 6: Сортировка внутри циклов.
❌ Плохо: List.Transform или Table.AddColumn с Table.Sort внутри.
Сложность: O(n² log n) и хуже.
✅ Хорошо: Один проход с агрегатами или предварительная группировка.
Сложность: O(n).
————
Пример 7: Проверка существования значения.
❌ Плохо: Sort + Contains
Сложность: O(n log n)
✅ Хорошо: List.Contains
Сложность: O(n)
✅ Ещё лучше при множественных обращениях к списку для его проверки:
List.Buffer + lookup
Сложность: O(n + m)
В следующем посте — когда в Power Query данные сортировать можно и нельзя.
via @ppc_bigbrainСортировка в Power Query — зло. Часть 2.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных. 9. Смерть производительности. Часть 1.Продолжим список альтернатив сортировке. 7️⃣ Агрегатные функции — сложность O(n). Эти функции выполняют один проход по данным для вычисления результата. ⚫️
List.Max — поиск максимального или минимального значения в списке.
Сложность: O(n).
Применение: вместо тяжелой сортировки всей таблицы по убыванию и взятия первого элемента со сложностью O(n log n).
⚫️ List.Min — поиск минимального значения в списке.
Сложность: O(n).
Применение: Вместо List.Sort + List.First — сортировки по возрастанию и взятия первого элемента.
⚫️ List.Sum — сумма элементов списка.
Сложность: O(n).
Применение: Для агрегации без предварительной сортировки.
⚫️ List.Average — среднее значение элементов.
Сложность: O(n).
Применение: Расчет среднего без сортировки.
⚫️ List.Count — подсчет элементов.
Сложность: O(1) или O(n) в зависимости от реализации.
Применение: Быстрый подсчет элементов без материализации.
⚫️ Table.RowCount — количество строк в таблице.
Сложность: O(1) при наличии метаданных.
Применение: Быстрая проверка размера данных.
✅ Правильный паттерн:
Group + Aggregate
❌ Неправильный паттерн:
Group + Sort внутри каждой группы
————
8️⃣ Функции фильтрации и поиска — O(n).
Фильтрация почти всегда дешевле сортировки и должна выполняться раньше.
⚫️ List.Select — фильтрация списка по условию.
Сложность: O(n).
Применение: Отбор элементов без сортировки.
⚫️ Table.SelectRows — фильтрация строк таблицы.
Сложность: O(n).
Применение: Основной метод фильтрации в Power Query.
⚫️ List.PositionOf — поиск позиции элемента.
Сложность: O(n).
Применение: Линейный поиск в несортированном списке.
⚫️ List.Contains — проверка наличия элемента.
Сложность: O(n).
Применение: Быстрая проверка существования.
⚫️ Table.Distinct — удаление дубликатов.
Сложность: O(n) с использованием хеш-таблицы.
Применение: Дедупликация без сортировки.
⚫️ List.Distinct — уникальные элементы списка.
Сложность: O(n).
Применение: Получение уникальных значений.
⚫️ Record.Field — сложность O(1).
Применение: Самый быстрый способ поиска (Lookup) по ключу.
————
9️⃣ Индексация и lookup — O(1) или O(n).
⚫️ Table.AddIndexColumn — добавление индекса строки.
Сложность: O(n) для создания, O(1) для доступа.
Применение: Быстрый доступ по позиции после создания индекса
⚫️ Table.Buffer — кеширование таблицы.
Сложность: O(n) для создания буфера.
Применение: Предотвращение повторных вычислений.
⚫️ Record lookup (обращение к полю записи) — прямой доступ.
Сложность: O(1).
Применение: Самый быстрый способ lookup в M.
⚫️ List.Buffer — кеширование списка в памяти.
Сложность: O(n) для создания, O(1) для последующих обращений.
Применение: Оптимизация повторных операций.
List.Buffer + lookup — сложность O(n) на построение, дальше — O(1).
Record и Join почти всегда лучше, чем сортировка + поиск.
————
1️⃣0️⃣ Объединение — O(n + m).
⚫️ Table.NestedJoin — вложенное соединение.
Сложность:
✅ Хорошо: O(n + m) — с правильными ключами.
❌ Плохо: O(n × m) — без оптимизации.
Применение: Join с сохранением вложенной структуры. При использовании Hash Join это намного быстрее, чем вложенные циклы.
⚠️ Недостаток: Table.NestedJoin медленее, чем Table.Join, т.к. первая присоединяет и разворачивает вложенные таблицы в каждой строке, а вторая — всю таблицу целиком.
⚫️ Table.Join — соединение таблиц с хешированием.
Сложность: O(n + m) при использовании hash join.
Применение: Объединение данных без сортировки.
⚠️ Неудобство: названия столбцов в таблице 2 не должны повторять названия столбцов из таблицы 1.
————
1️⃣1️⃣ Специализированные функции.
⚫️ List.BinarySearch — бинарный поиск в отсортированном списке.
Сложность: O(log n).
Применение: Эффективный поиск, но требует предварительной сортировки.
В следующем посте — плохие и хорошие примеры с анализом сложности вычислений.
via @ppc_bigbrainСортировка — смерть производительности. Часть 1.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений. 8. Порядок обработки данных.В Power Query функции сортировки
Table.Sort, List.Sort — одни из самых "дорогих" операций.
❌ Имеют вычислительную сложность O(n log n).
❌ Прерывают потоковую обработку данных.
❌ Ломают ленивые вычисления.
❌ Заставляют систему загружать все данные в оперативную память.
❌ При использовании в циклах быстро превращаются в вычислительную сложность O(n²) и хуже.
❌ Часто ломают Query Folding (свертывание запросов) — касается только к SQL запросов, а не к лежащим на ПК файлам.
Эксперты BI индустрии сортировку используют только в крайних случаях.
————
Категоризация альтернатив сортировке.
Ниже перечислены функции, которые выполняют задачи поиска и отбора данных быстрее, чем сортировка.
1️⃣ Функции поиска экстремумов (максимума/минимума) для таблиц — сложность O(n).
Вместо упорядочивания всего списка ради одного значения используются агрегатные функции.
⚫️ Table.Max — поиск строки с максимальным значением по столбцу.
Сложность: O(n).
Применение: Вместо Table.Sort + Table.First. Например, чтобы не оставлять только одну строку с максимальным расходом для каждой рекламной кампании, где сложность — O(n²) или O(n log n).
⚫️ Table.Min — поиск строки с минимальным значением по столбцу.
Сложность: O(n).
Применение: Вместо Table.Sort + Table.First
————
2️⃣ Получение элементов списка по позиции — сложность O(1).
Если данные уже имеют структуру, сортировка не нужна.
⚫️ List.First — первый элемент списка.
Сложность: O(1). Мгновенное взятие первого элемента.
Применение: Быстрый доступ к началу списка.
⚫️ List.Last — последний элемент списка.
Сложность: O(1).
Применение: Быстрый доступ к концу списка.
————
3️⃣ Топ-N без полной сортировки списка
⚫️ List.MaxN — N максимальных элементов из списка.
Сложность: O(n × k).
Применение: Частичная сортировка для топ-элементов.
⚫️ List.MinN — N минимальных элементов из списка.
Сложность: O(n × k).
Применение: Поиск топ-элементов.
⚫️ List.FirstN — первые N элементов.
Сложность: O(n).
Применение: Срез данных с начала.
⚫️ List.LastN — последние N элементов.
Сложность: O(n).
Применение: Срез данных с конца.
————
4️⃣ Получение элементов таблицы по позиции.
Если данные уже имеют структуру, сортировка не нужна.
⚫️ Table.First — первая строка таблицы.
Сложность: O(1).
Применение: Получение первой строки без сортировки.
⚫️ Table.Last — последняя строка таблицы.
Сложность: O(1).
Применение: Последняя строка без сортировки.
⚫️ Table.FirstN — первые N строк таблицы.
Сложность: O(n).
Применение: Выборка строк с начала.
⚫️ Table.LastN — последние N строк таблицы.
Сложность: O(n).
Применение: Выборка строк с конца.
————
5️⃣ Топ-N без полной сортировки таблицы
⚫️ Table.MaxN — поиск N строк с наибольшими значениями.
Сложность: O(n × k), где k — количество элементов (обычно k << n). На практике близко к O(n).
Применение: Топ-N элементов без полной сортировки.
⚫️ Table.MinN — поиск N строк с наименьшими значениями.
Сложность: O(n × k).
Применение: Поиск нижних N элементов.
Используется вместо: Sort + FirstN.
————
6️⃣ Группировка и агрегация — O(n) или O(n + g).
⚫️ Table.Group с вложенными функциями агрегации List.Max, List.Sum, List.Average, List.Count в группируемых полях.
Сложность: O(n) для группировки + O(g) для агрегации, где g — количество групп.
Применение:
— За один проход группирует данные с агрегацией.
— Самый мощный инструмент для замены сортировки.
— Cокращает объем данных при работе с группами.
— Ищет "лучшую" строку в группе без внутренней сортировки.
— Не замедляет обработку папки с файлами до сложности O(n²).
⚫️ List.Accumulate — пользовательская агрегация.
Сложность: O(n) при O(1) операции в функции.
Применение: Сложные агрегации без сортировки.
В следующем посте — больше альтернатив сортировке: агрегация, фильтрация и поиск, индексация и lookup, join.
via @ppc_bigbrainВ каком порядке оптимальнее обрабатывать данные.
Предыдущие посты серии: 1. Документация по промптам. 2. Выбор нейронок. 3. Подготовка к разработке. 4. Оптимизация кода. 5. Если код не "летает". 6. Минимизируем вычисления. 7. Фатальный пример вычислений.1️⃣ Удаляем ненужные столбцы. 2️⃣ Обрабатываем не исходный массив с разбивкой по датам и другим атрибутам, а в новом запросе ссылаемся на этот массив, получаем список уникальных значений из нужного столбца. 3️⃣ Обрабатываем уникальные значения в новом столбце. 4️⃣ Если эти данные нужны на следующих этапах — объединяем исходный массив с этим запросом по общему полю. 5️⃣ Если эти данные нужны в таком виде в конечной визуализации данных: а) Выгружаем второй запрос в модель данных. б) Объединяем две таблицы по ключевому полю в модели данных, т.к. это работает быстрее. ✅ Нет необходимости понимать код. Достаточно понимать, как попросить нейронку:
1. Обратиться к нужным таблицам и столбцам. 2. Какие операции нужно сделать. 3. Что должно получиться в результате. 4. Какие вычисления безопасны: O(1), O(log n), O(n), O(n + m). 5. А какие — смерть для производительности: O(n log n), O(n × m), O(n²), O(nᵏ), O(2ⁿ), O(n!).✅ Если группировать таблицу нужно по списку полей, названия которых могут меняться от проекта к проекту, для возможности использования кода в других проектах, список этих полей нужно получить динамически: 😶 Либо обратившись к умной таблице в Excel, куда вводить вручную эти значения, и передавать их дальше в код просто как название списка (количество элементов в списке и их значения при этом будут не важны). 😶 Либо вычленив общие текстовые паттерны в заголовках этих полей и отфильтровав: 1. Значение:
{"Текст"}.
2. Хардкод списка (так делать не нужно): {"Текст1", "Текст2", "Текст3"}.
3. Имя списка, который динамически получает список текстовых значений.
Примеры, как их отфильтровать (список неполный, ибо способов — уйма) по:
— Содержанию: List.Contains
— Отсутствию: not List.Contains
— Началу: Text.StartsWith
— Не началу: not Text.StartsWith
— Окончанию: Text.EndsWith
— Не окончанию: not Text.EndsWith
😶 Либо обратив внимание на расположение в таблице самих полей и если они находятся:
— Или всегда в начале;
— Или всегда в конце;
— Или идут подряд;
— Или стоят до, после или между полями с заведомо известными значениями;
То получить функцией Table.ColumnNames список полей таблицы, а дальше отфильтровать их:
— Взяв N элементов с начала списка: List.FirstN
— Взяв N элементов с конца списка: List.LastN
— Удалив N элементов в конце списка: List.RemoveLastN
— Получив диапазон значений между N и M позициями списка: List.Range
— Пропустив N элементов с начала списка: List.Skip
✅ Преобразуем список уникальных значений:
😶 Удаляем дубликаты, пустоты, null.
😶 В начале следующего запроса буферизуем его: List.Buffer.
В следующем посте — о смерти производительности кода в Power Query.
via @ppc_bigbrain