看看这个查询:
mysql> select * from test1其中name='javacode3500000 '和sex = 2;--| id | name | sex | email |--| 3500000 | javacode 3500000 | 2 | javacode3500000@163.com |-集合中的一行(0.00秒)
上面的查询速度很快,名字和性别上分别有索引 。你认为应该取哪个指标?
有人说名字位于第一位,所以取名字字段所在的索引 。该过程可以解释如下:
转到name所在的索引,找到对应于javacode3500000的所有记录 。
遍历记录,筛选出性别=2的值 。
我们来看看name='javacode3500000 '的检索速度,真的很快,如下:
MySQL > select * from test1 where name = ' javacode 3500000 ';--| id | name | sex | email |--| 3500000 | javacode 3500000 | 2 | javacode3500000@163.com |-集合中的一行(0.00秒)
真的可以取名字索引然后过滤,速度也很快 。真的和where之后的字段顺序有关吗?让我们交换姓名和性别的顺序,如下所示:
mysql> select * from test1其中sex=2,name = ' javacode3500000--| id | name | sex | email |--| 3500000 | javacode 3500000 | 2 | javacode3500000@163.com |-集合中的一行(0.00秒)
速度还是很快的 。是不是应该先通过性别索引检索数据,再筛选名字?我们先来看看sex=2的查询速度:
MySQL > select count(id)from test1其中sex = 2;-| count(id)|-| 2000000 |-集合中的一行(0.36秒)
看上面,查询用时360毫秒,有200万条数据 。如果拿性来说,肯定不行 。
我们用解释来看看:
mysql >解释select * from test1,其中sex=2,name = ' javacode3500000--------------------- id | select _ type | table | partitions | type | possible _ keys | key | key _ len | ref | rows | filtered | Extra |------------- 1 | SIMPLE | test1 | NULL | ref | idx 1,id x2 | idx 1 | 62 | const | 1 | 50.00 | Using where |------------------------//h/]1行,1警告(0
possible_keys:列出该查询可能采用的两个索引(idx1,idx2) 。
其实是idx1(关键列:索引实际取) 。
当多个条件中存在指标,且关系为and时,将取区分度高的指标 。很明显,姓名字段重复度低,取姓名查询会更快 。
模糊查询
看两个查询
MySQL > select count(*)from test1a where a . name like ' javacode 1000% ';-| count(*)|-| 1111 |-集合中的1行(0.00秒)MySQL > select count(*)from test1a其中a.name类似于“% javacode 1000%”;-| count(*)|-| 1111 |-集合中的1行(1.78秒)
上面的第一个查询可以使用name字段上面的索引,后面的查询无法确定要搜索的值的范围,所以只能扫描整个表而不使用索引,所以速度比较慢,如上所述 。
返回到表格
当要查询的数据不在索引树中时,需要再次从聚集索引中检索 。这个过程叫做表返回,比如查询:
MySQL > select * from test1 where name = ' javacode 3500000 ';--| id | name | sex | email |--| 3500000 | javacode 3500000 | 2 | javacode3500000@163.com |-集合中的一行(0.00秒)
上面的查询是*,因为姓名列所在的索引只包含姓名和id两列的值,不包含性别和邮箱,所以上面的过程如下:
取名称索引检索javacode3500000对应的记录,取出3500000的id 。
从主键索引中检索id=3500000的记录,并获取所有字段的值 。
索引覆盖
查询中使用的索引树包含了查询需要的所有字段的值,不需要聚合索引来检索数据 。这就是所谓的指数覆盖率 。
让我们来看一个查询:
select id,name from test1 where name = ' javacode 3500000 ';
name对应idx1索引,id是主键,所以idx1索引叶子的子节点包含name和id的值 。这个查询只需要将idx1作为索引 。如果在select之后使用了*,则需要返回到表中一次,以获取sex和email的值 。
所以,写sql的时候,尽量避免使用* 。*可能会多一个回表操作,看能不能通过索引叠加实现效率更高 。
推荐阅读
- 如何设置QQ交友验证问题
- 芥末酱的配方是什么
- 埃菲尔铁塔简笔画
- 义乌有什么好玩的地方
- 对虾和青虾的区别
- 如何设置qq空间全背景的封面
- 桂林有什么好玩的旅游景点
- 长沙有什么好玩的地方
- 如何设置QQ空间说说尾巴
- 汕头有什么好玩的景点
