使用随机PRIMARY KEY列的值缓慢插入InnoDB表

时间:2011-10-25 22:13:51

标签: mysql primary-key innodb flickr

对于我的网站,我使用PHP API for Flickr(http://www.flickr.com/services/api/)。此API提供了几种有用的方法来获取特定GPS位置周围的照片。

对API方法的调用看起来像URL,其中包含纬度,经度,API密钥,半径,排序等特定参数。比如说,它看起来像http://api.flickr.com/method?lat=0.0&lon=0.0&radius=10

我的网站对API进行了超过200,000次调用,以生成包含Flickr图片的多个页面。这是对API的极大推动,因此我在mySQL数据库中创建了一个结果缓存。

带缓存的InnoDB表的简化方案是:

char(32) request
datetime expires // 2-3 days
text     response // serialized data from API response

其中request是PRIMARY KEY,表示请求URI的MD5哈希值。其他领域非常简单:)

当表变得足够大时,例如超过100,000行,就会出现问题。新INSERTs最多需要2秒(最多6(!)秒,1,000,000行)。

据我所知,问题在于PRIMARY INDEX和引擎是InnoDB。每次插入新请求时,InnoDB引擎都会重建树索引并移动数据,因为MD5(请求)是一个非常随机的值。

所以......问题是是否有更好的方法来缓存此类请求?或许我应该切换到MyISAM引擎?或者可能是我应该尝试伪分区并创建几个表来解决问题?或者可能只是使用BTREE而不是HASH索引?

欢迎任何想法!

修改

好吧,我试图改变桌子,因为Furicane和Johan建议,但仍然没有运气 - INSERT需要3秒钟。当前request字段成为正常的非唯一索引,并且新id列已添加为具有自动增量的PRIMARY KEY。此外,我尝试在此表上添加4个分区,结果相同。

我认为request字段上的索引仍然是瓶颈。我目前看到的唯一方法是确定所有可能的参数,将它们作为列添加到表中,然后在它们上创建索引。

还有其他想法吗? :)

编辑2:

Salman A在下面的评论中说他的相似表表现得更好(插入时约为0.03)。这个问题可能出在系统上的IO负载上。虽然我不能承受任何高负荷。

iostat结果:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          22.94    0.71    8.42    8.50    0.00   59.43

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda              38.01       151.04       114.32 1383655437 1047309046

iotop结果:

Total DISK READ: 152.91 K/s | Total DISK WRITE: 197.67 K/s

将mySQL放在列表的顶部,用于写入和阅读。也许我的磁盘几乎死了?如何检查磁盘性能?

1 个答案:

答案 0 :(得分:3)

InnoDB不支持hash个密钥,只支持Btree。

MyISAM因不可靠而臭名昭着 我认为您的问题是您使用MD5值作为主键。

主键包含在每个辅助键中。 PK被迫成为一把独特的钥匙。

设置整数自动增量主键并将MD5值设置为普通索引 它甚至不需要是唯一的,因为这是减缓你速度的重要因素。

在此之后,您的插入应该运行得更快。