对于我的网站,我使用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放在列表的顶部,用于写入和阅读。也许我的磁盘几乎死了?如何检查磁盘性能?
答案 0 :(得分:3)
InnoDB不支持hash
个密钥,只支持Btree。
MyISAM因不可靠而臭名昭着 我认为您的问题是您使用MD5值作为主键。
主键包含在每个辅助键中。 PK被迫成为一把独特的钥匙。
设置整数自动增量主键并将MD5值设置为普通索引 它甚至不需要是唯一的,因为这是减缓你速度的重要因素。
在此之后,您的插入应该运行得更快。