ClickHouse 与 MySQL 的互访
前言
如果你熟悉PostgreSQL,推荐你看ClickHouse与PostgreSQL互访这篇文章。
ClickHouse vs MariaDB ColumnStore文章部分 MySQL 没有资格入场 PK,但合作还是可以。今天介绍的这篇文章ClickHouse and MySQL – Better Together[1](作者:Vadim Tkachenko), 主要是让熟悉 MySQL 的人也可以快速上手 ClickHouse
ClickHouse 提供了两个和 MySQL 有关的功能,
使用 MySQL 协议和 MySQL 客户端连接到 ClickHouse 使用 MySQL 表选择和关联 ClickHouse 表
ClickHouse Server config.xml 默认添加了 MySQL 协议的支持
<!-- Compatibility with MySQL protocol.
ClickHouse will pretend to be MySQL for applications connecting to this port.
-->
<mysql_port>9004</mysql_port>复制
启动 ClickHouse 后会看到这样的日志
<Information> Application: Listening for MySQL compatibility protocol: [::1]:9004
<Information> Application: Listening for MySQL compatibility protocol: 127.0.0.1:9004复制
接下来,就可以使用 MySQL 客户端登录了,
MySQL 客户端通过 MySQL 协议访问 ClickHouse
登录
除了端口和 clickhouse 客户端访问时不一样外,其余一样,
$ mysql -h127.0.0.1 -P9004 -udefault -pqwert
复制
查看版本信息
select version();
+-------------+
| version() |
+-------------+
| 21.3.1.6016 |
+-------------+
1 row in set (0.005 sec)复制
很明细,这是我系统上 ClickHose 的版本信息。
接下来以ontime[2] 数据(本例起止时间为 2017 年 1 月~ 2019 年 11 月)为例做些尝试,
切换数据库及显示表名
mysql> use default;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+--------+
| name |
+--------+
| ontime |
+--------+
1 row in set (0.00 sec)
Read 1 rows, 31.00 B in 0.000 sec., 2038 rows/sec., 61.71 KiB/sec.复制
简单的查下总行数
select count(*) from ontime;
+----------+
| count() |
+----------+
| 19684341 |
+----------+
1 row in set (0.00 sec)
Read 1 rows, 4.01 KiB in 0.000 sec., 2150 rows/sec., 8.42 MiB/sec.复制
top 10 离港的城市
mysql> SELECT Origin,count(*) cnt FROM ontime GROUP BY Origin ORDER BY cnt DESC LIMIT 10;
+--------+---------+
| Origin | cnt |
+--------+---------+
| ATL | 1117414 |
| ORD | 911572 |
| DFW | 739334 |
| DEN | 689847 |
| LAX | 637070 |
| CLT | 562160 |
| SFO | 507377 |
| PHX | 488398 |
| IAH | 467543 |
| LAS | 463627 |
+--------+---------+
10 rows in set (0.03 sec)
Read 19684341 rows, 93.86 MiB in 0.027 sec., 726992466 rows/sec., 3.39 GiB/sec.复制
最热门的 10 条航线
mysql> SELECT Origin,Dest,count(*) cnt FROM ontime GROUP BY Origin,Dest ORDER BY cnt DESC LIMIT 10;
+--------+-------+-------+
| Origin | Dest | cnt |
+--------+-------+-------+
| SFO | LAX | 44419 |
| LAX | SFO | 44204 |
| LGA | ORD | 39276 |
| ORD | LGA | 39141 |
| LAX | JFK | 37309 |
| JFK | LAX | 37256 |
| LAX | LAS | 33780 |
| LAS | LAX | 33757 |
| OGG | HNL | 29619 |
| HNL | OGG | 29616 |
+--------+-------+-------+
10 rows in set (0.05 sec)
Read 19684341 rows, 187.73 MiB in 0.053 sec., 372125496 rows/sec., 3.47 GiB/sec.复制
与 MySQL 表关联
在 ClickHouse 中使用字典从 MySQL 获取数据的功能早就实现了,但是它并不方便,导致使用了非标准的 SQL 扩展。从那时起,ClickHouse 中实现了两个新功能:
支持 JOIN 语法 支持外部表
这使我们可以结合使用 MySQL 和 ClickHouse 表来运行更熟悉的查询。在转到示例之前,让我们回顾一下为什么需要这样做。
典型的数据分析设计假定存在大量事实表,其中引用了维度表(如果使用 ClickHouse 词典,则为字典)。有关详细示例,请参见星形模式[3]。
维度表的更改(更新)频率可能更高,而 ClickHouse 并不擅长它,因为它以更多类似追加的方式运行。因此,我们可能希望将纬度表存储在 OLTP 数据库(如 MySQL)中。顺便说一句,这也有助于 GDPR 政策删除个性化数据。如果将所有个人数据存储在非规范化的事实表中,那么删除它会变得非常复杂。相反,如果个人数据存储在维度表中,则很容易将其匿名化。
因此,让我们回到我们的示例。
ontime(事实表)有一个参考字段 AirlineID,这并不是很有用,因为我们想在报告中查看航空公司名称。
可以在BTS 网站[4]上找到 AirlineID – AirlineName 查找(纬度)表的数据。
看起来像这样:
我们将此数据加载到 MySQL 表中:
CREATE TABLE airlines
id INT NOT NULL PRIMARY KEY,
name VARCHAR(255)
)
select count(*) from airlines;
+----------+
| count(*) |
+----------+
| 1671 |
+----------+复制
现在,我们如何将此表连接到 ClickHouse?为此,在 ClickHouse 中,我们使用MySQL table engine
创建一个表:
Clickhouse->(我们可以使用 mysql 客户端工具连接到它,请参阅第一部分)。
CREATE TABLE airlinesclick
(
`id` Int32,
`name` String
)
ENGINE = MySQL('127.0.0.1:3306', 'click', airlines, 'sbtest', 'sbtest');复制
现在,我们可以执行一个查询,该查询将 ClickHouse 事实表(ontime)和 MySQL 维度表(airlinesclick)按航班 ID 关联起来,获得离港最多的十大航空公司:
SELECT name,count(*) cnt FROM ontime
JOIN airlinesclick ON ontime.AirlineID=airlinesclick.id
GROUP BY name ORDER BY cnt DESC LIMIT 10;
+-----------------------------+---------+
| name | cnt |
+-----------------------------+---------+
| Southwest Airlines Co.: WN | 3931500 |
| Delta Air Lines Inc.: DL | 2783305 |
| American Airlines Inc.: AA | 2680537 |
| SkyWest Airlines Inc.: OO | 2245105 |
| United Air Lines Inc.: UA | 1780665 |
| JetBlue Airways: B6 | 875858 |
| Alaska Airlines Inc.: AS | 673652 |
| ExpressJet Airlines LLC: EV | 665911 |
| Republic Airline: YX | 616362 |
| Envoy Air: MQ | 595908 |
+-----------------------------+---------+
10 rows in set (0.05 sec)
Read 19686012 rows, 75.15 MiB in 0.050 sec., 394346280 rows/sec., 1.47 GiB/sec.复制
我们使用熟悉的 JOIN 语法在 ClickHouse 中执行了一个关联查询,只是被关联的两个表存储在不同服务器中:MySQL 和 ClickHouse。
最后
和 ClickHouse 提供的 PostgreSQL 协议一样,很多第三方客户端都不支持,
使用 DBeaver 尝试连接会报错,
Unexpected driver error occurred while connecting to the database
复制
Python 下使用 sqlalchemy 会报错,
list index out of range
复制
参考资料
ClickHouse and MySQL – Better Together: https://www.percona.com/blog/2020/02/03/clickhouse-and-mysql-better-together/
[2]ontime: https://clickhouse.tech/docs/en/getting-started/example-datasets/ontime/
[3]星形模式: https://en.wikipedia.org/wiki/Star_schema
[4]BTS 网站: https://www.transtats.bts.gov/Download_Lookup.asp?Lookup=L_AIRLINE_ID
欢迎关注公众号
有兴趣加群讨论数据挖掘和分析的朋友可以加我微信(witwall),暗号:入群