文章目录
- 从一个示例开始
- 离散性
- 联合索引
- 最左匹配原则
- 三星索引(索引设计尽量遵循该原则)
从一个示例开始
例如,此处有一个User
表,表的字段及类型如下表所示:
字段 | 类型 |
id | int |
name | varchar(32) |
age | int |
gender | tinyint |
mobile | varchar(20) |
假设创建单列索引,以哪列作为索引比较合适?
离散性
count distinct col :count col
即当前列去除重复的数据的个数:当前列的总数,该值越大代表离散性越好。
举个例子,如果在gender列上面创建索引,由于gender性别只有男和女两种,例如这里1表示男2表示女,那么即使创建了索引,它也会走全表扫描:
也就是说,此处选择姓名创建索引是最好的选择(离散性的比值为1:10已经是一个比较好的索引了 )。
联合索引
如果有一个联合索引(name,mobile,age)
,可以理解为创建了三个索引即(name)
、(name,mobile)
、(name,mobile,age)
。
最左匹配原则
对于mysql来说,建立的复合索引是通过从左到右的顺序去建立搜索树的。那么去检索时,例如查询条件为name=‘Young’ and mobile=‘155555’,age=‘26’,则会先优先比较name去确定下一步的搜索因子,此处因为查询了手机号码,索引会比较下一个搜索因子手机号码,然后是age这个搜索因子,最后得到数据返回。举一反三,若查询语句中没有name,则这次查询不会走索引; 如果使用name和age进行查询,则由于缺失了mobile这个因子导致name走索引,而age条件查询需要一一进行比较。
例如上表创建联合索引:(name,mobile,age)
(1)select * from user where name = ‘Young’ and mobile like ‘155%’ and age=26; (2列用到索引)
(2)select * from user where age=26 and name = ‘Young’;(1列用到索引)
答案是4。
由上篇文章可知,所有的非主键索引都是稀疏索引,第四条查询会先联合索引name,phoneNum取到的name,phoneNum和id的值,不需要再次遍历主键的索引树,效率最高。(也叫覆盖索引)
三星索引(索引设计尽量遵循该原则)
第一颗:where后面匹配的索引关键字列越多越好,扫描的数据越精确,越少越好。–通过索引筛选出的数据越少越好(列的离散性)
第二颗:避免再次排序(例如上篇文章讲到的id自增天然有序,则使用order by的时候无需在内存中进行二次排序)
第三颗:尽可能的应用覆盖索引,减少回表操作。