您的位置:首页 > 数据库 > MySQL

mysql 与存储引擎的那些事

2015-04-16 19:40 176 查看

mysql 与存储引擎的那些事

一、介绍

mysql 有很多存储引擎,比较常用有InooDB,MyISAM,Memory,Merge,但用的比较多的是InnoDB,MyISAM。

存储引擎:MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。这些不同的技术以及配套的相关功能在MySQL中被称作存储引擎(也称作表类型)。

二、程序问题

创建表时不指明存储引擎,系统就会使用默认存储引擎,默认存储引擎是InnoDB,如果要修改存储引擎,指令如下

alter table tablename engine=myisam;


将存储引擎更改为myisam

说说之前一些经历,往数据库中插入数据,数据量很大,大概有9900多万条数据,用的存储引擎是InnoDB。另外,表一共有5个字段,其中三个添加mul索引,还有一个是主键索引。在执行往数据库中插数据,速度特别慢。第一次使用的机器是普通的台式机,500Mb的数据插了将近4个小时,但总的数据有21G,这样的话,将这些数据插入到数据库花费的时间将达到一周,速度太慢了。而且还会出现 堆溢出的情况,然后就扩大缓冲池的大小
buffer-pool-size = 256m
。具体为
` -Xms1024m -Xmx1500 -Xmn800m -XX:SurviorRation=8
,这样就不会出现堆溢出的情况。中间又用到很多方法进行优化以提高速度,比如java程序中的往数据库插的代码,通过+号来连接字符串:

String sql = "insert into writesql(useragent,getREQ,date,time,url)" + "values('"+useragent+"', +getREQ+"','"+date+"','"+time+"','"+URL+"')"


这种代码在执行时,速度会比较慢。后来又换了一种方法,字符串连接使用StringBuilder#append来替代”+”真的会带来性能提升么

StringBuffer sql = new StringBuffer();
sql.append("insert into writesql(useragent,getREQ,time,url)")
.append("values('")
.append(useragent.replace("'", "\\'"))
.append("', '")
.append(getREQ.replace("'", "\\'"))
.append("','")
.append(time)
.append("','")
.append(URL.replace("'", "\\'"))
.append("')");


```
`注`  “+”连接字符串会带来额外的内存消耗
append相对于会有一定的提升。另外,频繁往数据库中插入数据,sql语句可以用StringBuffer 代替String
再到后来,使用另外一种方法:

```shell
PreparedStatement insertItems = conn.prepareStatement("insert into writesql(mac,useragent,getREQ,time,url,router,path) values(?,?,?,?,?,?,?);");

insertItems.setString(1 , useragent);
insertItems.setString(2 , getREQ);
insertItems.setString(3 , time);
insertItems.setString(4 , URL);
insertItems.setString(5 , mac);
insertItems.setString(6 , router);
insertItems.setString(7 , path);


JDBC驱动里有个PreparedStatement的类,这个类可以大大的提高MySQL的速度和安全性,具体就是预编译相同类型的语句,这样每次提交请求的时候,就可以使用已经编译好的语句来查询或是更新数据库,虽然并不是什么情况都可以提高效率,但是使用他也不会降低效率;安全性方面就是防止了sql语句的漏洞。因为一次往数据库插入的数据量非常庞大,而PreparedStatement可以进行批处理。

选择PreparedStatement还是Statement取决于你要怎么使用它们. 对于只执行一次的SQL语句选择Statement是最好的。相反, 如果SQL语句被多次执行选用PreparedStatement是最好的。PreparedStatement的第一次执行消耗是很高的. 它的性能体现在后面的重复执行。而我这刚好满足重复执行insert语句。

statement 和PreparedStatement的区别

1、预防了sql注入的问题。因为在preparedStatement中把一些字符自动转义了。

2、Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。

PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。

前一段时间做的一些东西,总结一下吧。

使用系统,centos7,数据库用的是mariadb(centos7默认是mariadb),是可以兼容MySQL的。

将21G的数据导入到数据库中,用的存储引擎是InnoDB。往数据库插如数据很慢,而且插完之后,对已有的数据进行查询,查看日志文件,插入有9700多万条,数据量还是非常庞大的,已经添加过索引了。比如指令
select count(*) from tablename ;
用的时间特别长,超过5分钟。有条件的查询也是一样特别慢,如
select distinct url from tablename;
另外,中间又出现了一些问题,之前的数据又问题,又重新做了一遍。然后将这数据重新导入到数据库,就把就数据库的有问题的数据删除掉。但是我在执行指令
delete from tablename;
用了一天的时间,数据仍然没有删除掉。后来在网上查了,删除数据delete速度是最慢的,另外还有两个删除数据的方法,drop和truncate,速度快慢drop>truncate>delete。也就说delete删除数据的速度是最慢的。delete删除数据的机制:

更换存储引擎,速度特别快。存储引擎为MyISAM。

三、实验

现在做一个测试:对比存储引擎,表结构等是否会对查询的速度有影响。

1、存储引擎是InnoDB

对一份文件,文件大概有6.7g,插入数据库条数大概有15856781条,存储引擎是InnoDB,将这些数据插入到数据所耗费的时间为9025秒。

表结构如下:




通过查询语句
select count(*) from writesql;
统计行数,所用时间为3.75秒。

通过已建的索引进行查询
select distinct mac from writesql
查询没有重复的MAC地址,共有386行,所用的时间为0.12秒

2、存储引擎是MyISAM

对一份文件,文件大概有6.7g,插入数据库条数大概有15856781条,存储引擎是MyISAM,将这些数据插入到数据所耗费的时间为12229秒。

表的结构




通过查询语句
select count(*) from writesql;
统计行数,所用时间为0.00秒,瞬间出来。

通过已建的索引进行查询
select distinct mac from writesql
查询没有重复的MAC地址,共有386行,所用的时间为0.02秒

可见,存储引擎不同会带来不同影响。存储引擎为InnoDB,将数据插入到数据库中的速度还是比存储引擎为myisam的快很多。但是存储引擎为InnoDB在查询数据时,会比较慢,也就是InnoDB不适合频繁读。

3、在原有的基础上在插入新的数据,速度会不会有变化呢?

3.1、存储引擎是InnoDB

对一份文件,文件大概有6.7g,插入数据库条数大概有36691238条,存储引擎是MyISAM,将这些数据插入到数据所耗费的时间为17151秒。

通过查询语句
select count(*) from writesql;
统计行数,所用时间为0.00秒,瞬间出来。

通过已建的索引进行查询
select distinct mac from writesql
查询没有重复的MAC地址,共有619行,所用的时间为0.15秒 。

3.2、存储引擎是MyISAM

对一份文件,文件大概有6.7g,插入数据库条数大概有36691238条,存储引擎是MyISAM,将这些数据插入到数据所耗费的时间为17151秒。

通过查询语句
select count(*) from writesql;
统计行数,所用时间为0.00秒,瞬间出来。

通过已建的索引进行查询
select distinct mac from writesql
查询没有重复的MAC地址,共有619行,所用的时间为0.15秒 。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: