Dentsu Aegis Network每天都在做品牌与人之间的交流,而数据分析是这项工作不可或缺的一部分。 在某些情况下,此过程不需要数据科学(尽管我们确实有数据科学),所以我们使用
Tableau BI平台。 其主要目的是为我们的员工和客户提供方便的界面来进行数据使用,而无需编写脚本,SQL查询等。
在本文中,我们将描述我们如何解决Tableau与
ClickHouse交互的问题。
问题的一般说明
我们面临着经典的挑战。 我们有人。 他们喜欢水果。 有些人喜欢一种水果,有些人喜欢所有水果,其他人可以喜欢水果的任何组合。

因此,有必要使用户能够在Tableau内置的仪表板上随意选择几种水果,并查看其中有多少人喜欢至少一种水果。 当然,我们没有水果,但是人们是真实的,只是在“水果”上更容易理解问题。
在我们的案例中,数据量非常大。 一万三千种不同的“水果”。 最受欢迎的“水果”拥有近3400万粉丝。 平均有45万人喜欢每种“水果”。 水果爱好者总数-2.82亿。
第一个额头解决方案
碰巧我们在
PostgreSQL (PG)和ClickHouse(CH)中拥有用于此任务的数据。 在PG中,有一个关于“水果”的参考表,在CH中,是一个具有以下结构的大表:“水果”的标识符和爱这个“水果”的人的标识符。 Tableau中没有用于CH的本机连接器,我仍然不想将数据传输到某个地方,因为这将需要对现有系统进行认真的重新设计。
我们尝试使用ODBC驱动程序将Tableau连接到CH,然后看看会发生什么。
- 并非所有的ODBC驱动程序都同样有用。 我们需要某个版本,该版本的功能的必要部分可以在其中运行,但不能保证其余部分在您突然需要时也可以运行。
- 我们无法将所有数据提取到Tableau提取物中,因为它是13,000 * 450,000 = 5,850,000,000个记录。
接下来,我们决定在CH数据库的查询中使用抽样,即,不是对所有人都估计了所选“水果”组合的恋人数量,而是对5%的样本进行了估计,以使提取的样本变小。 另外,我们立即从CH中使用PG“水果”目录进行内部联接获取,以获得“水果”名称。 它有帮助-我们的提取物能够在5小时内生成。
我们需要每天更新一次仪表板中的数据,因此5个小时的更新摘录似乎还可以-我们将在晚上进行更新。 但是在将来,我们将需要更多的功能:应该有更多的“水果”;因此,我们需要计算其交集的人群的数量和规模也应该增加。 因此,完全不选择对摘录进行长时间更新。
另外,由于采样还存在另一个问题。 碰巧的是,在我们国家,仪表板的不同部分的数字本来应该是一致的。 这是由于这样的事实,在一个地方,我们准确地计算了一种水果的恋人数量,并且在某种程度上结合了多种水果-不准确。 我们和我们的用户都不喜欢这个结果。
然后,我们决定根本不创建提取物。 为了避免加载大量数据,我们对数据集进行了划分,并对CH使用实时连接。 在数据集之间,使用内置的Tableau Edit关系功能建立了连接。 使用两个表中的“水果”标识符,将PG数据源设置为主要数据并将其链接为CH。
因此,我们能够使用主数据库(数据混合)过滤辅助数据源。 但是我们没有成功,因为在将过滤器从一个数据源扔到另一个数据源后,我们不得不使用对结果子集(COUNTD)中的人员进行计数的功能,并且数据混合有一个局限性,就是根本不允许这样做。 直接通过这种数据连接进行的这种功能原则上不起作用。
有一种变通方法可以帮助避免这种Tableau限制,但可以在相对较小的数据集上使用它,在我们的情况下显然不是这种情况。
之后,我们尝试了另一种选择。 数据集仍被拆分并用于CH的实时连接。 在这里,使用set操作将过滤器从描述为“水果”的数据集过滤到包含“水果”迷的数据集。 但是由于用户界面不方便,此选项最终不适合使用。 用户将不得不查看整个列表并通过cntrl + click选择“水果”,而不是用户熟悉的过滤器,而同时应用所有选定的值时,则没有应用功能。
结果,在我们所有的尝试之后,我们不得不返回到具有提取和采样的选项,非常慢,并且仅给出一个近似的答案。

找到解决方案
显然,我们不需要将所有数据提取到Tableau提取物中。 用户不喜欢一次查看所有数据-喜欢所有“水果”的人数。 他平均需要10个“水果”。 很遗憾,Tableau不知道如何执行此操作。
我们团队中有一些用Python编写的人。 因此,我们在搜索中决定朝这个方向移动并找到
TabPy 。
TabPy是一项Web服务,允许您获取Tableau成本核算中执行Python脚本的结果。
运作方式:
- Tableau使用所谓的“脚本函数”与TabPy交互,然后与Python交互。 脚本函数包含Python脚本本身,结果所需的数据类型以及我们传递给此函数的参数。 在我们的案例中,参数是“水果”的标识符,我们要计算的恋人数量。
- TabPy将接收到的脚本函数文本转换为脚本,并将其传递给解释器。 我们在脚本中注册了与CH库的连接。
- 接下来,TabPy将执行脚本的结果返回给Tableau。

在脚本函数中,参数始终作为数组传递;结果也由数组返回。
并非所有事情都立即起作用。 我们了解的主要内容:直接在Tableau中的计算字段中编写Python脚本不是一个好主意。 有两个原因:
- 在脚本函数内部,有时很难使用熟悉的Python语法。 例如,不接受多个引号。
- 考虑到将来对仪表板的支持,我们意识到,如果需要以某种方式更改脚本,那么每次都要在Tableau书本中进行更改。 这显然不是最佳方法,因为我们正在尽最大努力避免手动支持仪表板。
因此,我们使用了另一件事
-TabPy Client 。
TabPy客户端是一个库,可让您在TabPy服务器上发布Python脚本,然后在Tableau中调用它们。 使用它时,我们不用在Tableau中编写脚本,而是使用其中指定的参数调用TabPy服务器上的.py文件,将参数传递给它,然后执行它。
这种方法使用TabPy和Tableau解决了我们的问题。 该脚本是在熟悉的开发环境中编写和测试的,并且与本书分开存储,而本书现在不需要人工支持。
为了解决我们的特定问题,我们必须执行以下操作。
首先,我们尝试不使用TabPy Client来解决它。 在这种情况下,将在Tableau内部创建以下形式的“计算”字段:
它起作用了,但是上面描述了一些问题。 当我们找出TabPy Client时,我们意识到通过将Calculation字段和脚本本身进行划分,我们得到了一个更方便,更正确的系统。 这是“计算”字段和带有脚本的.py文件的样子:
在这里,您可以看到'people_count_test'是TabPy客户端的标识符,由于它可以清楚地在此Calculation字段中执行哪个脚本。
最终,这种方法使我们完全满意。

总结
用户之所以满意,是因为他们可以随意选择“水果”的组合,并迅速获得其中至少一个的风扇数量,并且仪表板不同部分的数量相同。
BI开发人员很高兴您可以使用Tableau中的ClickHouse,而不必直接连接到它。
我们的Tableau Server非常高兴,您无需在晚上进行大量提取。
通常,当Tableau没有开箱即用的合适解决方案时,TabPy将为BI开发人员提供更多的处理数据的自由。 例如,将数据科学模型直接嵌入Tableau中,但这完全是另一回事了……
本文是与我的同事Dimitri Shcherbenko(
dima_vs )和Sukhoveev Ivan(
suho_v )R&D Dentsu Aegis Network Russia共同撰写的。