在新版 Metabase 中使用阿里云 MaxCompute (ODPS)

阿里云官方最近提供了 MaxCompute 对 Metabase 的支持,今天我们来测用一下,详细文档

前提条件

Java 11 的安装方式可以通过网络查找相关资料,此处不作详细介绍。

下载以下三个 JAR 包文件:

信息

在阿里云官方提供支持之前,如果想要使用 Metabase 连接 MaxCompute,就需要自行开发 Metabase MaxCompute Driver。该驱动使用 Clojure(一种 Java 方言) 进行开发,过程较为复杂。我曾在另一篇博文 中详细介绍过。我之前开发的驱动已不支持最新版的 Metabase,想到需要重新开发就感到头疼。幸运的是,现在阿里云官方已经提供了支持。

创建一个名为 metabase_dev 的 MySQL 数据库,用于存储 Metabase 相关数据。

DROP DATABASE IF EXISTS `metabase_dev`;
CREATE DATABASE IF NOT EXISTS `metabase_dev` DEFAULT CHARACTER SET utf8mb4;
USE `metabase_dev`;

部署 Metabase

metabase 目录下创建子目录 metabase_jar,用于存放 metabase_0.52.2.jar 文件。然后在 metabase 文件夹中新建部署脚本 deploy_metabase.sh,内容如下:

#!/bin/sh

export MB_DB_TYPE=mysql
export MB_DB_DBNAME=metabase
export MB_DB_PORT=3306
export MB_DB_USER=<username>
export MB_DB_PASS=<password>
export MB_DB_HOST=127.0.0.1
# 下面的密钥可以通过如下命令生成。注意一旦赋值,千万不要改!改了很坑!
# openssl rand -base64 32
export MB_ENCRYPTION_SECRET_KEY=<SECRET_KEY>

export MB_JETTY_PORT=3000
export MB_JETTY_HOST=0.0.0.0

ps -ef | grep "metabase_" | grep -v grep | awk '{print $2}' | xargs kill -9

nohup java -Duser.country=CN -Duser.language=zh -jar metabase_jar/metabase_0.52.2.jar>> metabase.log 2>&1&

tail -fn 200 metabase.log

deploy_metabase.sh 脚本添加可执行权限,然后运行该脚本。

chmod a+x deploy_metabase.sh
./deploy_metabase.sh

启动成功后,通过浏览器访问 http://localhost:3000 即可查看。首次使用时,系统会引导你进行管理员配置,过程非常简单,基本可以快速完成。查看关于 Metabase,你将看到如下图所示的内容。

支持 MaxCompute (ODPS)

我们先查看当前 metabase 目录的结构,可以看到新增了一个 plugins 文件夹,里面存放了多个数据库驱动的 jar 包。为了支持 ODPS,需要安装相应的驱动。在第一小节中已经下载了两个相关的 jar 包,安装方法是将这两个 jar 包放入 plugins 目录下,然后重启服务即可。

$ tree metabase
metabase
├── deploy_metabase.sh
├── metabase.log
├── metabase_jar
│   └── metabase_0.52.2.jar
└── plugins
    ├── athena.metabase-driver.jar
    ├── bigquery-cloud-sdk.metabase-driver.jar
    ├── databricks.metabase-driver.jar
    ├── druid-jdbc.metabase-driver.jar
    ├── druid.metabase-driver.jar
    ├── hive-like.metabase-driver.jar
    ├── mongo.metabase-driver.jar
    ├── oracle.metabase-driver.jar
    ├── presto-jdbc.metabase-driver.jar
    ├── redshift.metabase-driver.jar
    ├── sample-database.db.mv.db
    ├── snowflake.metabase-driver.jar
    ├── sparksql.metabase-driver.jar
    ├── sqlite.metabase-driver.jar
    ├── sqlserver.metabase-driver.jar
    └── vertica.metabase-driver.jar

2 directories, 19 files

重启完成后,进入管理员界面,在“数据库”选项卡下,即可选择 MaxCompute 数据库类型进行配置,示例如下:

自动选择最新分区

现在就可以直接连接 ODPS 进行数据查询,如下图所示。然而,许多 ODPS 表都是分区表,而使用 Metabase BI 工具的通常是产品、运营、销售等人员。他们经常忽略分区表的存在,忘记添加 where pt=20241209 这样的过滤条件,导致简单的查询变成了全表扫描,消耗大量计算资源。本小节将解决如何在没有手动指定分区的情况下,自动选择分区表的最新分区。

思路是对 SQL 语句进行改写。首先,检查查询中涉及的所有表,判断它们是否为分区表,然后获取最新的分区。根据这些信息,改写 SQL 语句,例如:

2024-12-10 20:20:08,060 WARN jdbc.OdpsConnection:: [connection-1] Before SQL: SELECT uuid, taxonomy1, form, pt FROM dwd_mongo_content_item_profile_day LIMIT 5;
2024-12-10 20:20:08,605 WARN jdbc.OdpsConnection:: [connection-1] Run SQL: SELECT uuid, taxonomy1, form, pt FROM dwd_mongo_content_item_profile_day where pt='20241209' LIMIT 5;, Begin time: 1733833208060

实际操作方法如下:修改 ODPS JDBC 的源码,主要是调整 OdpsStatement#runSQL 方法,在执行查询前进行 SQL 改写。随后重新打包,替换原有的 odps-jdbc-jar-with-dependencies.jar 文件。

我将 SQL 改写逻辑封装在 SqlHelper 类的静态方法中,然后在 OdpsStatement#runSQL 中进行简单调用。这样对源码的改动最小,即使 odps 源码更新,我也可以拉取最新代码,大概率不会出现代码冲突,只需重新打包即可。SqlHelper 的代码不足 100 行,由于可能存在疏漏,这里暂不展示源码。

相关推荐