写在前面的话
公司一直在用MySql,最近由于业务量增大,数据压力也越来越大,MySQL的问题也逐渐暴露出来,之前只听说mysql性能不行,没想到几千条数据之间的关联查询也卡到需要优化的地步。
我之前用过很长一段时间的SqlServer,一般是数据量达到十万级以上才开始进行优化,几千条数据的表都是随便写逻辑的,从来不考虑性能问题,这让我产生了兴趣,想看看MySQL性能到底有多差。
既然要测评,所幸把最近非常火的PostgreSql和DB界老大Oracle也拉出来一起玩玩。
由于第一次接触PostgreSql和Oracle,配置方面不太了解,以下对这两种数据库的测试结果可能不是最优情况。Oracle大神勿喷。
测试环境
阿里云服务器 4核16G内存
Windows Server2012R2 x64
5Mbps带宽
高效云盘(2120IOPS)
数据库版本
MySql 8.0.19
Oracle 11G 企业版
MSSqlServer 2012 企业版
PostgreSql 13.3-2
数据库脚本(仅mysql)
数据库脚本只粘mysql的了,其他几种数据库大同小异
CREATE TABLE `itest_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`str` varchar(255) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL,
`iname` varchar(50) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `inameindex`(`iname`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = gbk COLLATE = gbk_chinese_ci ROW_FORMAT = Dynamic;
测试程序
测试程序 java + springboot + mybatis
为了贴近实际的生产环境,是用java程序在本地进行的测试,而数据库是在服务器上,所以测试结果可能受网络影响。
但考虑到生产环境下的执行效率也会受到网络和代码逻辑的影响,所以感觉本测试虽然不如专业的数据库测评结果准确,但是却更实用。
四种数据库是一套程序,仅数据源不同
//实体
import lombok.Data;
@Data
public class ItestTable {
int id;
String str;
String iname;
}
//mapper
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface ItestTableMapper {
@Select("select * from itest_table")
public List<ItestTable> selectAll();
@Select("select * from itest_table where str like '%${str}%'")
public List<ItestTable> selectByStr(@Param("str")String str);
@Select("select * from itest_table where iname = #{iname}")
public List<ItestTable> selectByIname(@Param("iname")String iname);
@Insert("insert into itest_table(str,iname) values(#{str},#{iname})")
public void insert(@Param("str") String str, @Param("iname") String iname);
@Update("update itest_table set str = '修改后' where iname = '乙'")
public void update();
}
//测试用例
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
@Slf4j
class SpringbootDemoApplicationTests {
@Autowired
ItestTableMapper itestTableMapper;
//首先清空全部数据
@Test
void insert1000()
{
String str = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨";
String[] nameAyy = new String[]{"甲","乙","丙","丁","戊","己","庚","辛"};
long stime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
itestTableMapper.insert(str+i,nameAyy[i%4]);
}
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
@Test
void select1000(){
long stime = System.currentTimeMillis();
List<ItestTable> list = itestTableMapper.selectAll();
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
@Test
void insert10000()
{
String str = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨";
String[] nameAyy = new String[]{"甲","乙","丙","丁","戊","己","庚","辛"};
long stime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
itestTableMapper.insert(str+i,nameAyy[i%4]);
}
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
@Test
void select11000(){
long stime = System.currentTimeMillis();
List<ItestTable> list = itestTableMapper.selectAll();
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
//此时创建索引
@Test
void insert10000WithIndex()
{
String str = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨";
String[] nameAyy = new String[]{"甲","乙","丙","丁","戊","己","庚","辛"};
long stime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
itestTableMapper.insert(str+i,nameAyy[i%4]);
}
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
@Test
void selectNoIndex(){
long stime = System.currentTimeMillis();
List<ItestTable> list = itestTableMapper.selectByStr("1");
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
@Test
void selectWithIndex(){
long stime = System.currentTimeMillis();
List<ItestTable> list = itestTableMapper.selectByIname("甲");
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
@Test
void update()
{
long stime = System.currentTimeMillis();
itestTableMapper.update();
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
}
测试结果
单位:毫秒
测试结论
1.Oracle作为DB界扛把子,测评结果却不尽如人意,与网上的评价不符,怀疑是我配置的有问题,毕竟今天是我第一次安装使用Oracle,感觉安装麻烦、配置复杂,不会配置效率还超低,而且还收费!直接弃用。
2.MySql读写性能全面败北,优点是配置简单,且生态系统完善,有很多基于MySql开发的组件、工具,作为java程序员,想要完全放弃MySql几乎不可能;但MySql确实也不适合作为复杂业务的主力数据库,由于其轻量级的特点,可以作为辅助库参与系统。
3.PostgreSql最近的火爆也不是没有理由,作为完全开放源代码的数据库,插入性能方面完全碾压MySql,查询性能也毫不逊色。重点是安装配置极为简单,Oracle和PostgreSql同样为第一天接触,PostgreSql的上手难度比Oracle低很多。在不考虑生态的情况下,PostgreSql可以完全替代MySQL。若作为主力数据库,查询效率还是略显不足。
4.MSSqlServer的插入速度比Oracle稍有逊色,但是查询效率完全碾压其他三种数据库。有着令人意想不到的10倍的差距。而且文件体积也比较小。
我相信在Oracle大神的手中,Oracle性能可以碾压SqlServer,但是SqlServer却可以实现开箱即用,非常适合中小型公司的项目,且正版价格比Oracle低不少。