我是如何用2个Unix命令给MariaDB SQL提速的
我试图在 MariaDB(MySQL)上运行一个简单的连接查询,但性能简直糟糕透了。下面将介绍我是如何通过两个简单的 Unix 命令,将查询时间从 380 小时降到 12 小时以下的。
下面就是这个查询,它是 GHTorrent 分析的一部分,我使用了关系在线分析处理框架 simple-rolap 来实现这个分析。
?
1
2
3
4
5
6
select distinct
project_commits.project_id,
date_format(created_at, ‘%x%v1') as week_commit
from project_commits
left join commits
on project_commits.commit_id = commits.id;
两个连接字段都有索引。不过,MariaDB 是通过对 project_commits 进行全表扫描和对 commits 进行索引查找来实现连接的。这可以从 EXPLAIN 的输出看出来。

这两个表中的记录比较多:project_commits 有 50 亿行记录,commits 有 8.47 亿行记录。服务器的内存比较小,只有 16GB。所以很可能是因为内存放不下那么大的索引,需要读取磁盘,因此严重影响到了性能。从 pmonitor 对临时表的分析结果来看,这个查询已经运行半天了,还需要 373 个小时才能运行完。
/home/mysql/ghtorrent/project_commits#P#p0.MYD 6.68% ETA 373:38:11
在我看来,这个太过分了,因为排序合并连接(sort-merge join)所需的 I/O 时间应该要比预计的执行时间要低一个数量级。我在 dba.stackexchange.com 上寻求帮助,有人给出了一些建议让我尝试,但我没有信心它们能够解决我的问题。我尝试了第一个建议,结果并不乐观。尝试每个建议都需要至少半天的时间,后来,我决定采用一种我认为可以有效解决这个问题的办法。
我将这两个表导出到文件中,使用 Unix 的 join 命令将它们连接在一起,将结果传给 uniq,把重复的行移除掉,然后将结果导回到数据库。导入过程(包括重建索引)从 20:41 开始,到第二天的 9:53 结束。以下是具体操作步骤。
1. 将数据库表导出为文本文件
我先导出连接两个表需要用到的字段,并按照连接字段进行排序。为了确保排序顺序与 Unix 工具的排序顺序兼容,我将字段转换为字符类型。
我将以下 SQL 查询的输出保存到文件 commits_week.txt 中。
?
1
2
3
4
select cast(id as char) as cid,
date_format(created_at, ‘%x%v1') as week_commit
from commits
order by cid;
然后将以下 SQL 查询的输出保存到 project_commits.txt 文件中:
?
1
2
3
select cast(commit_id as char) as cid, project_id
from project_commits
order by cid;
这样就生成了以下两个文件。
-rw-r–r– 1 dds dds 15G Aug 4 21:09 commits_week.txt
-rw-r–r– 1 dds dds 93G Aug 5 00:36 project_commits.txt
为了避免内存不足,我使用 –quick 选项来运行 mysql 客户端,否则客户端会在输出结果之前尝试收集所有的记录。
2. 使用 Unix 命令行工具处理文件
接下来,我使用 Unix 的 join 命令来连接这两个文本文件。这个命令线性扫描两个文件,并将第一个字段相同的记录组合在一起。由于文件中的记录已经排好序,因此整个过程完成得很快,几乎就是 I/O 的速度。我还将连接的结果传给 uniq,用以消除重复记录,这就解决了原始查询中的 distinct 问题。同样,在已经排好序的输出结果上,可以通过简单的线性扫描完成去重。
这是我运行的 Unix 命令。
join commits_week.txt project_commits.txt | uniq >joined_commits.txt
经过一个小时的处理,我得到了想要的结果。
-rw-r–r– 1 dds dds 133G Aug 5 01:40 joined_commits.txt
3. 将文本文件导回数据库
最后,我将文本文件导回数据库。
?
1
2
3
4
5
6
create table half_life.week_commits_all (
project_id INT(11) not null,
week_commit CHAR(7)) ENGINE=MyISAM;
load data local infile ‘joined_commits.txt'
into table half_life.week_commits_all
fields terminated by ‘ ‘;
相关热词: 命令
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://www.juheyunku.com/sql/mariadb/8564.shtml
相关文章
热门TAG
命令 权重 外链 企业网站 白帽 php 织梦教程 dedecms修改内容 javascript 织梦 功能 标签 调用 详解 服务器 网站流量 实例解析 Dedecms 织梦cms HTML tags标签 python jquery教程 jquery windows SEO优化 蜘蛛 搜索引擎 网站收录 JSP最新文章
-
mariadb 在低配 VPS 上崩溃问
时间:2020-12-25
-
centos 7安装mysql5.5和安装
时间:2020-12-25
-
Mysql/MariaDB启动时处于进度
时间:2020-12-25
-
详谈MySQL和MariaDB区别与性
时间:2020-12-24
-
浅谈MySQL和mariadb区别
时间:2020-12-24
-
MySQL分支选择参考:Perco
时间:2020-12-24
-
Windows10系统下安装MariaDB
时间:2020-12-24
-
我是如何用2个Unix命令给
时间:2020-12-24
热门文章
-
Mysql/MariaDB启动时处于进度条状态导致启动
时间:2020-12-25
-
Windows Server 2016 服务器配置指南 之 Maria
时间:2020-12-24
-
centos 7安装mysql5.5和安装 mariadb使用的命令
时间:2020-12-25
-
我是如何用2个Unix命令给MariaDB SQL提速的
时间:2020-12-24
-
详谈MySQL和MariaDB区别与性能全面对比
时间:2020-12-24
-
Windows10系统下安装MariaDB 的教程图解
时间:2020-12-24
-
浅谈MySQL和mariadb区别
时间:2020-12-24
-
mariadb 在低配 VPS 上崩溃问题处理方案
时间:2020-12-25
-
MySQL分支选择参考:Percona还是MariaDB
时间:2020-12-24
