[英]Slow INSERT into InnoDB table with random PRIMARY KEY column's value
对于我的网站,我使用Flickr的PHP API( 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放在列表的顶部,用于写入和阅读。 也许我的磁盘几乎死了? 如何检查磁盘性能?
InnoDB不支持hash
键,只支持Btree。
MyISAM因不可靠而臭名昭着。
我认为您的问题是您使用MD5值作为主键。
主键包含在每个辅助密钥中。 PK被迫成为一把独特的钥匙。
设置整数自动增量主键并将MD5值设置为普通索引。
它甚至不需要是唯一的,因为这是减缓你速度的重要因素。
在此之后,您的插入应该运行得更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.