在大概了解了MySQL 各类类型的索引,以及索引自己的利弊与判断一个字段是否需要建立索引以后,就要着手建立索引来优化Query 了。在不少时候,WHERE 子句中的过滤条件并不仅是针对于单一的某个字段,常常会有多个字段一块儿做为查询过滤条件存在于 WHERE 子句中。在这种时候,就必需要判断是该仅仅为过滤性最好的字段创建索引,仍是该在全部字段(过滤条件中的)上创建一个组合索引。并发
对于这种问题,很难有一个绝对的定论,需要从多方面来分析考虑,平衡两种方案各自的优劣,而后选择一种最佳的方案。由于从上一节中已了解到索引在提 高某些查询的性能同时,也会让某些更新的效率降低。而组合索引中由于有多个字段存在,理论上被更新的可能性确定比单键索引要大不少,这样带来的附加成本也 就比单键索引要高。可是,当WHERE 子句中的查询条件含有多个字段时,经过这多个字段共同组成的组合索引的查询效率确定比只用过滤条件中的某一个字段建立的索引要高。由于经过单键索引过滤的 数据并不完整,和组合索引相比,存储引擎需要访问更多的记录数,天然就会访问更多的数据量,也就是说须要更高的 IO 成本。性能
可能有朋友会说,那能够建立多个单键索引啊。确实能够将 WHERE 子句中的每个字段都建立一个单键索引。可是这样真的有效吗?在这样的状况下,MySQL Query Optimizer 大多数时候都只会选择其中的一个索引,而后放弃其余的索引。即便他选择了同时利用两个或更多的索引经过 INDEX_MERGE 来优化查询,所收到的效果可能并不会比选择其中某一个单键索引更高效。由于若是选择经过 INDEX_MERGE 来优化查询,就需要访问多个索引,同时还要将几个索引进行 merge 操做,这带来的成本可能反而会比选择其中一个最有效的索引更高。优化
在通常的应用场景中,只要不是其中某个过滤字段在大多数场景下能过滤90%以上的数据,而其余的过滤字段会频繁的更新,通常更倾向于建立组合索引, 尤为是在并发量较高的场景下。由于当并发量较高的时候,即便只为每一个Query节省了不多的 IO 消耗,但由于执行量很是大,所节省的资源总量仍然是很是可观的。索引
固然,建立组合索引并非说就需要将查询条件中的全部字段都放在一个索引中,还应该尽可能让一个索引被多个 Query 语句利用,尽可能减小同一个表上的索引数量,减小由于数据更新带来的索引更新成本,同时还能够减小由于索引所消耗的存储空间。资源
此外,MySQL 还提供了另一个优化索引的功能,那就是前缀索引。在 MySQL 中,能够仅仅使用某个字段的前面部份内容作为索引键索引该字段,以达到减少索引占用的存储空间和提升索引访问效率的目的。固然,前缀索引的功能仅仅适用于 字段前缀随机重复性很小的字段。若是需要索引的字段前缀内容有较多的重复,索引的过滤性天然也会随之下降,经过索引所访问的数据量就会增长,这时候前缀索 引虽然可以减小存储空间消耗,可是可能会形成 Query 访问效率的极大下降,得不偿失。
class