我有一个表,主键设置为VARCHAR(14)
。
当我获得大量访问者时,服务器的I / O速率变得疯狂,当使用iotop
时,我可以看到mysql是问题。
对于使用模式,对于每次访问,脚本将通过varchar键select
单行。没有联接或任何其他复杂查询。
这是由VARCHAR键引起的疯狂I / O速率吗?我应该将其更改为INT(11)
吗?
谢谢,
编辑:此图片可能有所帮助:http://i.imgur.com/TL5sY.png
答案 0 :(得分:1)
在InnoDB中,表中的数据按照与主键相同的顺序在磁盘上排序(它集中在主键上)。由于varchar键不是顺序的,这意味着您的插入也不是顺序的,这会导致随机写入,这是繁重的I / O操作。因此,首先检查高I / O是否不是由写入引起的,而不是读取引起的。虽然读取也会导致高I / O - 如果ID是唯一的字符串,MySQL很难在缓冲池中正确加载正确的ID子集(因为它总是加载整个页面而不是单个记录),并且如果缓冲池很小,它必须为每个请求虚拟地在缓冲池中加载一个新页面,这意味着它必须刷新脏页等,这实际上会导致对I / O子系统的读写加载。因此,如果您无法更改主键的类型,请检查您的innodb_buffer_pool_size。
如果您需要进一步的帮助,请发布innodb_buffer_pool_size值,以及表的确切结构,以GB为单位的大小/记录数以及与表一起使用的查询。
答案 1 :(得分:0)
即使您将PK列更改为自动增量INT
,假设您的VARCHAR
列包含字符数据,您仍需要访问其索引以选择行,不是吗?创建INT
PK列没有任何好处。
另一方面,如果您的PK列包含VARCHAR
列中的整数数据,则应将其绝对更改为INT
答案 2 :(得分:0)
将密钥保留为逻辑密钥 - 然后使用INT(?)作为物理密钥。物理密钥应随机分布,因此死锁的风险会降低。设计数据库应该在盛大开放之前包括这些经典分析 - 一旦你启动并运行,这就成了一个压力很大的问题。 正如mkk建议的那样 - 索引可以被强调,但群集中的数据是真正的问题。索引往往在内存中。 当I / O每秒/秒足够高时,我总是在执行物理键时使用时间戳反转 - 以便将它们传播到群集中。
答案 3 :(得分:0)
你在做这样的事情:
SELECT *
FROM table
WHERE varchar_key = 467487644;
如果是这样,mysql将尝试在比较之前将每行中varchar_key的值转换为整数。它每次都会进行全表扫描。
更改为:
SELECT *
FROM table
WHERE varchar_key = '467487644';
将防止这种情况发生,并且主密钥将被正确使用。
你应该检查EXPLAIN输出,如果你只是通过主键在一个表中查找一行,则解释输出应该在“key”列中具有“PRIMARY”,并且“rows”应该是1。否则,有些事情是不对的。