索引优化

10 分钟阅读 1358 字 + 1155 词
十一、索引优化
sql
1.不在索引列上做任何操作(计算,函数等等),会导致索引失效
2.慎用不等于号,会使索引失效
3.存储引擎不能使用索引中范围条件右边的列
4. 只访问索引的查询:索引列和查询列一致,尽量用覆盖索引,减少select *
5. NULL/NOT NULL的可能影响:c1允许为空,作为where的查询条件不会使索引失效;c2不允许为空,c2 is null  is not null都不会用到索引
6. 字符串类型加引号,不加引号会索引失效
7. UNION的效率比or更好
8.like查询要当心,就是是否满足最左前缀
应该创建索引的情况:
频繁作为查询条件的字段应该创建索引 与其他表关联的字段应该创建索引 经常用于排序和分段的字段
不应该创建索引的情况:
​ 数据量太少 ​ 经常更新的表 ​ 数据字段中包含太多的重复值
mysql
insert into student values (6, '19',34, '19', '19', '19', '2015-02-12 10:10:00');

show create table student;
#索引优化
#1、不在索引列上做任何操作(计算,函数等等),会导致索引失效
explain select * from student where id = 3;
explain select * from student where id + 1 = 4;

#2、慎用不等于号,会使索引失效
show create table student;
explain select * from student where c1 =  'wuhan';
explain select * from student where c1 <> 'wuhan';
explain select c1 from student where c1 <> 'wuhan';
explain select c1,c2 from student where c1 <> 'wuhan';

explain select * from student where c1 > 'wuhan' or c1 < 'wuhan';
explain select c1 from student where c1 > 'wuhan' or c1 < 'wuhan';
#下面这条会使用index
explain select c1 from student where c1 > 'wuhan' UNION 
 select c1 from student where c1 < 'wuhan';

#3、存储引擎不能使用索引中范围条件右边的列
explain  select * from student where c1 = 'wuhan' and c2 > 'c' and c3 = 'wangdao';
explain  select * from student where c1 = 'wuhan' and c2 like 'c%' and c3 = 'wangdao';

#4. 只访问索引的查询:索引列和查询列一致,尽量用覆盖索引,减少select *
explain  select c1,c2 from student where c1 = 'wuhan';
explain  select * from student where c1 = 'wuhan';
explain  select c1,c2 from student where c2 ='wuhan'; 

#5. NULL/NOT NULL的可能影响


#6. 字符串类型加引号,不加引号会索引失效
explain  select * from student where c1 = '19';
explain  select * from student where c1 = 19;

#7. UNION的效率比or更好
explain select * from student where c1 = '19';
explain select * from student where c1 = 'wuhan';
explain select * from student where c1 = '19' or c1 = 'wuhan';
explain select * from student where c1 = '19' union select * from student where c1 = 'wuhan';
优化索引的方法:
  1. ==前缀索引优化==
    1. 使用前缀索引是为了减小索引字段大小 ,可以增加一个索引页中存储的索引值, 有效提高索引的查询速度 。在一些大字符串的字段作为索引时, 使用前缀索引可以帮助我们减小索引项的大小
    2. 不过前缀索引有一定的局限性,例如: order by就无法使用前缀索引 ;无法把前缀索引用作覆盖索引
  2. ==覆盖索引优化==
    1. 利用覆盖索引可以避免回表的操作 ,建立一个联合索引与主键和所需要的列。
  3. ==主键索引最好是自增的==
    1. InnoDB 创建主键索引默认为聚簇索引 数据被存放在了 B+Tree 的叶子节点上 。也就是说,同一个叶子节点内的各个数据是按主键顺序存放的,因此,每当有一条新的数据插入时,数据库会根据主键将其插入到对应的叶子节点中。
    2. 如果我们使用自增主键 ,那么每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有的数据,当页面写满,就会自动开辟一个新页面。 因为每次插入一条新记录,都是追加操作,不需要重新移动数据 ,因此这种插入数据的方法效率非常高。
    3. 如果我们使用非自增主键,由于每次插入主键的索引值都是随机的,因此每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这将不得不移动其它数据来满足新数据的插入,甚至需要从一个页面复制数据到另外一个页面,我们通常将这种情况称为 页分裂 页分裂还有可能会造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率
    4. 另外,主键字段的长度不要太大,== 因为主键字段长度越小,意味着二级索引的叶子节点越小 ==(二级索引的叶子节点存放的数据是主键值),这样二级索引占用的空间也就越小
  4. ==索引最好是NOT NULL==
    1. 第一原因:== 索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化 ==,因为可为 NULL 的列会使索引、索引统计和值比较都更复杂,比如进行索引统计时,count 会省略值为NULL 的行。
    2. 第二个原因:NULL 值是一个没意义的值, 但是它会占用物理空间,所以会带来的存储空间的问题 ,因为 InnoDB 存储记录的时候,如果表中存在允许为 NULL 的字段,那么行格式中至少会用1字节空间来存储NULL值列表。
  5. ==防止索引失效==
    1. 不在 索引列上做任何计算或者函数操作 ,会导致索引失效
    2. 慎用不等于号 ,会使索引失效
    3. 存储引擎 不能使用索引中范围条件>或者<右边的列
    4. 只访问索引的查询: 索引列和查询列一致,尽量用覆盖索引,减少select
    5. NULL/NOT NULL的可能影响:c1允许为空,作为where的查询条件不会使索引失效;c2不允许为空,c2 is null is not null都不会用到索引
    6. 字符串类型加引号,不加引号会索引失效
    7. UNION的效率比or更好
    8. like查询要当心,就是是 否满足最左前缀
    9. 在where子句中, 如果在or前的条件列是索引列,而在or后的条件列不是索引列,那么索引会失效。
    10. 注意避免使用Using filesort,当查询语句中包含group by 操作,而且无法利用索引完成排序操作的时候,就需要利用相应的排序算法了。甚至会文件排序