Как стать автором
Обновить
14
17

Пользователь

Отправить сообщение

Спасибо, да, хорошая идея

Имеются две формулы расчета кардинальности, которые применяются в СУБД.

1.Кардинальность поля в смысле теории множеств как мощность множества (или кардинальное число), количество уникальных записей в поле

card\left( A \right)=\left| A \right|=M

2.Кардинальность в смысле СУБД как отношение количества уникальных записей в поле M к общему количеству записей N в таблице: M / N.

Также под кардинальностью в СУБД часто понимается тип связи: один ко многим, один к одному, многие ко многим.

Первое определение через кардинальное число в каких-то случаях полезно: например, для UI знать, что всего 10 уникальных записей и они поместятся в дропдаун. Однако для случая оптимизации запросов характеризовать кардинальность через кардинальное число без учета общего количества записей в таблице неинформативно.

Например, кардинальность поля по кардинальному числу равна 1 000 000. Для 1 000 000 записей в таблице это поле с высокой кардинальностью. Для таблицы с 1 000 000 000 записями это поле "в 1000 раз менее уникально" по сравнению с полем первичного ключа с 1 000 000 000 уникальными записями, и при оптимизации запросов поле с 1 000 000 можно считать низкокардинальным для таблицы с 1 000 000 000 записями.

Соответственно, поэтому в статье рассматривается второе определение кардинальности, первое определение кардинальности называется просто "количество уникальных записей" без деталей из теории множеств, также приводится формула расчета для второго определения кардинальности

Поэтому кардинальность поля (или полей) таблицы можно измерять отношением количества уникальных записей в поле (полях) к общему количеству записей в таблице

и краткое обоснование пользы такого определения кардинальности для задач оптимизации запросов

т.е. при значении кардинальности для поля (полей) от 0 до 0.1 такое поле (поля) является низкокардинальным и добавление такого поля (полей) в GROUP BY снизит время выполнения запроса

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

Кардинальность отдельных разрядов в строковом представлении целого числового значения? вы серьёзно?

Среди данных для двух полей одной таблицы

00
01
02
...
99

нет ни чисел, ни строк, это кортежи из двух цифр, первая цифра пишется в одно поле таблицы, вторая цифра - во второе поле той же таблицы, это описано в легенде.

Будем рассматривать в качестве "первого поля таблицы" разряд десятков двузначного числа (т.е., например, 1 из числа 12), в качестве "второго поля таблицы" разряд единиц двузначного числа (т.е., например, 2 из числа 12). Будем считать, что порог низкой кардинальности 0.1, и рассмотрим 100 записей (т.е. "количество записей в таблице" будет 100).

Это словесное описание таблицы такого вида

Кардинальность отдельных разрядов в строковом представлении целого числового значения? вы серьёзно?

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

Пример далее не имеет особого отношения к теме статьи и просто как иллюстрация.

Например, у Пети 5 пальцев, и он хранит их состояние (0 - палец согнут и 1 - палец разогнут) в 5 разных битах одного двоичного числа из 5 бит, каждый бит соответствует одному пальцу (младший бит - мизинец и т.д.). Петя назагибал пальцы 10 раз и получил 10 двоичных чисел: 00000, 11111, 00001, 11111, 00001, 11111, 00001, 11111, 00001, 11111.

Видно, вероятность появления 1 в младшем бите равна 9/10=0.9 (например, Петя после первого разгиба мизинца его сломал и больше не двигал).

Также видно, что на 10 наблюдениях кардинальность (в смысле кардинального числа) состояния каждого пальца Пети, а также кардинальность (в смысле кардинального числа) каждого бита, соответствующего состоянию пальца Пети, равна 2 (количество уникальных значений, т.е. 0 и 1).

Также можно посчитать кардинальность состояния каждого пальца Пети и кардинальность каждого бита, соответствующего состоянию пальцу Пети, в смысле отношения кардинального числа к числу записей, и получим 2 / 10 = 0.2.

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

Если рассмотреть

column_1, column_2, column_3, ..., column_n

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

uniq_1,uniq_2,uniq_3...,uniq_n

то видно, что как раз решается проблема расчета кардинальности набора выбранных полей m

column_1, column_2, column_3, ..., column_m,m\leqslant n

за счет оценки кардинальности набора m полей (а не более точного вычисления кардинальности) без дополнительных SQL запросов и на основе существующих значений

uniq_1,uniq_2,uniq_3...,uniq_n

Проблема задачи в том, что на примере 10 полей в таблице

column_1, column_2, column_3, ..., column_{10}

и количества полей для оценки кардинальности в 3 поля

column_1, column_2, column_3

получаем разное число сочетаний из 10 по 3:

\mathrm{C}_{10}^{3}=\frac{10!}{3!\cdot (10-3)!}=120

Т.е. при проверке кардинальности "в лоб" на основе дополнительных SQL запросов для проверки кардинальности 3 полей из 10 полей таблицы уже потенциально есть 120 вариантов и 120 запросов.

В статье как раз предлагается собирать статистику в одном SQL запросе периодически, использовать её для оценки кардинальности нескольких полей, и отказаться от сотен других потенциальных SQL запросов, которые могут решать задачу оценки кардинальности "в лоб" одним SQL запросом на каждый набор m полей из всех n полей таблицы.

Добавился best practice по DAX :)

Возвращаясь к реляционной алгебре, похоже, что предложенная мера соответствует выделенному выражению

UPDATE: Ошибся веткой

Спасибо за отличные аргументы в копилку DAX :)

По поводу SQL - согласен, вот такие есть недостатки SQL, что появляются идеи улучшений SQL кода, уже без выбора диалекта SQL, СУБД, её версии (версия до 22.02.2022 - такая версия часто рекомендуется к использованию, или после 22.02.2022, и т.д.) - достаточно много нюансов, которые отвлекают от решения основных задач, от бизнес-логики. Например, у меня встречалось, что версия СУБД до 22.02.2022 не применяет WHERE сразу до JOIN при наличии нескольких JOIN, т.е. выделение подзапросов с WHERE приводит к более эффективному плану выполнения SQL запроса в версии СУБД до 22.02.2022, но в последней версии СУБД это исправлено и можно не использовать подзапросы с WHERE.

Спасибо за подробную обратную связь.

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

Поэтому Visiology дает свободу в реализации сложных мер и использовании их в фильтрах, других виджетах и дашбордах.

Кстати, рекомендуют сначала сделать базовую метрику

Хорошая практика, Вы описываете дополнительные преимущества DAX с точки зрения архитектуры BI решения, схемы данных и визуализаций. В первом примере статьи цель была в сравнении решений задачи на DAX и SQL, поэтому для упрощения сравнения DAX был написан без меры, в третьем примере рассмотрен уже DAX с мерой.

Описанный Вами подход к расчету мер может быть эффективно реализован в Visiology.

FILTER внутри CALCULATE в этом случае генерируется автоматически

Поскольку в перечисленных случаях CALCULATE без FILTER является синтаксическим сахаром для CALCULATE с FILTER (более полный список эквивалентных DAX можно найти, например, здесь, или в других источниках), то использование в Visiology CALCULATE с FILTER не накладывает ограничений для этих случаев.

SUM лучше чем MAX отвечает на поставленный вопрос "Кто скупил дешевую колбасу?"

Справедливо и выглядит как дополнительный критерий, по объемам покупок :)

Да, интересно, даже есть об этом материал, но обычно DISTINCTCOUNT быстрее

There may be reports where the # Customer SUMX measure is way faster than the classic # Customer measure based on DISTINCTCOUNT, though usually the opposite is true.

Спасибо, да, баги - это другая сторона ClickHouse :)

Интересно, что в русской документации не упоминается DEPRICATED, только warning

runningAccumulate не DEPRICATED в https://clickhouse.com/docs/ru/sql-reference/functions/other-functions
runningAccumulate не DEPRICATED в https://clickhouse.com/docs/ru/sql-reference/functions/other-functions

В английской документации есть DEPRICATED

runningAccumulate не DEPRICATED в https://clickhouse.com/docs/en/sql-reference/functions/other-functions
runningAccumulate не DEPRICATED в https://clickhouse.com/docs/en/sql-reference/functions/other-functions

Да, Firebird через ODBC

ODBC источник для Power BI
ODBC источник для Power BI

Отличий много, хочется отметить, что DAX работает практически со всеми источниками данных, в отличие от диалекта SQL, который применяется только в рамках одной базы данных. Например, лишь небольшая часть окна импорта данных в Power BI с источниками данных выглядит так:

Многообразие источников данных для DAX в Power BI
Многообразие источников данных для DAX в Power BI

В общем и целом, DAX и любой диалект SQL - инструменты для решения разных задач, но в области Business Intelligence, дашбордов и анализа данных у DAX есть свои преимущества над диалектами SQL, например в скорости написания запросов, лаконичности кода запросов, простоте анализа разнородных источников данных и т.д.

Я сам работаю и работал над платными BI системами, например, Visiology, MercerInsight, также были проекты с SAP BI, и самописные BI системы на стеке .NET + Elasticsearch + RabbitMQ, и поэтому в бесплатных BI продуктах, если честно, меньше ориентируюсь.

Здесь ответ просто для справки, если у кого-то, например, нет времени спросить AI, да и пора отпусков, может не у всех удобный интернет или VPN, чтобы спросить AI. Например, я сам этот опенсорсный список детально не смотрел, на пляже, если будет минутка, можно что-то погуглить по очереди.

Тут же мой прошлый комментарий и не звучит как 100% рекомендация, он с долей сомнения и для справки.

Плюс статья, в первую очередь, про выбор KPI, чтобы получить об этом представление.

И по поводу BI системы или инструментов - выбор вроде есть, но очень часто его на самом нет. Например, до 2022 года SAP BI был практически стандартом для компаний уровня Газпрома, крупных металлургических компаний и т.д., у которых есть акции на рынке и которые проходят аудиторскую проверку и публикуют свою отчетность и информацию для инвесторов. Или, например, амбициозная IT компания может считать KPI своими силами, и выбор инструментов уже может быть в рамках стека приоритетного языка программирования компании, а не опенсорсных систем. У российских гос. компаний свои требования к безопасности BI систем, какие-то опенсорсные системы могут им не удовлятворять.

Т.е. при выборе BI системы нужно учитывать требования рынка (например, информация для акционеров), учитывать структуру компании (например, группа компаний, и требуется ли консолидированная отчетность), сколько видов отчетности требуется (например, отченость по международным стандартам МСФО и РСБУ), учитывать ограничения безопасности для гос. компаний, учитывать возможности IT подразделения самой компании, учитывать бюджет, сроки, успехи конкурентов на рынке и т.д. Если применить все эти фильтры, то список BI систем сильно сокращается, и для многих компаний вовсе исключаются опенсорсные BI системы.

UPDATE: по поводу Apache Superset, например, посмотрел демо видео на главной странице, там как-то не очень заметно какого-то сложного drill down, итогов-подытогов, таблиц с группировкой с +/-, сводных таблиц, сложных фильтров и т.д., как-то негусто на первый взгляд, на минималках. Ещё условно такие критерии есть.

Из опенсорсных, похоже, популярные:

  1. Apache Superset: платформа визуализации и исследования данных с открытым исходным кодом, разработанная как визуальная, интуитивно понятная и интерактивная.

  2. Metabase: простой и легкий инструмент бизнес-аналитики, который позволяет пользователям легко визуализировать и анализировать данные.

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

  4. Apache Druid: высокопроизводительная аналитическая база данных в режиме реального времени, предназначенная для быстрых специальных запросов к большим наборам данных.

  5. KNIME: платформа анализа данных с открытым исходным кодом, которая позволяет пользователям создавать визуальные рабочие процессы для обработки, анализа и визуализации данных.

  6. Pentaho: Комплексная платформа бизнес-аналитики с открытым исходным кодом, которая предлагает интеграцию данных, интеллектуальный анализ данных, отчеты, информационные панели и многое другое.

  7. BIRT (Инструменты бизнес-аналитики и отчетности): проект программного обеспечения с открытым исходным кодом, который позволяет пользователям создавать визуализации данных, отчеты и информационные панели.

Без ограничений по a1 в T никак, без ограничений по a1 даже INNER JOIN наоборот превратится в CROSS JOIN:

SELECT T_1.a1, T_2.a1 FROM T AS T_1 INNER JOIN T AS T_2 ON T_1.a1 = T_2.a1

Ограничения по a1 в T могут быть разные (уникальность, первичный ключ, уникальность на основе данных в таблице T, но без формальных ограничений уникальности на уровне ClickHouse), и связь T_1.a1 и T_2.a1 может быть условно через третьи таблицы, каждый случай нужно рассматривать отдельно, но условие T_1.a1 = T_2.a1 по крайней мере должно работать (обеспечивать связь один к одному) на основе какого-то набора данных, чтобы дальше исследовать проблему.

Согласен, что для произвольного запроса убрать CROSS JOIN невозможно, но в статье рассматриваются три частных случая и есть условия их применимости, не предлагается выкинуть любой CROSS JOIN. Такое впечатление, что в комментарии не дубликаты имеются в виду, а декартово произведение, полный перебор. Три случая в статье относятся к особым видам запросов, где действительно можно убрать CROSS JOIN. Здесь я проиллюстрировал два запроса: первый попадает под один из описанных случаев, второй нет, и так и остаётся CROSS JOIN.

Кроме того, в реляционной алгебре нет дубликатов (т.к. идёт работа со множествами), но декартово произведение всё равно используется, т.е. декартово произведение без дубликатов (другого декартового произведения условно и нет в реляционной алгебре) и CROSS JOIN без дубликатов как минимум не лишены смысла, поэтому с учетом того, что проектов и кейсов много, и здесь наверно тоже какие-то частные случаи имеются в виду, и этот кейс не противоречит кейсам из статьи

 CROSS JOIN, которые я встречал, именно для того и нужны, чтобы произвести дубликаты

Точно, здесь как раз простые случаи, как от него избавиться и что нужно учесть

Согласен, но и на практике при ручном написании запросов такие случаи тоже встречаются (хоть и в виде диких ляпов).

Эти случаи могут быть актуальными, когда SQL генерируется кодом (.NET, Java, Go и т.д.) для конкретного UI или отчета, т.е. не вручную. Во всех трех случаях для таблицы с 1 млн записей условно UI корректный (например, сводная таблица), или отчет условно корректный, т.е. их можно получить не за 1 млн × 1 млн операций, а за разумное число операций, условно 1 млн, но из-за CROSS JOIN получить отчет невозможно. Т.е. это больше для случаев, когда SQL генерируется не вручную и чинится тоже не вручную.

Рассмотренные случаи помогают что-то исправить в CROSS JOIN (удалить его) без значительного вмешательства в проект, такого, как:

  • ограничить число записей в запросе для одной или обеих таблиц в CROSS JOIN (например, LIMIT, LIMIT BY, topK в ClickHouse, или обычный GROUP BY - если возможно)

  • добавление паджинации для одной или обеих таблиц из запроса (если возможно)

  • условное упрощение сводной таблицы до таблицы размером 4 × 4 и выполнение 16 отдельных запросов для каждой ячейки (может быть актуально, например, для таблиц по кварталам или месяцам, при возможности можно выполнять запросы параллельно)

  • добавление или изменение фильтров для сводной таблицы

  • отказ от сводной таблицы как условно последнее средство, замена одного отчета несколькими и т.д., т.е. пересмотр бизнес-логики

Согласен, забыл в том случае дополнить, что a1 в T даже должно быть уникальным, ненулевым, в общем, ключом, иначе совсем не получится JOIN по ON T_1.a1 = T_2.a1;

Согласен, что разные результаты для SELECT T_1.a1, T_1.a1 FROM T AS T_1 CROSS JOIN T AS T_2; и SELECT a1, a1 FROM T;, пояснение "возвращают одинаковые результаты с точностью до дубликатов (которые можно удалить с помощью GROUP BY)" может выглядеть неоднозначно, в playground приведён пример

SELECT T_1.a1, T_1.a1 FROM T AS T_1 CROSS JOIN T AS T_2 GROUP BY T_1.a1, T_1.a1;

SELECT a1, a1 FROM T;

Он корректен, если a1 - это ключевое уникальное поле, для произвольного a1 корректно только такое:

SELECT T_1.a1, T_1.a1 FROM T AS T_1 CROSS JOIN T AS T_2 GROUP BY T_1.a1, T_1.a1;

SELECT a1, a1 FROM T GROUP BY a1, a1;

Согласен, что с точки зрения SQL это можно назвать иначе, "оптимизация CROSS JOIN" - для упрощения, чтобы не писать условно "оптимизация производительности SQL запроса путём удаления CROSS JOIN и замены на эквивалентный SQL запрос с другими типами JOIN (или без них) и дополнительными ограничениями, который возвращает те же результаты запроса"

Информация

В рейтинге
428-й
Откуда
Россия
Работает в
Дата рождения
Зарегистрирован
Активность

Специализация

Fullstack Developer
Lead