mysql联查sql语句
sql语句:增删改查,其中 增、删、改只用于单表多表级联删除,级联更新有时候会出现(例如:删除父类别,子类别也会被删除)多表查询:多表联查、子查询建表语句: 一般不需要语句建表,语句了解认识即可,手动...
2024.11.15不啰嗦,直接入正题。问题是这样的。请问下面的sql语句,要想加快查询速度,该怎么创建索引?以下,以mysql数据库为准。
select * from test where a=? and b>? order by c limit 0,100复制代码结果可能会出乎你的意料。我们首先准备一下运行环境,然后按照最左前缀原则和explain关键字来进行验证。结果真是颠覆了xjjdog多年的认知。
准备阶段为了进行验证,我们创建一个简单的数据表。里面有a、b、c三个简单的int字段。
CREATE TABLE `test` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8复制代码接下来,写一个简单的存储过程,来插入10w条数据。等待大约1分钟,数据插入完毕。
drop PROCEDURE IF EXISTS test_initData;delimiter $CREATE PROCEDURE test_initData()BEGIN declare i INT DEFAULT 1; WHILE i10 and b >10 order by c复制代码首先,我们拿上面的sql语句进行验证。结果发现,查询使用了索引idx_a_b_c,只用到了前缀a,b。而extra部分,则用到了filesort,也就是性能非常差的方式。
我们尝试换一下查询参数的位置。 explain select * from test where c>10 and b >10 order by a复制代码这次索引自动选择了idx_b_a_c,但依然使用的filesort,查询效果是一样的。按照上面的逻辑,不是应该选择idx_b_c_a么?2、指定索引
接下来使用force index方式,强制指定索引。 这里直接给出结果,就是下面的sql。
explain select * from test FORCE INDEX(idx_c_b_a) where a>10 and b >10 order by c复制代码结果如下。
我们使用force index来指定使用的索引。这次效果非常好,显示使用了index,使用了where,只在索引上就完成了操作。但扫描的行数却增加了。但是,这与我们的经验是相悖的。idx_c_b_a的索引,是在字段(c,b,a)上创建的。按照最左原则,支持的搜索条件有:c,cb,cba。在这个例子中,order by后面的参数,却被当作了前缀的头部信息。
我们删掉其他索引,只留下idx_c_b_a,然后去掉force index部分。结果发现,mysql现在能够自动的选择索引了。
在看另外一种情况,order by上有两个参数。
explain select * from test FORCE INDEX(idx_b_c_a) where a>10 order by b,c复制代码结果如上,使用idx_b_c_a,不走filesort。其他索引都不是最优。
3、explain部分返回值意义
我们得出上面的结论,是根据mysql自己提供的explain工具。这个工具能够输出一些有用的信息。下面是相关的部分返回值的意义。
select_type
表示select的类型,常见的取值有:
SIMPLE简单表,不使用表连接或子查询。
PRIMARY主查询,即外层的查询。
UNIONUNION中的第二个或者后面的查询语句。
SUBQUERY子查询中的第一个。
type
表示MySQL在表中找到所需行的方式,或者叫访问类型。常见访问类型如下,从下到上,性能越来越差。
system,const 表只有一行记录(等于系统表),这是const类型的特列。
eq_ref 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。
ref 非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。
range 只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引。这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。
index Full Index Scan,Index与All区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。
all 全表扫描,性能最差
Extra
using index
表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率不错。如果同时出现using where,表明索引被用来执行索引键值的查找;如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。
using filesort
说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作称为“文件排序”。
using temporary
使用了用临时表保存中间结果,mysql在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。
End可以看到,在我们创建了多个索引的时候,mysql的查询优化,并不一定能够进行智能的解析、用到最优的方式,需要使用force index指定索引。
mysql中的索引,主要就用在where条件中和排序动作中。分两种情况。
1、先过滤,再排序,会用到过滤条件中的索引参数,但是排序会使用较慢的外部排序。因为这个结果集是经过过滤的,并没有什么索引参与。
2、先排序,再过滤,可以使用同一个索引,排序的优先级高于过滤的优先级。选择合适的索引,在过滤的同时就把这个事给办了。但是扫描的行数会增加。
我想,mysql并不能够了解到这两个过程,到底谁快谁慢,于是选了一个最通用的方式,直接选用了第一种。甚至在索引非常多的时候,直接晕菜了。**索引建多了,你可能间接把mysql给害了。**这是现象,至于深层次的原因,欢迎读过mysql相关源码的给解释一下。
这对经常变换字段进行排序的代码来说,并不是一个好的信号。考虑到程序的稳定性,我想应该要尽量减少where条件过滤后的结果集。这种情况下,创建一个(a,b)的联合索引,或许是一个折衷的方式。
原文链接:https://juejin.im/post/5d6881d4f265da03ab426341
小结欢迎关注头条号:JAVA大飞哥
点击关注评论转发一波:私信小编发送“架构”(免费获取)
获取微服务、分布式、高并发、高可用,性能优化丶Mysql源码分析等等一些技术资料
最后,每一位读到这里的Java程序猿朋友们,感谢你们能耐心地看完。希望在成为一名更优秀的Java程序猿的道路上,我们可以一起学习、一起进步!都能赢取白富美,走向架构师的人生巅峰!
sql语句:增删改查,其中 增、删、改只用于单表多表级联删除,级联更新有时候会出现(例如:删除父类别,子类别也会被删除)多表查询:多表联查、子查询建表语句: 一般不需要语句建表,语句了解认识即可,手动...
2024.11.15大家好,今日继续讲解VBA数据库解决方案,今日的内容是第70讲: 数据查询中,三个工作表联合查询的方法。在各种查询中,内连接,左外连接,右外连接等等,这些方法大家在工作中要多加利用,并且灵活利用,利用...
2024.11.15概览最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的...
2024.11.15一、向MyServer数据库里的5张表添加约束:1、向部门表Department添加约束字段名数据类型表关系备注D_IdINT主键 自动增长 NOT NULL部门IDD_NameVarchar(10)...
2024.11.15使用 drop 语句,可以删除索引、表和数据库。drop INDEX 语句我们可以使用 drop INDEX 命令删除表的索引。不同的数据库其具体应用略有区别,如下MySQL 的drop INDEX ...
2024.11.15