阿里云官方最近提供了 MaxCompute 对 Metabase 的支持,今天我们来测用一下,详细文档。
Java 11 的安装方式可以通过网络查找相关资料,此处不作详细介绍。
下载以下三个 JAR 包文件:
metabase_0.52.2.jar
。maxcompute.metabase-driver.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_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,你将看到如下图所示的内容。
我们先查看当前 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 行,由于可能存在疏漏,这里暂不展示源码。