SQL优化-索引
索引的优势和劣势
索引简单来说是排好序的数据结构,所以它能大幅度的提高查询效率,降低数据排序的成本,降低数据库的IO成本。
但是索引也同样占用很大空间,通常是以索引文件的形式存储在磁盘上,并且更新数据的同时得更新相应的索引。
总的来说:索引能提高查询效率,但降低更新效率,所以经常更新的表尽量不要加索引
索引的分类和索引命令语句
索引分类
- 单值索引:一个索引只包含单个列,一个表可以有多个单值索引。
- 唯一索引:索引列的值必须唯一,但允许有空值
- 复合索引:一个索引包含多个列
一张表建议建立索引不要超过五个
基本语法
- 创建:
(1)CREATE [UNIQUE] INDEX indexname ON mytable(columnname(length));
(2)ALTER mytable ADD [UNIQUE] INDEX [indexname] ON (columnname(length)); - 删除:DROP INDEX [indexname] ON mytable;
- 查看:SHOW INDEX FROM table_name\G;
(\G存在的情况下列形式显示,不存在的情况下行形式显示) - 使用ALTER命令:ALTER TABLE mytable ADD (PRIMARYKEY)((UNIQUE|INDEX|FULLTEXT)indexname)(column_list);
PRIMARYKEY:唯一索引(主键索引,一般自动添加),索引值唯一,且不能为null。
UNIQUE:唯一索引,索引值唯一,可出现null,且null可重复出现。
INDEX:普通索引,索引值可出现多次。
FULLTEXT:全文索引。
判断是否适合建索引
适合建立索引的情况
- 主键自动建立唯一索引
- 频繁作为查询条件的字段
- 查询中与其它表关联的字段
- 查询中排序的字段
- 查询中统计或分组的字段
不适合建立索引的情况
- 频繁更新的字段(更新不止是更新记录,还得更新索引)
- Where语句用不到的字段
- 表的记录不多
- 频繁增删改的表
- 数据列大量重复内容(如:性别,只有 男,女)
一般来说复合索引优于单值索引
性能分析
MySql Query Optimizer
MySql自带的查询优化器,MySql有专门负责优化SELECT语句的优化器模块。
MySql 常见瓶颈
- CPU:CPU在饱和的时候,一般发生在数据装入内存或者从磁盘读取数据的时候。
- IO:磁盘I/O瓶颈常发生在装入数据远大于内存容量的时候。
- 服务器硬件问题。
EXPLAIN(查看执行计划)
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySql是如何处理你的SQL语句,从中得出如何优化你的SQL语句。
如何使用?
在SQL语句前+EXPLAIN关键字(如:explain select * from userdb)
包含信息
- id:select查询的序列号,表示操作顺序,id相同的情况下顺序由上到下,id不同的情况下顺序由大到小。
- select_type:查询类型,主要用于区别普通查询,联合查询,嵌套查询等的复合查询。
- table:显示这一行数据是关于哪张表
- type:从好到怀:system(表只有一行记录,系统表)>const(通过一次索引就找到)>eq_ref(唯一索引扫描)>ref(非唯一索引扫描)>range(只索引给定范围)>index(全索引扫描)>all(全表扫描) 一般来说要保证达到range级别
- possible_keys:可能用到的哪些索引
- key:实际用到的索引
- key_len:索引中使用的字节数,在不损失精确性的情况下,越小越好。
- ref:显示索引的哪些列被使用
- rows:查找到所需数据的行数
- extra: 加分项:USING index , 扣分项:USING filesort、USING temporary(有扣分项的情况下尽量优化)
EXPLAIN实际运用
创表并插入数据
CREATE TABLE IF NOT EXISTS blogs(
id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
author_id INT(10) UNSIGNED NOT NULL,
category VARCHAR(20) NOT NULL,
views INT(20) NOT NULL,
assist INT(20) NOT NULL,
comments VARCHAR(20) NOT NULL,
title VARCHAR(255) NOT null,
content TEXT NOT NULL);
INSERT INTO blogs(author_id,category,views,assist,comments,title,content)VALUES
(1,'java',821,100,'1','java','1'),
(2,'sql',534,100,'2','sql','1'),
(3,'c',1928,100,'3','c','1'),
(4,'c++',851,100,'4','c++','1'),
(5,'c#',89,50,'5','c#','1');
- 没有建立索引的情况下用EXPLAIN:
EXPLAIN SELECT id, author_id from blogs where comments = '1' and views > 1 ORDER BY assist desc LIMIT 1;
扫描二维码关注公众号,回复:
11638892 查看本文章
- 查找表中的索引
show index from blogs;
这里只有sql自主建的主键索引
- 建立索引
create index idx_blogs_cva on blogs (comments,views,assist);
- 再查找表中的索引
show index from blogs
- 再用EXPLAIN查看性能
EXPLAIN SELECT id, author_id from blogs where comments = '1' and views > 1 ORDER BY assist desc LIMIT 1;
这里很明显已经用到了索引,但是Extra里面出现了Using filesort,SQL需要优化
- 优化方式:删除索引,再建立comments,assist索引(具体原因,后面会说到)
Drop index idx_blogs_cva on blogs;
create index idx_blogs_ca on blogs(comments,assist);
EXPLAIN SELECT id, author_id from blogs where comments = '1' and views > 1 ORDER BY assist desc LIMIT 1;