Mysql学习总结(35)——Mysql两千万数据优化及迁移
最近有一张2000W条记录的数据表需要优化和迁移。2000W数据对于MySQL来说很尴尬,因为合理的创建索引速度还是挺快的,再怎么优化速度也得不到多大提升。不过这些数据有大量的冗余字段和错误信息,极不方便做统计和分析。所以我需要创建一张新表,把旧表中的数据一条一条取出来优化后放回新表;
一. 清除冗余数据,优化字段结构
2000W数据中,能作为查询条件的字段我们是预知的。所以将这部分数据单独创建新的字段,对于有规则的数据合理改变字段结构,比如身份证就是varchar(18)。对于不重要的数据我们合并后存在一个结构为text的字段。
对于一些有关联的数据我们需要计算,常见的比如身份证种能获取到准确的性别,出生地、生日、年龄。
二. 数据迁移
我们从数据库中取出一条旧数据,再通过计算处理后得到想要的新数据,最后将新数据插入新表。不过在获取新数据时遇到如下问题。
数据量太大,无法一次获取(2000W数据扔到内存挺可怕的);
我们可以通过MySQL的limit语法分批获取。比如每次获取50000,SQL语句如下:
select * from table_name limit 15000000,50000;通过这种方法能解决数据量太大的问题,但是随着limit的第一个参数越来越大,查询速度会慢的吓人(上面这条SQL执行会花35秒)。时间就是生命,于是我们开始优化SQL语句,优化后变成下面这样:
select * from table_name order by id desc limit 5000000,50000;可通过二分法拆分2000W数据,当执行到1000W数据时,将数据倒序。优化后SQL执行效率显著提升,从35秒降到9秒;
不过还是很慢,时间就是生命……还好我们有自增ID(创建数据表第一条定律,一定要有自增字段),优化后的SQl如下:
1. select * from table_name where id>15000000 and id<15050000;
2. select * from table_name where id>15000000 limit 50000;为了直观演示,我写了两条功能一样的SQL。相比第一条,第二条的limit会导致SQL的索引命中变差,效率同样也会下降。第一条SQL的执行时间是2毫秒,第二条执行时间5毫秒(我取的平均值)。每次数据的查询速度直接从35秒降到2毫秒……
数据量太大并且数据无法预估,某些特殊数据会导致数据导入失败;
我们有三种方案去将新数据存入新表,分别如下:
一条一条插入数据;
开始肯定会想这种方案一定不行,因为每次插入都会有一次数据库IO操作。但是该方案有个好处是能及时发现有问题的数据,修改后再继续执行; 在Oracle中使用『绑定变量』能带来性能提升,正好MySQL也提供了『绑定变量』的功能。于是在不改变逻辑的情况下,尝试优化数据存储速度。代码如下:
public function actionTest(array $data)
{
$mysqli = new mysqli("192.168.1.106", "username", "password", "test");
$sql = "insert into table_name(name,identity) values (?,?)"; $stmt = $connection->prepare($sql);
$name = "";
$identity = "";
//使用绑定变量
$stmt->bind_param("si", $name, $identity);
foreach($data as $val)
{
$name = $val[name];
$identity = $val[card_id];
//执行
$stmt->execute();
}
$stmt->close();
}最后效果不怎么好,MySQL的『绑定变量』并没带来明显的速度提升,不过能有效的防止SQL注入;
一次插入50000条数据;
这是我最后选中的方案,一是能及时发现有问题的数据,二是导入数据非常稳定。就像支持断点续传一样,每一步都能看到效果。在执行脚本时,也能同步开始写分析逻辑;
组装成SQL文件,最后统一导入;
组装一个大的SQL文件,最后通过MySQL自带的工具导入也是极好的。但如果有一条SQL有问题,你可能需要重跑一次脚本。因为在9G大小的文本文件中修改一个符号是很痛苦的事情……
三. 总结
通过各种优化,最后将脚本执行时间缩短到了20分钟内。优化后数据质量得到了较高保证,下次将尝试2亿数据的优化&迁移……
Mysql学习总结(35)——Mysql两千万数据优化及迁移的更多相关文章
- Mysql学习笔记(三)对表数据的增删改查。
正文内容. 这一部分是最简单的,也是最麻烦的.简单是因为其实只包括增删该插四个部分.大体上看,增加数据.删除数据.修改数据.查询数据都不麻烦啊,我们日常都是常用的.这个谁不会呢?以前在培训机构学mys ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 导入数据
1.mysql 命令导入 使用 mysql 命令导入语法格式为: mysql -u用户名 -p密码 < 要导入的数据库数据(runoob.sql) 实例: # mysql -uroot -p12 ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 处理重复数据
有些 MySQL 数据表中可能存在重复的记录,有些情况允许重复数据的存在,但有时候我们也需要删除这些重复的数据. 防止表中出现重复数据 可以在 MySQL 数据表中设置指定的字段为 PRIMARY K ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL简介
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...
- mysql学习3:mysql之my.cnf详解
mysql之my.cnf详解 本文转自:https://www.cnblogs.com/panwenbin-logs/p/8360703.html 以下是 my.cnf 配置文件参数解释: #*** ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 安装
所有平台的 MySQL 下载地址为: MySQL 下载:https://dev.mysql.com/downloads/mysql/ 注意:安装过程我们需要通过开启管理员权限来安装,否则会由于权限不足 ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 运算符
要介绍 MySQL 的运算符及运算符的优先级. MySQL 主要有以下几种运算符: 算术运算符 比较运算符 逻辑运算符 位运算符 算术运算符 MySQL 支持的算术运算符包括: 在除法运算和模运算中, ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 事务
MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成 ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL UNION 操作符
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中.多个 SELECT 语句会删除重复的数据. 语法 MySQL UNION 操作符语法格式: SELECT ...
随机推荐
- js里写html代码 啥时候要用“\"转义
当去掉\的时候 字体变黑 需要加\
- Linux 技巧:让进程在后台可靠执行的几种方法
我们常常会碰到这种问题.用 telnet/ssh 登录了远程的 Linux server,执行了一些耗时较长的任务, 结果却因为网络的不稳定导致任务中途失败.怎样让命令提交后不受本地关闭终端窗体/网络 ...
- TOMCAT虚拟路径配置
在tomcat安装好后,只要把你的web项目copy到%TOMCAT_HOME%webapp下面就可以是使用啦!!其实还有种方法就是设定虚拟目录,即把项目的目录映射到tomcat中.这样做即可以不用重 ...
- linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库
linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库 创建静态库:ar -rcs test.a *.o查看静态库:ar -tv test.a解压静态库:ar -x test.a 查 ...
- 0x26 广搜变形
电路维修 这道题虽然乍一看就会想斜对角的两点之间边权受初始电路的影响要么为0要么为1,但是有一个思考点就是可以通过奇偶性,证明相邻的两个点是不可能在同一个电路中.练习一下双端队列. #include& ...
- [BZOJ 3365] Distance Statistics
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3365 [算法] 点分治 [代码] #include <algorithm> ...
- 7.gcc的使用
什么是gcc gcc编译器(GNU C Compiler) 现在我们所说的 gcc 是 GUN Compiler Collection的缩写,可以支持多种语言编译,比如 C,C++,Java, pas ...
- SQL语句之Insert
插入常见的3种形式: 单条插入, 批量插入, 返回刚插入行的id http://www.cnblogs.com/yezhenhan/archive/2011/08/17/2142948.html
- WINDOWS系统注册表(读、写)
读取注册表 写入注册表
- C语言中文件定位函数总结
C语言中文件定位函数主要是:fseek, ftell, fsetpos, fgetpos. 先来讲前两个函数,这是最基本的定位函数: fseek函数:能把文件指针移动到文件任何位置,其原型是:int ...