有几个Q& A用于"为什么InnoDB(很多)比MyISAM"慢,但我找不到相反的主题。
所以我有一个表定义为InnoDB wherin我将文件内容存储在blob字段中。因为通常应该使用MyISAM我切换了那张桌子。这是它的结构:
CREATE TABLE `liv_fx_files_files` (
`fid` int(11) NOT NULL AUTO_INCREMENT,
`filedata` longblob NOT NULL,
`filetype` varchar(255) NOT NULL,
`filename` varchar(255) NOT NULL,
`filesize` int(11) NOT NULL,
`context` varchar(1) NOT NULL DEFAULT '',
`saveuser` varchar(32) NOT NULL,
`savetime` int(11) NOT NULL,
`_state` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`fid`),
KEY `_state` (`_state`)
) ENGINE=MyISAM AUTO_INCREMENT=4550 DEFAULT CHARSET=utf8;
目前已存储4549条记录(filedata
从0到48M。所有文件的总和约为6G。
因此,每当我需要知道当前的总文件大小时,我都会发出查询
SELECT SUM(filesize) FROM liv_fx_files_files;
问题在于,由于我从InnoDB切换到MyISAM,这个简单的查询持续时间很长(大约30秒或更长),而在InnoDB上,它在不到一秒的时间内完成。
但聚合不是唯一非常慢的查询;它几乎是每个查询。
我想我可以通过采用配置(目前针对InnoDB(仅限)使用优化)来修复它,但不知道要调整哪些设置。请问有人暗示我吗?
current mysql server config (SHOW VARIABLES
as csv)
针对两种表类型触发的另一个查询的示例(两者都包含完全相同的数据并具有相同的定义)。所有其他测试的查询行为相同,比如对InnoDB的MyISAM表运行时间更长!
SELECT sql_no_cache `fxfilefile`.`filename` AS `filename` FROM `myisamtable`|`innodbtable` AS `fxfilefile` WHERE `fxfilefile`.`filename` LIKE '%foo%';
答案 0 :(得分:2)
执行摘要:使用InnoDB,并相应地更改my.cnf设置。
详细说明:
“MyISAM更快” - 这是一个老妻子的故事。今天,InnoDB在大多数情况下更快。
假设你有至少4GB的RAM ......
key_buffer_size
应该占RAM的20%左右; innodb_buffer_pool_size
应为0。key_buffer_size
应该只有20MB; innodb_buffer_pool_size
应占RAM的70%左右。让我们来看看两个引擎如何以不同的方式处理事情。
结论:
MyISAM表中的表扫描花了很多时间踩过奶牛垫; 如果你没有碰到BLOB
,那么InnoDB要快得多
当SELECT SUM(x) FROM tbl;
上没有索引时,这使得InnoDB成为x
的明显赢家。使用INDEX(x)
,任何引擎都会很快。
由于BLOB是内联的,如果更新表中的记录,MyISAM会出现碎片问题; InnoDB的碎片少得多。这会影响所有操作,使InnoDB再次成为赢家。
CREATE TABLE
中列的顺序对任一引擎的性能都没有影响。
因为BLOB占据了每行的大小,对其他列的调整对性能的影响非常小。
如果您决定使用MyISAM,我会建议使用“并行”表(“垂直分区”)。将BLOB和id放在一个单独的表中。这将有助于MyISAM更接近InnoDB的模型和性能,但会增加代码的复杂性。
对于“点查询”(通过索引查找单行),引擎之间的性能差异不会很大。
你的my.cnf
似乎是古董; <{1}}在很长一段时间内都没有必要。
答案 1 :(得分:0)
尝试编辑你的MySQL配置文件,通常是/etc/mysql/my.cnf并使用“巨大的”预设。
# The MySQL server
[mysqld]
port = 3306
socket = /var/run/mysqld/mysqld.sock
skip-locking
set-variable = key_buffer=384M
set-variable = max_allowed_packet=1M
set-variable = table_cache=512
set-variable = sort_buffer=2M
set-variable = record_buffer=2M
set-variable = thread_cache=8
# Try number of CPU's*2 for thread_concurrency
set-variable = thread_concurrency=8
set-variable = myisam_sort_buffer_size=64M
答案 2 :(得分:0)
读取4500条记录肯定是30秒非常慢。假设有足够的空间进行I / O缓存,那么我要尝试的第一件事就是改变字段的顺序;如果这些按照它们被声明的顺序写入表中,则DBMS在读取大小值之前需要寻找到每个记录的末尾(我还建议限制那些vharchar(255)列的大小,并且那个varhar(1)NOT NULL应该是CHAR)。
CREATE TABLE `liv_fx_files_files2` (
`fid` int(11) NOT NULL AUTO_INCREMENT,
`filesize` int(11) NOT NULL,
`context` char(1) NOT NULL DEFAULT '',
`saveuser` varchar(32) NOT NULL,
`savetime` int(11) NOT NULL,
`_state` int(11) NOT NULL DEFAULT '0',
`filetype` varchar(255) NOT NULL,
`filename` varchar(255) NOT NULL,
`filedata` longblob NOT NULL,
PRIMARY KEY (`fid`),
KEY `_state` (`_state`)
) ENGINE=MyISAM AUTO_INCREMENT=4550 DEFAULT CHARSET=utf8;
INSERT INTO liv_fx_files_files2
(fid, filesize, context, saveuser, savetime, _state, filetype, filename, filedata)
SELECT fid, filesize, context, saveuser, savetime, _state, filetype, filename, filedata
FROM liv_fx_files_files;
但理想情况下,我会将数据和元数据拆分为单独的表格。