在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为<b><font color="#c41230">MySQL的B-Tree只对<,<=,=,>,>=,BETWEEN,IN,以及不以通配符开始的LIKE才会使用索引。</font></b>
一些技巧和注意事项
<b><font color="#c41230">索引字段尽量使用数字型(简单的数据类型)</font></b>
若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。<b><font color="#0076b3">这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了</font></b>
<b style=""><font color="#c41230">尽量不要让字段的默认值为NULL</font></b>
<b><font color="#0076b3">索引不会包含有NULL值的列,只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。<br><br>所以我们在数据库设计时尽量不要让字段的默认值为NULL,应该指定列为NOT NULL,除非你想存储NULL。你应该用0、一个特殊的值或者一个空串代替空值。</font></b>
<b><font color="#c41230">前缀索引和索引选择性</font></b>
<b><font color="#c41230">对字符串列进行索引,如果可能应该指定一个前缀长度。</font></b>
对于<b><font color="#c41230">BLOB、TEXT或者很长的VARCHAR类型的列</font></b>,必须使用前缀索引,因为MYSQL不允许索引这些列的完整长度。
前缀索引是一种能使索引更小、更快的有效办法,但另一方面也有其缺点:<b><font color="#c41230">MySQL无法使用前缀索引做order by和group by,也无法使用前缀索引做覆盖扫描。</font></b>
短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。在绝大多数应用里,数据库中的字符串数据大都以各种各样的名字为主,把索引的长度设置为10~15个字符已经足以把搜索范围缩小到很少的几条数据记录了。<br><br>通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。但这样也会降低索引的选择性。
<b><font color="#c41230">索引的选择性是指,不重复的索引值(基数)和数据表中的记录总数的比值。</font></b>
索引的选择性越高则查询效率越高,因为选择性高的索引可以让MYSQL在查找时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
也就是识别度
<b><font color="#c41230">使用唯一索引</font></b>
索引的选择性/识别度越高越好
<b><font color="#c41230">使用组合索引代替多个列索引</font></b>
<b><font color="#c41230">注意重复/冗余的索引、不使用的索引</font></b>
识别度不高的索引,或者重复/冗余的索引,可以删除
<b><font color="#c41230">对大的文本进行搜索,使用全文索引而不要用使用 like ‘%…%’</font></b>
innodb不支持全文索引,建议走es
<b><font color="#c41230">like语句不要以通配符开头</font></b>
<b><font color="#c41230">不要在列上进行运算</font></b>
<b><font color="#c41230">索引列不能是表达式的一部分,也不是是函数的参数。</font></b>
例如以下两个查询无法使用索引:
1)表达式: select actor_id from sakila.actor where actor_id+1=5;
2)函数参数:select ... where TO_DAYS(CURRENT_DATE) - TO_DAYS(date_col)<=10;<br>
<b><font color="#c41230">尽量不要使用NOT IN、<>、!= 操作</font></b>
<b><font color="#c41230">or条件</font></b>
用 or 分割开的条件, 如果 or 前的条件中的列有索引, 而后面的列中没有索引, 那么涉及到的索引都不会被用到<br><br>应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20 可以这样查询: select id from t where num=10 union all select id from t where num=20
<b><font color="#c41230">组合索引的使用要遵守“最左前缀”原则'</font></b>
<b><font color="#c41230">将选择性/识别度最高的列放在前面</font></b>
<b><font color="#0076b3">1. 查询必须从索引的最左边的列开始,否则无法使用索引。例如,你不能直接利用索引查找在某一天出生的人。</font></b>
<b><font color="#0076b3">2. 不能跳过某一索引列</font></b>
<b><font color="#0076b3">3. 存储引擎不能使用索引中范围条件右边的列。</font></b>例如,如果你的查询语句为WHERE last_name="Smith" AND first_name LIKE 'J%' AND dob='1976-12-23',则该查询只会使用索引中的前两列,因为LIKE是范围查询。
<b><font color="#c41230">使用索引排序时,ORDER BY也要遵守“最左前缀”原则</font></b>
<b><font color="#0076b3">1. 当索引的顺序与ORDER BY中的列顺序相同,且所有的列是同一方向(全部升序或者全部降序)时,可以使用索引来排序。</font></b>
<b><font color="#0076b3">2. ORDER BY子句和查询型子句的限制是一样的:需要满足索引的最左前缀的要求,有一种情况下ORDER BY子句可以不满足索引的最左前缀要求,那就是前导列为常量时:WHERE子句或者JOIN子句中对前导列指定了常量。</font></b>
<b><font color="#0076b3">3. 如果查询是连接多个表,仅当ORDER BY中的所有列都是第一个表的列时才会使用索引。其它情况都会使用filesort文件排序。</font></b>
<b><font color="#0076b3">4. 如果列类型是字符串,那么一定记得在 where 条件中把字符常量值用引号引起来,否则的话即便这个列上有索引,MySQL 也不会用到的,因为MySQL 默认把输入的常量值进行转换以后才进行检索。</font></b>
<b><font color="#c41230">任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段</font></b>
<b><font color="#c41230">如果 MySQL 估计使用索引比全表扫描更慢,则不使用索引。当索引列有大量数据重复时,查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。</font></b>