mysql实战优化之四:mysql索引优化

0、 使用SQL提示

用户可以使用use index、ignore index、force index等SQL提示来进行选择SQL的执行计划。

1、支持多种过滤条件

2、避免多个范围条件

应尽量避免在 where 子句中使用!=或<>操作符,可以用in、between and代替,否则将引擎放弃使用索引而进行全表扫描。

3、优化排序

1,2,3详细见《mysql索引之十:Mysql 索引案例学习

4、如果需要在大字段上建立索引,可以考虑使用前缀索引

建立前缀索引的语法为:

ALTER TABLE table_name ADD KEY(column_name(prefix_length));

5、 重复索引、冗余索引

为了降低索引维护成本,禁止冗余索引,增大IO压力。(a,b,c)、(a,b),后者为冗余索引。可以利用前缀索引来达到加速目的,减轻维护负担。

详细见《mysql索引之九:重复索引和冗余索引,索引和锁

6、什么情况下应不建或少建索引

6.1、表记录太少

如果一个表只有5条记录,采用索引去访问记录的话,那首先需访问索引表,再通过索引表访问数据表,一般索引表与数据表不在同一个数据块,这种情况下ORACLE至少要往返读取数据块两次。而不用索引的情况下ORACLE会将所有的数据一次读出,处理速度显然会比用索引快。

如表zl_sybm(使用部门)一般只有几条记录,除了主关键字外对任何一个字段建索引都不会产生性能优化,实际上如果对这个表进行了统计分析后ORACLE也不会用你建的索引,而是自动执行全表访问。如:

select * from zl_sybm where sydw_bh=’5401’(对sydw_bh建立索引不会产生性能优化)

6.2、经常插入、删除、修改的表

对一些经常处理的业务表应在查询允许的情况下尽量减少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等业务表。

6.3、数据重复且分布平均的表字段

假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。

6.4、经常和主字段一块查询但主字段索引值比较多的表字段

如gc_dfss(电费实收)表经常按收费序号、户标识编号、抄表日期、电费发生年月、操作 标志来具体查询某一笔收款的情况,如果将所有的字段都建在一个索引里那将会增加数据的修改、插入、删除时间,从实际上分析一笔收款如果按收费序号索引就已 经将记录减少到只有几条,如果再按后面的几个字段索引查询将对性能不产生太大的影响。

7、null

应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

Sql 代码 : select id from t where num is null;

可以在 num 上设置默认值 0,确保表中 num 列没有 null 值,然后这样查询:

Sql 代码 : select id from t where num=0;

匹配某列的前缀字符串

8、where子句中OR来连接条件

应尽量避免在 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;

9、in 和 not in

in 和 not in 也要慎用,否则会导致全表扫描,如:

select id from t where num in(1,2,3);

对于连续的数值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3;

10、匹配某列的前缀字符串

如用%进行模糊查询是,下面的查询也将导致全表扫描:

select id from t where name like '%c%';

 若要提高效率,可以考虑全文检索。

11、where子句中使用参数

如果在 where 子句中使用参数,也会导致全表扫描。因为 SQL 只有在运行时才会解析局部变量,但优 化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计 划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num ;
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num ;

12、避免表达式运算

应尽量避免在 where 子句中对字段进行表达式操作, 这将导致引擎放弃使用索引而进行全表扫描。
select id from t where num/2=100;
可以这样查询:
select id from t where num=100*2;


13、避免对字段使用函数

应尽量避免在 where 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc';#name 以 abc 开头的 id
应改为:
select id from t where name like 'abc%';


14、尽可能的让字段顺序与索引顺序相一致

根据最左前缀原理,在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引, 否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

15、exists 代替 in

很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b);
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num);



原文地址:https://www.cnblogs.com/duanxz/p/5145824.html