Сортировка в Power Query — зло. Часть 2.
Продолжим список альтернатив сортировке.
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. Документация по промптам.
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