MySQL支持的两种主要表存储格式MyISAM,InnoDB,上个月做个项目时,先使用了InnoDB,结果速度特别慢,1秒钟只能插入10几条。后来换成MyISAM格式,一秒钟插入上万条。当时觉的这两个表的性能也差别太大了吧。后来自己推测,不应该差别这么慢,估计是写的插入语句有问题,决定做个测试:
站长.站
测试环境:Redhat Linux9,4CPU,内存2G,MySQL版本为4.1.6-gamma-standard
中国站长.站
测试程序:Python+Python-MySQL模块。 中.国.站长站
测试方案: Www@Chinaz@com
1、MyISAM格式分别测试,事务和不用事务两种情况:
中.国.站长站
2、InnoDB格式分别测试AutoCommit=1(不用begin transaction和用begin transaction模式),AutoCommit=0 (不用begin transaction和用begin transaction模式)四种情况。 站长.站
测试方法为插入10000条记录。为了测试不互相影响,单独建立了专用的测试表,建表语句如下: Chinaz^com
1、MyISAM不用事务表: 中国.站.长站
以下为引用的内容:
CREATE TABLE `MyISAM_NT` ( 中国.站长站
`TableId` int(11) NOT NULL default ‘0’, Chinaz_com
`TableString` varchar(21) NOT NULL default ” Chinaz~com
) ENGINE=MyISAM;
中国.站长站
Chinaz~com
2、MyISAM用事务表: 中国.站长站
以下为引用的内容:
CREATE TABLE `MyISAM_TS` ( Chinaz.com
`TableId` int(11) NOT NULL default ‘0’, Chinaz~com
`TableString` varchar(21) NOT NULL default ”
Www_Chinaz_com
) ENGINE=MyISAM; Chinaz@com
Www~Chinaz~com
3、InnoDB关闭AutoCommit,不用事务: 中.国站长站
以下为引用的内容:
CREATE TABLE `INNODB_NA_NB` ( 站.长.站
`TableId` int(11) NOT NULL default ‘0’,
中.国.站.长.站
`TableString` varchar(21) NOT NULL default ”
[中国站长站]
) ENGINE=InnoDB; 中国站.长.站
Chinaz.com
4、InnoDB关闭AutoCommit,用事务: 中国站长_站,为中文网站提供动力
以下为引用的内容:
CREATE TABLE `INNODB_NA_BE` (
中国.站长站
`TableId` int(11) NOT NULL default ‘0’,
站长.站
`TableString` varchar(21) NOT NULL default ”
中.国.站.长.站
) ENGINE=InnoDB; Chinaz^com
Chinaz_com
5、InnoDB开启AutoCommit,不用事务:
中国站长_站,为中文网站提供动力
以下为引用的内容:
CREATE TABLE `INNODB_AU_NB` (
中国站.长.站
`TableId` int(11) NOT NULL default ‘0’, Chinaz_com
`TableString` varchar(21) NOT NULL default ”
Www~Chinaz~com
) ENGINE=InnoDB;
Www@Chinaz@com
中.国站长站
6、InnoDB开启AutoCommit,用事务: 中国.站长站
以下为引用的内容:
CREATE TABLE `INNODB_AU_BE` ( Chinaz^com
`TableId` int(11) NOT NULL default ‘0’, Chinaz@com
`TableString` varchar(21) NOT NULL default ” Www_Chinaz_com
) ENGINE=InnoDB; 站.长.站
测试的Python脚本如下: Www^Chinaz^com
#!/usr/bin/env Python
Chinaz~com
”’ 中.国站长站
中国站.长.站
MyISAM,InnoDB性能比较
[中国站长站]
作者:空心菜(Invalid) 中国.站长站
时间:2004-10-22 Chinaz^com
以下为引用的内容:
”’ [中国站长站]
import MySQLdb Www_Chinaz_com
import sys
中国站长_站,为中文网站提供动力
import os
中.国.站.长.站
import string
Www@Chinaz@com
import time Www_Chinaz_com
c = None Www~Chinaz~com
testtables = [("MyISAM_NT",None,0), Chinaz^com
("MyISAM_TS",None,1),
Www~Chinaz~com
("INNODB_NA_NB",0,0),
Chinaz.com
("INNODB_NA_BE",0,1), Www~Chinaz~com
("INNODB_AU_NB",1,0), Www_Chinaz_com
("INNODB_AU_BE",1,1) Chinaz
] 中国站.长.站
def BeginTrans():
Www_Chinaz_com
print "ExecSQL:BEGIN;" 中.国站长站
c.execute("BEGIN;")
[中国站长站]
return
中国站长.站
def Commit():
[中国站长站]
print "ExecSQL:COMMIT;"
Www.Chinaz.com
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 Chinaz~com
c.execute("select count(*) from "+table)
站.长.站
return c.fetchall()[0][0] Chinaz~com
def AddTable (Table,TableId,TableString): 中.国.站长站
sql = "INSERT INTO "+Table+"(TableId, TableString) VALUES( "+ TableId+ ",’" + TableString +"’)"
Www_Chinaz_com
try: 中.国.站.长.站
c.execute(sql)
Www~Chinaz~com
except MySQLdb.OperationalError,error:
Chinaz~com
print "AddTable Error:",error Www.Chinaz.com
return -1; 中.国.站长站
return c.rowcount 中.国.站.长.站
def main():
Chinaz
argv = sys.argv Www_Chinaz_com
if len(argv) < 2:
中.国站长站
print ‘Usage:’,argv[0],’ TableId TestCount \n’
中国.站.长站
sys.exit(1) Chinaz~com
global c #MySQL访问cursor
中国站长.站
db_host = "localhost"
Chinaz@com
db_name = "demo"
Chinaz~com
db_user = "root"
中国.站长站
db_user_passwd = "" [中国站长站]
print "Config:[%s %s/%s %s] DB\n"%(db_host,db_user,db_user_passwd,db_name)
Chinaz.com
if len(argv) > 2:
Chinaz
tableid = argv[1]
Www@Chinaz@com
testcount = int(argv[2]) #
中.国.站长站
for test in testtables: 中国.站.长站
中国站.长站
#每次操作前都重写建立数据库连接 站.长站
以下为引用的内容:
try: Chinaz
mdb = MySQLdb.connect(db_host, db_user, db_user_passwd, db_name) Chinaz^com
except MySQLDb.OperationalError,error: [中国站长站]
print "Connect MySQL[%s %s/%s %s] DB Error:"%(db_host,db_user,db_user_passwd,db_name),error,"\n"
Chinaz_com
sys.exit(1)
中国.站长站
else:
中国站长_站,为中文网站提供动力
c = mdb.cursor() 中国.站.长站
table,autocommit,trans = test
Chinaz~com
starttime = time.time() Chinaz~com
print table," ",time.strftime("%y-%m-%d %H:%M:%S",time.localtime())
中.国站长站
if autocommit != None: Chinaz_com
AutoCommit(autocommit)
中国站.长.站
if trans == 1: 中.国站长站
BeginTrans() Www^Chinaz^com
for i in xrange(testcount):
Www.Chinaz.com
tablestring = "%020d"%i 中国站.长.站
if (AddTable(table,tableid,tablestring)<1): Www.Chinaz.com
print "AddTable Error",tablestring
中国.站长站
if trans == 1: 中.国.站.长.站
Commit() Www@Chinaz@com
print time.strftime("%y-%m-%d %H:%M:%S",time.localtime())
中国站长.站
endtime = time.time() Chinaz@com
usedtime = endtime-starttime Www_Chinaz_com
print table,"count:",getcount(table)," used time:",usedtime
Chinaz^com
c.close() Chinaz
mdb.close()
Www_Chinaz_com
if __name__ == ‘__main__’:
中国站.长站
main()
Chinaz_com
测试结果如下: 中国站.长站
Config:[localhost root/ demo] DB Www@Chinaz@com
MyISAM_NT 04-10-22 16:33:24
Www@Chinaz@com
04-10-22 16:33:26 站.长.站
MyISAM_NT count: 10000 used time: 2.1132440567
Chinaz
MyISAM_TS 04-10-22 16:33:26 Chinaz^com
ExecSQL:BEGIN; Www_Chinaz_com
ExecSQL:COMMIT;
中.国.站.长.站
04-10-22 16:33:29 Chinaz~com
MyISAM_TS count: 10000 used time: 2.65475201607
Chinaz~com
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 Www.Chinaz.com
ExecSQL:Set AUTOCOMMIT = 0
中国站.长.站
ExecSQL:BEGIN; 中国站.长站
ExecSQL:COMMIT;
Www^Chinaz^com
04-10-22 16:33:35 Chinaz^com
INNODB_NA_BE count: 10000 used time: 3.85625100136
Www~Chinaz~com
INNODB_AU_NB 04-10-22 16:33:35
中国站长.站
ExecSQL:Set AUTOCOMMIT = 1
Www~Chinaz~com
04-10-22 16:34:19 Chinaz~com
INNODB_AU_NB count: 10000 used time: 43.7153041363
Www_Chinaz_com
INNODB_AU_BE 04-10-22 16:34:19 中国站长.站
ExecSQL:Set AUTOCOMMIT = 1 Www_Chinaz_com
ExecSQL:BEGIN;
Www_Chinaz_com
ExecSQL:COMMIT; Www~Chinaz~com
04-10-22 16:34:22 Www.Chinaz.com
INNODB_AU_BE count: 10000 used time: 3.14328193665
中.国站长站
中.国站长站
结论: 中国站长_站,为中文网站提供动力
由此得知影响速度的主要原因是AUTOCOMMIT默认设置是打开的,
Chinaz_com
我当时的程序没有显式调用BEGIN;开始事务,导致每插入一条都自动Commit,严重影响了速度。
站长.站
算来也是个低级错误! 站.长站
相关参考: 中国站.长站
http://dev.mysql.com/doc/MySQL/en/COMMIT.html 中国站.长站
http://dev.mysql.com/doc/MySQL/en/InnoDB_and_AUTOCOMMIT.html Www@Chinaz@com