MySQL两种表存储结构MyISAM和InnoDB的性能比较测试

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

MySQL支持的两种主要表存储格式MyISAM,InnoDB,上个月做个项目时,先使用了InnoDB,结果速度特别慢,1秒钟只能插入10几条。后来换成MyISAM格式,一秒钟插入上万条。当时决定这两个表的性能也差别太大了吧。后来自己推测,不应该差别这么慢,估计是写的插入语句有问题,决定做个测试:
测试环境:Redhat Linux9,4CPU,内存2G,MySQL版本为4.1.6-gamma-standard
测试程序:Python+Python-MySQL模块。
测试方案:
1、MyISAM格式分别测试,事务和不用事务两种情况:
2、InnoDB格式分别测试AutoCommit=1(不用begin transaction和用begin transaction模式),
     AutoCommit=0 (不用begin transaction和用begin transaction模式)四种情况。

测试方法为插入10000条记录。为了测试不互相影响,单独建立了专用的测试表,建表语句如下:
1、MyISAM不用事务表:
CREATE TABLE `MyISAM_NT` (
  `TableId` int(11) NOT NULL default '0',
  `TableString` varchar(21) NOT NULL default ''
) ENGINE=MyISAM;

2、MyISAM用事务表:
CREATE TABLE `MyISAM_TS` (
  `TableId` int(11) NOT NULL default '0',
  `TableString` varchar(21) NOT NULL default ''
) ENGINE=MyISAM;

3、InnoDB关闭AutoCommit,不用事务:
CREATE TABLE `INNODB_NA_NB` (
  `TableId` int(11) NOT NULL default '0',
  `TableString` varchar(21) NOT NULL default ''
) ENGINE=InnoDB;

4、InnoDB关闭AutoCommit,用事务:
CREATE TABLE `INNODB_NA_BE` (
  `TableId` int(11) NOT NULL default '0',
  `TableString` varchar(21) NOT NULL default ''
) ENGINE=InnoDB;

5、InnoDB开启AutoCommit,不用事务:
CREATE TABLE `INNODB_AU_NB` (
  `TableId` int(11) NOT NULL default '0',
  `TableString` varchar(21) NOT NULL default ''
) ENGINE=InnoDB;

6、InnoDB开启AutoCommit,用事务:
CREATE TABLE `INNODB_AU_BE` (
  `TableId` int(11) NOT NULL default '0',
  `TableString` varchar(21) NOT NULL default ''
) ENGINE=InnoDB;

测试的Python脚本如下:

#!/usr/bin/env Python
'''
MyISAM,InnoDB性能比较
作者:空心菜(Invalid)
时间:2004-10-22
'''
import MySQLdb 
import sys
import os
import string
import time

c = None

testtables = [("MyISAM_NT",None,0),
             ("MyISAM_TS",None,1),
             ("INNODB_NA_NB",0,0),
             ("INNODB_NA_BE",0,1),
             ("INNODB_AU_NB",1,0),
             ("INNODB_AU_BE",1,1)
             ]

def BeginTrans():

    print "ExecSQL:BEGIN;"
    c.execute("BEGIN;")

    return

def Commit():

    print "ExecSQL:COMMIT;"
    c.execute("COMMIT;")
    return

def AutoCommit(flag):

    print "ExecSQL:Set AUTOCOMMIT = "+str(flag)
    c.execute("Set AUTOCOMMIT = "+str(flag))
    return

def getcount(table):
    #print  "ExecSQL:select count(*) from "+table
    c.execute("select count(*) from "+table)
    return c.fetchall()[0][0]

 
def AddTable (Table,TableId,TableString):

    sql = "INSERT INTO "+Table+"(TableId, TableString) VALUES( "+ TableId+ ",'" + TableString +"')"
    try:
        c.execute(sql)
    except MySQLdb.OperationalError,error:
        print "AddTable Error:",error
        return -1;
    return c.rowcount


def main():

    argv = sys.argv

    if len(argv) < 2:
        print 'Usage:',argv[0],' TableId TestCount \n'
        sys.exit(1)

    global c        #mysql访问cursor

    
    db_host = "localhost"
    db_name = "demo"
    db_user = "root"
    db_user_passwd = ""

    print "Config:[%s %s/%s %s] DB\n"%(db_host,db_user,db_user_passwd,db_name)

    if len(argv) > 2:
        tableid = argv[1]
        testcount = int(argv[2])   #

    for test in testtables:
        #每次操作前都重写建立数据库连接    
        try:
            mdb = MySQLdb.connect(db_host, db_user, db_user_passwd, db_name) 
        except MySQLDb.OperationalError,error:
            print "Connect Mysql[%s %s/%s %s] DB Error:"%(db_host,db_user,db_user_passwd,db_name),error,"\n"
            sys.exit(1)
        else:
            c = mdb.cursor()
        table,autocommit,trans = test
        starttime = time.time()
        print table," ",time.strftime("%y-%m-%d %H:%M:%S",time.localtime())

        if autocommit != None:
            AutoCommit(autocommit)

        if trans == 1:
            BeginTrans()

        for i in xrange(testcount):
            tablestring = "%020d"%i
            if (AddTable(table,tableid,tablestring)<1):
                print "AddTable Error",tablestring

        if trans == 1:
            Commit()

        print time.strftime("%y-%m-%d %H:%M:%S",time.localtime())
        endtime = time.time()
        usedtime = endtime-starttime

        print table,"count:",getcount(table)," used time:",usedtime
        c.close()
        mdb.close()


if __name__ == '__main__':
    main()
测试结果如下:

Config:[localhost root/ demo] DB

MyISAM_NT   04-10-22 16:33:24
04-10-22 16:33:26
MyISAM_NT count: 10000  used time: 2.1132440567
MyISAM_TS   04-10-22 16:33:26
ExecSQL:BEGIN;
ExecSQL:COMMIT;
04-10-22 16:33:29
MyISAM_TS count: 10000  used time: 2.65475201607
INNODB_NA_NB   04-10-22 16:33:29
ExecSQL:Set AUTOCOMMIT = 0
04-10-22 16:33:31
INNODB_NA_NB count: 10000  used time: 2.51947999001
INNODB_NA_BE   04-10-22 16:33:31
ExecSQL:Set AUTOCOMMIT = 0
ExecSQL:BEGIN;
ExecSQL:COMMIT;
04-10-22 16:33:35
INNODB_NA_BE count: 10000  used time: 3.85625100136
INNODB_AU_NB   04-10-22 16:33:35
ExecSQL:Set AUTOCOMMIT = 1
04-10-22 16:34:19
INNODB_AU_NB count: 10000  used time: 43.7153041363
INNODB_AU_BE   04-10-22 16:34:19
ExecSQL:Set AUTOCOMMIT = 1
ExecSQL:BEGIN;
ExecSQL:COMMIT;
04-10-22 16:34:22
INNODB_AU_BE count: 10000  used time: 3.14328193665
结论:
由此得知影响速度的主要原因是AUTOCOMMIT默认设置是打开的,
我当时的程序没有显式调用BEGIN;开始事务,导致每插入一条都自动Commit,严重影响了速度。
算来也是个低级错误!

相关参考:
http://dev.mysql.com/doc/mysql/en/COMMIT.html
http://dev.mysql.com/doc/mysql/en/InnoDB_and_AUTOCOMMIT.html













本文转自ljianbing51CTO博客,原文链接:http://blog.51cto.com/ljianbing/1611331 ,如需转载请自行联系原作者



相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
21天前
|
数据采集 监控 机器人
浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)
最开始转转的客服系统体系如IM、工单以及机器人等都是使用第三方的产品。但第三方产品对于转转的业务,以及客服的效率等都产生了诸多限制,所以我们决定自研替换第三方系统。下面主要分享一下网页端IM技术及相关测试方法,我们先从了解IM系统和WebSocket开始。
39 4
|
1天前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
6天前
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
45 7
|
16天前
|
存储 关系型数据库 MySQL
Mysql索引:深入理解InnoDb聚集索引与MyisAm非聚集索引
通过本文的介绍,希望您能深入理解InnoDB聚集索引与MyISAM非聚集索引的概念、结构和应用场景,从而在实际工作中灵活运用这些知识,优化数据库性能。
81 7
|
20天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
70 13
|
1月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
149 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
22天前
|
存储 关系型数据库 MySQL
MySQL引擎InnoDB和MyISAM的区别?
InnoDB是MySQL默认的事务型存储引擎,支持事务、行级锁、MVCC、在线热备份等特性,主索引为聚簇索引,适用于高并发、高可靠性的场景。MyISAM设计简单,支持压缩表、空间索引,但不支持事务和行级锁,适合读多写少、不要求事务的场景。
51 9
|
2月前
|
监控 测试技术 PHP
性能和压力测试
【10月更文挑战第10天】性能和压力测试
121 60
|
26天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
59 1
|
1月前
|
缓存 Ubuntu Linux
Linux环境下测试服务器的DDR5内存性能
通过使用 `memtester`和 `sysbench`等工具,可以有效地测试Linux环境下服务器的DDR5内存性能。这些工具不仅可以评估内存的读写速度,还可以检测内存中的潜在问题,帮助确保系统的稳定性和性能。通过合理配置和使用这些工具,系统管理员可以深入了解服务器内存的性能状况,为系统优化提供数据支持。
38 4

热门文章

最新文章