在建立表的时候建立索引:html
其中关键字 INDEX
能够用 KEY
替代,INDEX
前面能够加上索引的类型 UNIQUE | FULLTEXT | SPATIAL | NORMAL
,默认是 NORMAL
java
CREATE TABLE `student` (
`id` bigint NOT NULL,
`name` varchar(30),
PRIMARY KEY (`id`),
INDEX `idx_name` (`name`) -- 对 name 字段加上名为 idx_name 的索引
)
复制代码
对已经存在的表添加索引:mysql
ALTER TABLE student ADD INDEX idx_name (`name`)
复制代码
并非每一个字段都适合建立索引,索引的建立也是要消耗磁盘空间的,并非说索引就越多越好git
在这里分享一个xiao ji si,InnoDB 表最多能够包含 1017列,最多建立 64个 二级索引面试
对于 Mysql 来讲,含有空值的列很难进行查询优化,若是频繁查询的值又避免不了为 null,能够考虑使用 0,1 或者空字符这些短字符串进行替代。若是索引的字段能够为 NULL,索引的效率会降低不少,由于它们使得索引、索引的统计信息以及比较运算更加复杂markdown
举个例子,一张学生表里面有个字段是性别 sex
, 它里面存的是男和女,各占约百分之五十,那这样即使你创建了索引,用哪一个值都是搜出一半来,那这样还不如不建索引ide
MySQL有一个查询优化器,查询优化器发现某个值出如今表的数据行中的百分比很高的时候,它通常会忽略索引,进行全表扫描函数
惯用的百分比界线是"30%"。(匹配的数据量超过必定限制的时候查询器会放弃使用索引(这也是索引失效的场景之一哦)oop
以上字段均可以考虑设计上索引
例:对于学生表(student
)和成绩表(grade
),假设有这么一条语句被频繁执行:
-- 下班准备去幸福小区,爆破成绩不及格的学生
select name, age from student a
left join grade b on a.id = b.student_id
where a.address like '%幸福小区%' and b.grade < 60
复制代码
对于 student
表,能够创建索引的字段有 name、age、address、birthday
,对于 grade
表,在 student_id
创建索引,能够大大提升连表查询的速度
group by
,order by
的字段将 order by
后面的字段创建索引,这样在查询的时候就不须要再去作一次排序了,由于咱们都已经知道了创建索引以后在B+树中的记录都是排序好的
group by 和 order by
实际上是相似,因此将这两个放在一块儿说了
由于在group by
的时候也要先根据 group by
后面的字段排序,而后在执行聚合操做
若是 group by
后面的字段没有排序,那么这个时候MySQL是须要先进行排序的,这样就会产生临时表,一个排好序的临时表,而后再在临时表中执行聚合操做,这样子固然效率很低了,若是 group by
后面的字段已经创建了索引,那么MySQL
就不须要再去排序,也就不会产生临时表
SQL优化中,合理的创建索引算是基本操做了。虽然索引能带来查询上的效率提高,可是索引的成本也是不小的,索引会占用磁盘空间,而且下降添加、删除、和更新的速度。若是一个字段不被常常查询,可是又常常被更新,那么便不该该在这个字段上加索引
由于索引是须要占用磁盘空间的,能够简单理解为每一个索引都对应着一颗 B+树。若是一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是不少的,且修改索引时,耗费的时间也是较多的。若是是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操做效率也会提高
冗余索引指的是索引的功能相同,可以命中索引(a, b)就确定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,可以命中前者的查询确定是可以命中后者的 在大多数状况下,都应该尽可能扩展已有的索引而不是建立新索引
前缀索引仅限于字符串类型,较普通索引会占用更小的空间,因此能够考虑使用前缀索引带替普通索引
索引并非说建立好以后就可无论,良好的索引须要开发人员的长期维护
首先索引对于中到大型表索引都是很是有效的,可是特大型表的话维护开销会很大,不适合建索引,对于小型表来讲,查询所有数据的时间可能比遍历索引的时间还要短,不须要建立索引
其次须要删除长期未使用的索引也是有必要的,不使用的索引不只占用着磁盘空间,并且会形成没必要要的性能损耗,Mysql5.7 后能够经过查询 sys.schema_unused_indexes
表来获取长期未使用的索引
若是是已经创建好的索引的字段在使用的时候执行了函数操做,那么这个索引就使用不到了
由于MySQL
为该索引维护的B+树就是基于该字段原始数据的,若是正在使用过程当中加了函数,MySQL
就不会认为这个是原来的字段,那确定不会走索引了
若是非要让函数走索引,能够在建立索引的时候把函数带上
例:
SELECT * FROM student WHERE round(age) = 2;
复制代码
上面语句会使索引 idx_age
失效,若是非要让这条语句走索引,能够这样建立:
create index idx_age_round on student(round(age));
复制代码
其次,在 where
中对索引列进行了运算,也会使索引失效
like
条件中使用 % 开头select * from student where name like '%bc%'
复制代码
就上面的语句来讲,索引是不生效的,想要索引生效,须要把前缀的 %
去掉
or
条件若是想要让 or
条件走索引,须要把 or
条件中的全部字段加上索引
最左匹配原则就是指在联合索引中,若是你的 sql 语句中用到了联合索引中的最左边的索引,那么这条 sql 语句就能够利用这个联合索引去进行匹配,当遇到范围查询(>、<、between、like)就会中止匹配