1、is null可以使用索引(网上很多文章存在误导,这个确实可以使用索引),is not null无法使用索引。
2、为什么重复数据较多的列不适合使用索引?
假如索引列TYPE有5个键值,如果有1万条数据,那么 WHERE TYPE = 1将访问表中的2000个数据块。
再加上访问索引块,一共要访问大于2000个的数据块。
如果全表扫描,假设10条数据一个数据块,那么只需访问1000个数据块,既然全表扫描访问的数据块少一些,肯定就不会利用索引了。
3、MySQL主要提供2种方式的索引:B-Tree索引,Hash索引
B树索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN)。相当于二分查找。
哈希索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1)。
显然,如果值的差异性大,并且以等值查找(=、 <、>、in)为主,Hash索引是更高效的选择,它有O(1)的查找复杂度。
如果值的差异性相对较差,并且以范围查找为主,B树是更好的选择,它支持范围查找。
BTree详细介绍:https://www.cnblogs.com/coder2012/p/5309197.html
4、字段类型和传入类型不一致会导致索引失效,例如name=9999,应该写成name='9999'
5、哈希索引只保存哈希值和行指针不保存数据,因此无法使用哈希索引来避免读取行
6、哈希索引不是按照索引值顺序存储的,所以无法用于排序。哈希索引只支持等值比较(如:=,in(),<=>),不支持大于,小于等比较
7、在索引的分类中,我们可以按照索引的键是否为主键来分为“主索引”和“辅助索引”,使用主键键值建立的索引称为“主索引”,其它的称为“辅助索引”。因此主索引只能有一个,辅助索引可以有很多个
8、使用mysql内部函数导致索引失效.对于这样情况应当创建基于函数的索引.
错误的例子:select * from test where round(id)=10;
说明,此时id的索引已经不起作用了 正确的例子:首先建立函数索引,
create index test_id_fbi_idx on test(round(id));
然后 select * from test where round(id)=10; 这时函数索引起作用了
9、不使用NOT IN和<>操作
NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可使用id>3 or id<3来代替。
10、如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的
11、复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
12、 SHOW SESSION STATUS LIKE 'Handler_read%'; 可以查看索引使用情况。详情点击这里
13、执行计划EXPLAIN中type表示MySQL在表中找到所需行的方式,又称“访问类型”
ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从最差到最好)
- ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
- index:Full Index Scan,index与ALL区别为index类型只遍历索引树
- range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行。显而易见的索引范围扫描是带有between或者where子句里带有<, >查询。当mysql使用索引去查找一系列值时,例如IN()和OR列表,也会显示range(范围扫描),当然性能上面是有差异的。
- ref:使用非唯一索引扫描或者唯一索引的前缀扫描,返回匹配某个单独值的记录行
- eq_ref:类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
- const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量
- NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。