Резюме: Большинство примеров соединений MDX, которые я видел, включали объединение относительно небольших наборов, скажем, с десятками или сотнями элементов в каждом. Но я также обнаружил, что хочу попробовать объединить (в частности, «непустое объединение») наборы, каждый из которых состоит из тысяч или десятков тысяч элементов, и пока это не работает. Мне интересно, можно ли это заставить работать, или мне, возможно, нужно рассмотреть возможность использования чего-то другого, кроме Mondrian/OLAP.
Чтобы быть конкретным, у меня есть куб, который записывает взаимодействия между Фирмами (n = 7000) и Клиентами (n = 27000). В настоящее время и Фирма, и Клиент представляют собой совершенно плоские иерархии; есть уровень «Все» и уровень «индивидуальная компания», без каких-либо промежуточных уровней. Существует центральная таблица фактов и отдельные таблицы измерений для фирм и для клиентов.
По крайней мере, мои пользователи, похоже, хотят получать сводные отчеты по этим направлениям, объединяющие все непустые взаимодействия между Фирмами и Клиентами:
select
[Measures].[Amount] on columns,
NonEmptyCrossJoin([Firm].Children,
[Client].Children) on rows
from MyCube
Но этот запрос и его варианты не работают в моей тестовой установке Мондриана. Либо я получаю исключение OutOfMemoryException (в куче Java объемом 2 ГБ), либо Java тратит невероятно много времени на mondrian.rolap.RolapResult$AxisMember.mergeTuple(TupleCursor). (Я могу предоставить более полную трассировку стека, если это поможет.) Под «невероятно долго» я имею в виду, что Java будет часами работать над запросом, прежде чем я сдамся.
Первоначально я ожидал, что приведенный выше запрос будет выполняться нормально, потому что концептуально его можно было бы выполнить несколько эффективно, просто выполнив запрос SQL следующим образом:
select Firm, Client, Sum(Amount) as n
from fact, firm, client
where fact.firmid = firm.firmid and fact.clientid = client.clientid
group by Firm, Client
(На самом деле, если я выполняю что-то подобное непосредственно в MySql, выполнение занимает не более 15 секунд.)
Но судя по журналам отладки, Мондриан не пытается провести эту оптимизацию. Вместо этого он, похоже, выполняет соединение внутри себя и таким образом, что это оказывается особенно медленным. Я установил mondrian.native.crossjoin.enable=true в своих свойствах mondrian.properties, но это не похоже на один из типов соединения, которые Mondrian может «сделать родным». (Если я включу mondrian.native.unsupported.alert=ERROR, я получу соответствующее исключение.)
Я задаюсь вопросом, нужно ли мне предотвращать попытки моих пользователей объединяться в такие большие измерения / наборы, или Mondrian, возможно, не тот инструмент, который я ищу здесь. Но может я просто что-то не так делаю.