特别注意:索引跟出参也有相关联系
索引注意:是否能使用索引,取决于mysql查询优化器对统计数据分析后,是否认为使用索引更快。因此,单纯的讨论一条sql是否可以使用索引有点片面,还需要考虑数据。
一个表最多可有16个索引。最大索引长度是256个字节,尽管这可以在编译MySQL时被改变;理想状态约 5个左右。
1、表的主键、外键必须有索引;
2、sql有个最左原则,字段离散率越高索引效率越好的原则(离散率低的都没有必要建索引)
3、经常与其他表进行连接的表,在连接字段上应该建立索引;
4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
5、索引应该建在选择性高的字段上;
6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:
如果使用联合索引,那么where条件也要尽量根据联合索引的顺序来
A、正确选择复合索引中的主列字段,一般是选择性较好的字段;
B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;
C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;
D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;
E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;
8、频繁进行数据操作的表,不要建立太多的索引;
9、删除无用的索引,避免对执行计划造成负面影响;
10、不要对数据库的字段进行函数处理 如:where comments= #{comments} 前面一个comments属于数据库字段 后面#{comments} 是可以用函数处理的,但是前面的comments 数据库的字段是不能被函数处理的,否则不会走索引。
11、 in索引在主键的时候也会走索引
12、sql语句在大于或者大于等于的时候会走索引,但是在小于或者小于等于的时候没有走索引
个人经验:内连接时外键设为索引时 则 主表索引级别 eq_ref 若在外键的表建立索引此索引会失效
所以 使用强制的主键索引 FORCE INDEX (PRI)
联表时子句适当先用子句过滤数据也会提升几十倍的速度
个人经验:左(右)连接 左表不走索引,但是如果在 GROUP BY pm.id(左表主键)
若不是主键强制索引 FORCE INDEX (PRI) 则左表的索引为 index 类型
若在where后跟上主键字段则两张表的索引类型都为const
1、为了解决上面(1)的问题,采用延迟索引。"延迟关联" :通过使用覆盖索引查询返回需要的主键,
再根据主键关联原表获得需要的数据。
通过延迟关联解决(1)无法使用覆盖索引的问题,使其能够使用覆盖索引。
explain select * from article join (select comments from
article where category_id=12) as t on t.comments=article.comments;
2、优化UNION查询。MySQL通过创建并填充临时表的方式来执行UNION查询,
因此需要手工的将where、limit、order by等子句“下推”到UNION的各个子查询中,
除非确实需要服务器消除重复的行,否则一定要使用UNION ALL,如果没有ALL关键字,
MySQL会给临时表加上distinct,从而对临时表的数据做唯一性检查,这样代价非常高。
3、优化关联查询,确保on或者using子句中的列上有索引。
确保group by和order by的表达式只涉及一个表中的列,
这样MySQL才有可能使用索引来优化整个过程。
4、优化group by和distinct。MySQL使用同样的方法优化这两类查询,
通常是利用索引的顺序性进行优化。但是如果无法使用索引,
group by使用两种策略来完成:使用临时表或者文件排序来做分组。
5、只有索引列顺序和order by子句的顺序完全一致,并且所有列的排序方向都一致时,MySQL才能使用索引来对结果做排序
6、使用索引覆盖扫描,把所有需要的列都放入索引,这样存储引擎无须回表获取对应行就可以返回结果;
7、优化MySQL的参数
通过优化MySQL的参数可以提高资源利用率,从而达到提高MySQL服务器性能的目的。如下是一些该方面参数的介绍。该参数的配置信息都在my.cnf或者my.ini文件中。
key_buffer_size:表示索引缓冲区的大小。所有线程共享缓冲区。增加索引缓冲区可以得到更好处理的索引。当然如果这个值太大,会导致操作系统频换换页,降低系统性能。
table_cache:表示同时打开表的个数,该值越大能够同时打开的表的个数越多。如果打开表的个数太多会影响操作系统的性能。
query_cache_size:查询缓冲区的大小。该值和query_cache_type配合使用。当query_cache_type=0,所有查询都不使用缓冲区,但是MySQL并不会释放query_cache_size所配置的缓冲区内存。当query_cache_type=1,所有查询使用缓冲区,除非在查询语句中指定SQL_NO_CACHE,如SELECT SQL_NO_CACHE * FROM table_name; 当query_cache_type=2,只有在查询语句中使用SQL_CACHE关键字,查询才会使用缓冲区。使用查询缓冲区可以提高查询速度,这种方式适用于修改操作少且经常执行相同的查询操作的情况。
innodb_buffer_pool_size:表示InnoDB类型的表和索引的最大缓存,该值越大查询速度就会越快。
max_connections:表示数据库的最大连接数。该值过大会浪费内存资源,严重可能会导致MySQL服务器僵死。
sort_buffer_size:表示每个需要排序线程分配的缓冲区的大小。该值越大排序的速度越快。增加该值可以提高ORDER BY或 GROUP BY操作的速度。默认值为2M。
8、使用索引合并的案例
https://blog.csdn.net/caomiao2006/article/details/52144964
explain select * from test where (key1_part1=4 and key1_part2=4) or key2_part1=4\G 只有and 和or 同时出现时才会走复合索引 但是具体要看mysql分析器
9、Innodb行锁优化建议
尽可能让所有的数据检索都通过索引来完成,从而避免Innodb因为无法通过索引键加锁而升级为表级锁定;
合理设计索引,让Innodb在索引键上面加锁尽可能准确,尽可能的缩小锁定范围,避免造成不必要的锁定而影响其他Query的执行;
尽可能减少基于范围的数据检索过滤条件,避免间隙锁带来的负面影响而锁定了不该锁定的记录;
尽量控制事务的大小,减少锁定的资源量和锁定时间长度;
在业务环境允许的情况下,尽量使用较低级别的事务隔离,以减少MySQL因为实现事务隔离级别所带来的附加成本;