Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql InnoDB插入速度非常慢,速度也越来越慢_Mysql_Performance_Innodb - Fatal编程技术网

Mysql InnoDB插入速度非常慢,速度也越来越慢

Mysql InnoDB插入速度非常慢,速度也越来越慢,mysql,performance,innodb,Mysql,Performance,Innodb,最近,我将我的项目表切换到InnoDB(认为有这种关系是件好事)。我使用一个PHP脚本一次索引大约500个产品 存储word/ids关联的表: CREATE TABLE `windex` ( `word` varchar(64) NOT NULL, `wid` int(10) unsigned NOT NULL AUTO_INCREMENT, `count` int(11) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`wid`),

最近,我将我的项目表切换到InnoDB(认为有这种关系是件好事)。我使用一个PHP脚本一次索引大约500个产品

存储word/ids关联的表:

    CREATE TABLE `windex` (
 `word` varchar(64) NOT NULL,
 `wid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `count` int(11) unsigned NOT NULL DEFAULT '1',
 PRIMARY KEY (`wid`),
 UNIQUE KEY `word` (`word`)
) ENGINE=InnoDB AUTO_INCREMENT=324551 DEFAULT CHARSET=latin1
另一个表存储产品id/单词id关联:

CREATE TABLE `indx_0` (
 `wid` int(7) unsigned NOT NULL,
 `pid` int(7) unsigned NOT NULL,
 UNIQUE KEY `wid` (`wid`,`pid`),
 KEY `pid` (`pid`),
 CONSTRAINT `indx_0_ibfk_1` FOREIGN KEY (`wid`) REFERENCES `windex` (`wid`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `indx_0_ibfk_2` FOREIGN KEY (`pid`) REFERENCES `product` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
该脚本使用MyISAM进行了测试,它索引产品的速度相对较快(比InnoDB快得多)。第一次在InnoDB中运行时速度慢得离谱,但在将更多值嵌套在一起之后,我最终将速度提高了很多(但还不够)

我认为innodb在这种情况下会更快,因为有行级锁,但事实并非如此

我构造了一个如下所示的查询:

SELECT
title,keywords,upc,...
FROM product
WHERE indexed = 0
LIMIT 500
我创建一个循环并用需要添加到windex的所有单词和需要添加到indx_0的所有单词id/产品id对填充一个数组

因为每当我执行因重复值而失败的“替换到”或“插入忽略到”时,innodb会不断增加我的自动增量值,所以我需要确保我添加的值不存在。为此,我首先使用如下查询选择所有存在的值:

SELECT wid,word
FROM windex
WHERE
word = "someword1" or word = "someword2" or word = "someword3" ... ...
然后我根据已有的结果过滤掉我的数组,这样我添加的所有新词都是100%新的

这大约占整个执行时间的20%。另外80%用于将成对值添加到indx_0中,对于indx_0,还有更多的值

这是我得到的一个例子

0.4806秒选择产品。(总共0.4807秒)。
0.0319秒收集500个项目。(总共0.5126秒)。
5.2396秒,选择windex值进行比较。(总共5.7836秒)。
1.8986秒更新计数。(总共7.6822秒)。
0.0641秒添加832条windex记录。(总共7.7464秒)。
17.2725秒添加3435个pid/wid对的索引。(总共25.7752秒)。
操作耗时26.07秒,对500种产品进行了索引

3435对都在一个查询中执行,例如:

INSERT INTO indx_0(pid,wid)
VALUES (1,4),(3,9),(9,2)... ... ...

在我的例子中,为什么InnoDB比MyISAM慢得多?

InnoDB提供了比MyISAM更复杂的密钥结构(
外键),并且在InnoDB中重新生成密钥的速度非常慢。您应该将所有update/insert语句封装到一个事务中(在InnoDB中,这些语句实际上相当快,曾经我在InnoDB表上有大约30000个insert查询,其中包含2个索引,大约需要30分钟,曾经我将每10000个insert封装到
BEGIN TRANSACTION
COMMIT
中,不到2分钟)

我建议使用:

开始交易;
选择。。。从产品;
更新。。。;
插入。。。;
插入。。。;
插入。。。;
犯罪
这将导致InnoDB只刷新索引一次,而不是几百次


让我知道它是否有效

我也遇到了类似的问题,而且InnoDB似乎默认启用了InnoDB_flush_log_at_trx_commit,它会刷新硬盘日志文件上的每个插入/更新查询。硬盘的写入速度是此过程的瓶颈

因此,请尝试修改您的mysql配置文件

  `innodb_flush_log_at_trx_commit  = 0`
重新启动mysql服务


我在插入时体验了大约x100的加速。

单词索引的想法是为了创建某种搜索功能吗?如果是这样的话,那么看看真正的搜索引擎,比如solr或mysql全文搜索。我相信这肯定会带来一些进步。我也有类似的问题,维克托。看来这会管用的。谢谢-UdayI在一个光标中遇到了一个问题,这个问题已经解决了(从90秒到0.9秒!)慢慢地,我在学习需要什么InnoDB@Vyktor,关于“我在
开始事务
提交
中每插入10000次,所用时间不到2分钟”,为什么要分成10k批?为什么不在一个事务中包含所有语句?@Pacerier更容易恢复,一般来说,我尽量避免真正大的事务,这样我就不会在内部表锁上遇到麻烦了…@Vyktor,现在我不确定我是否理解您的意思,当我们正确执行批插入时,该事务肯定是唯一正在运行的。。。。。。另外,您所说的“更容易恢复”是什么意思?请注意,应用此选项会失去事务安全性。。。如果您在告诉客户机它已经完成之后,但在它真正写入磁盘之前,失去了电源,则意味着它将永远失去电源。