索引覆盖:
索引覆盖是指 如果查询的列恰好是索引的一部分,该列查询只需要在索引文件上进行,不需要回行到磁盘再找数据
这种查询速度非常快,称为"索引覆盖"
举例什么样的情况叫索引覆盖?
建一个表,这个表有三个字段,id,name,intro,将id和name建立一个联合索引
CREATE TABLE `t99` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键id' ,
`name` char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名' ,
`intro` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '介绍' ,
PRIMARY KEY (`id`),
INDEX `idname` (`id`, `name`) USING BTREE
);
随便插入两条数据
当我们做查询的时候
select name from test where id = 1;
这一句用到了索引覆盖,
select intro from test where id = 1;
这一句没用到索引覆盖,需要回行拿取数据
当我们用explain 解释这两个语句的时候,会发现,他们的extra第一个是using index ,第二个是null,这就是索引覆盖。
理想的索引
这里有一个概念,就是索引的区分度要高,然后索引的长度得小,这里其实挺矛盾,只有越长的索引区分度才会越高,但是这里实际上就是一个平衡,在长度尽量小的情况下,区分度要尽量高。
1.查询频繁
2.区分度高
3.长度小
4.尽量能覆盖常用查询字段
哪有什么多么完美的程序,总不是根据实际情况去优化和处理问题~
sql语句优化
1.sql语句的时间花在哪?
等待时间,执行时间
这两个时间并非孤立的,如果单条语句执行的快了,对其他语句的锁定的时间也就少了
所以我们来分析如何降低执行时间
2.sql语句的执行时间,又花在哪儿了?
查询--->沿着索引查找,慢者可能全表扫描
取出--->查到行后,把数据取出来
如何查询快?
a.查询的快 --->联合索引的顺序,区分度,长度
b.取的快,索引覆盖
c.传输的少,更少的行和列
切分查询:按数据拆成多次
例:插入1万条数据,每1k条为单位,插件
分解查询:按逻辑把多表链接查询分成多个简单sql
3.sql语句的优化思路?
不查->少查->高效的查
不查 通过业务逻辑来计算
比如论坛的注册会员数,我们根据之前的三个月每天的注册人数,用程序来估算
理论----追求绝对的精准,往往给你带来更的麻烦
少查 尽量精准数据,少取行,我们观察新闻网站,评论内容等,一般一次性取出10-30条左右
必须要查,尽量走在索引上查询(查询,分组,排序都走索引)
少查不必要的字段
explain的列的分析
id查询的序号,可能有多个select
select_type :查询类型 举例 simple 简单查询
table :表名
type:索引发挥的作用,是扫描一部分还是扫描所有
possible_keys: 可能用到的键
key: 实际用到的键
key_len: 实际用的键的最大长度
ref: 两表联查的引用关系
rows: 估计本次要查出多少行
extra: 额外信息
type
all 扫描了所有的行
index 扫描所有的索引节点
range 按范围查的
const system null 常量级别 非常快
ref 引用
eq_ref 引用等于某个值