在使用索引的时候,我们同样需要考虑代价,但是不用为代价感到恐惧,我们只需要思考是否值得。
首先,索引会占据更多的磁盘空间,很多时候索引甚至比数据本身还要大,比如将拥有100万行记录的表转为MyISAM类型后,可以看到索引文件(MYI 文件)的大小几乎是数据文件(MYD 文件)的两倍。
我们来创建这样一个数据表:
CREATE TABLE `key_t` ( `id` int(11) NOT NULL, `key1` int(11) NOT NULL DEFAULT '0', `key2` int(11) NOT NULL DEFAULT '0', `key3` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `normal_key` (`key1`,`key2`,`key3`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
这个数据表建立了一个包含了三个字段的组合索引 normal_key,同时它还有一个自增类型的主键。我们为这个表填充了 100 万行的记录,其中 key1、key2、key3的内容均为0到999的随机整数。
先如今,存储空间比计算时间要廉价得多,TB 级别的高速磁盘任你选择,而且大多数情况下在磁盘空间写满之前,计算能力的瓶颈早已迫使数据库进行扩展,所以你几乎不用担心索引空间的增长,从这一点上看,牺牲空间换取时间是值得的。
其次,当建立索引的字段发生更新时,会引发索引本身的更新,这将产生不小的计算开销。一个简单的测试,上面建立的 key_t 表,在不使用组合索引和使用组合索引两种情况下测试插入数据的性能,结果如下表所示:
可以看到有接近一倍的差距。同样,对于 update、delete 等查询,一旦涉及索引字段的变更,也会引发索引计算,导致更多的时间开销。
是否使用索引取决于站点的应用和你的权衡,mysqlreport 中有一部分数据统计给你提供参考:
通过它,我们了解了站点中各种类型查询数量的比例,比如上面告诉我们在所有 DMS 查询中,select 占据了 85.56%,而 update 和 delete 加起来一共不到15%,牺牲更新时间换取读取时间是值得的。