【发布时间】:2012-02-25 05:14:34
【问题描述】:
我最近将我的项目表切换到 InnoDB(认为关系将是一件好事)。我正在使用 PHP 脚本一次索引大约 500 个产品。
存储单词/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/word 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 对来填充一个数组。
因为每当我执行因重复值而失败的“REPLACE INTO”或“INSERT IGNORE INTO”时,innodb 都会不断增加我的自动增量值,所以我需要确保我添加的值不存在。为此,我首先使用如下查询选择所有存在的值:
SELECT wid,word
FROM windex
WHERE
word = "someword1" or word = "someword2" or word = "someword3" ... ...
然后我根据现有结果过滤掉我的数组,这样我添加的所有新词都是 100% 新的。
这需要大约 20% 的总执行时间。另外 80% 用于将对值添加到 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 秒)。
添加 3435 个 pid/wid 对的索引需要 17.2725 秒。 (总共 25.7752 秒)。
索引 500 个产品的操作耗时 26.07 秒。
3435 对都在一个查询中执行,例如:
INSERT INTO indx_0(pid,wid)
VALUES (1,4),(3,9),(9,2)... ... ...
在我的情况下,为什么 InnoDB 比 MyISAM 慢这么多?
【问题讨论】:
-
单词索引的想法是创建某种搜索功能吗?如果是这种情况,请查看真正的搜索引擎,例如 solr 或 mysql 全文搜索。无法胜过此类特定任务。
标签: mysql performance innodb