mysql索引 sql优化

1.索引是什么?

MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,B+Tree索引,哈希索引,全文索引等等,这些索引的本质就是一种数据存储结构。

2.建立mysql索引的一些原则:

①.先存数据,再建索引,作为排序的列要建立索引。

②.不要对数据量小的数据表建立索引,数据量超过300的表应该有索引

③.对于规模小的数据表建立索引,不仅不会提高查询效率,相反使用索引查找可能比简单的全表扫描还 要慢,而且建索引还会占用一部分的存储空间

④.当对表的查询操作比更新操作频率更高时,对该表建立索引

⑤.在不同值较少的字段上不必要建立索引,如性别字段

⑥.对查询操作中使用频繁的字段建立索引

⑦.表的主键、外键必须有索引

⑧.经常出现在Where后面的字段,特别是大表的字段,应该建立索引

⑨.经常进行GROUP BY、ORDER BY的字段上建立索引

⑩.索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引

3.索引失效的情况:

①.在组合索引中不能有列的值为NULL,如果有,那么这一列对组合索引就是无效的。

②.在一个SELECT语句中,索引只能使用一次,如果在WHERE中使用了,那么在ORDER BY中就不要用了。

③.LIKE操作中,’%aaa%’ 以及 ‘%aaa’ 不会使用索引,也就是索引会失效,但是‘aaa%’可以使用索引。

④.在索引的列上使用表达式或者函数会使索引失效,
例如:select * from users where YEAR(adddate)<2007,
将在每个行上进行运算,这将导致索引失效而进行全表扫描,
因此我们可以改成:select * from users where adddate<’2007-01-01′。
其它通配符同样,也就是说,在查询条件中使用正则表达式时,只有在搜索模板的第一个字符不是通 配符的情况下才能使用索引。

⑤.在查询条件中使用不等于,包括<符号、>符号和!=会导致索引失效。特别的是如果对主键索引使用!=则不会使索引失效,如果对主键索引或者整数类型的索引使用<符号或者>符号不会使索引失效。(经erwkjrfhjwkdb同学提醒,不等于,包括<符号、>符号和!,如果占总记录的比例很小的话,也不会失效)

⑥.在查询条件中使用IS NULL或者IS NOT NULL会导致索引失效。

⑦.字符串不加单引号会导致索引失效。更准确的说是类型不一致会导致失效,比如字段email是字符串类型的,使用WHERE email=99999 则会导致失败,应该改为WHERE email=‘99999’。

⑧.在查询条件中使用OR连接多个条件会导致索引失效,除非OR链接的每个条件都加上索引,这时应该改为两次查询,然后用UNION ALL连接起来。

⑨.如果排序的字段使用了索引,那么select的字段也要是索引字段,否则索引失效。特别的是如果排序的是主键索引则select * 也不会导致索引失效。

⑩.尽量不要包括多列排序,如果一定要,最好为这队列构建组合索引;

4.避免全表扫描的方法:

①.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引

②.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,
如:select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0

③.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描

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

⑤.in 和 not in 也要慎用,否则会导致全表扫描,
如:select id from t where num in(1,2,3)
对于连续的数值,用 between替代:select id from t where num between 1 and 3

⑥.下面的查询也将导致全表扫描:select id from t where name like ‘%李’
若要提高效率,可以考虑全文检索。
ps: %在右侧不会导致全表扫描

⑦.避免在索引列上使用计算,也就是说,应尽量避免在 where 子句中对字段进行表达式操作和函数操作,这将导致引擎放弃使用索引而进行全表扫描。
如:select id from t where num/2=100改为select id from t where num=100*2
select id from t where substring(name,1,3)=‘abc’ 改为select id from t where name like ‘abc%’

⑧.exists 代替 in ,exists返回值是true或false,用于判断子查询返回结果集是否为空。
select num from a where num in(select num from b)
替换为select num from a where exists (select 1 from b where b.num=a.num)

⑨.任何地方都不要使用select * from t ,用具体的字段列表代替*

⑩.用>=替代>
例:
高效: SELECT id FROM EMP WHERE DEPTNO >=4
低效: SELECT id FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录,而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录。

你可能感兴趣的:(mysql索引 sql优化)