mysql> select * from tbl_emp; +----+-------+--------+ | id | name | deptId | +----+-------+--------+ | 1 | jack | 1 | | 2 | tom | 1 | | 3 | alice | 2 | | 4 | john | 3 | | 5 | faker | 4 | | 7 | ning | NULL | | 8 | mlxg | NULL | +----+-------+--------+ 7 rows in set (0.00 sec)
两表的关联关系如图所示:
1、左连接(A独有+AB共有)
查询所有部门以及各部门的员工数:
mysql> select t1.id,t1.deptName,count(t2.name) as emps from tbl_dept t1 left join tbl_emp t2 on t2.deptId=t1.id group by deptName order by id; +----+----------+------+ | id | deptName | emps | +----+----------+------+ | 1 | 技术部 | 2 | | 2 | 美工部 | 1 | | 3 | 总裁办 | 1 | | 4 | 人力资源 | 1 | | 5 | 后勤组 | 0 | +----+----------+------+ 5 rows in set (0.00 sec)
2、右连接(B独有+AB共有)
查询所有员工及其所属部门:
mysql> select t2.id,t2.name,t1.deptName from tbl_dept t1 right join tbl_emp t2 on t2.deptId=t1.id; +----+-------+----------+ | id | name | deptName | +----+-------+----------+ | 1 | jack | 技术部 | | 2 | tom | 技术部 | | 3 | alice | 美工部 | | 4 | john | 总裁办 | | 5 | faker | 人力资源 | | 7 | ning | NULL | | 8 | mlxg | NULL | +----+-------+----------+ 7 rows in set (0.04 sec)
3、内连接(AB共有)
查询两表共有的数据:
mysql> select deptName,t2.name empName from tbl_dept t1 inner join tbl_emp t2 on t1.id=t2.deptId; +----------+---------+ | deptName | empName | +----------+---------+ | 技术部 | jack | | 技术部 | tom | | 美工部 | alice | | 总裁办 | john | | 人力资源 | faker | +----------+---------+
4、A独有
即在(A独有+AB共有)的基础之上排除B即可(通过b.id is null即可实现):
mysql> select a.deptName,b.name empName from tbl_dept a left join tbl_emp b on a.id=b.deptId where b.id is null; +----------+---------+ | deptName | empName | +----------+---------+ | 后勤组 | NULL | +----------+---------+
5、B独有
与(A独有)同理:
mysql> select a.name empName,b.deptName from tbl_emp a left join tbl_dept b on a.deptId=b.id where b.id is null; +---------+----------+ | empName | deptName | +---------+----------+ | ning | NULL | | mlxg | NULL | +---------+----------+
6、A独有+B独有
使用union将(A独有)和(B独有)联合在一起:
mysql> select a.deptName,b.name empName from tbl_dept a left join tbl_emp b on a.id=b.deptId where b.id is null union select b.deptName,a.name emptName from tbl_emp a left join tbl_dept b on a.deptId=b.id where b.id is null; +----------+---------+ | deptName | empName | +----------+---------+ | 后勤组 | NULL | | NULL | ning | | NULL | mlxg | +----------+---------+
7、A独有+AB公共+B独有
使用union(可去重)联合(A独有+AB公共)和(B独有+AB公共)
mysql> select a.deptName,b.name empName from tbl_dept a left join tbl_emp b on a.id=b.deptId union select a.deptName,b.name empName from tbl_dept a right join tbl_emp b on a.id=b.deptId; +----------+---------+ | deptName | empName | +----------+---------+ | 技术部 | jack | | 技术部 | tom | | 美工部 | alice | | 总裁办 | john | | 人力资源 | faker | | 后勤组 | NULL | | NULL | ning | | NULL | mlxg | +----------+---------+
Using filesort:说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作称为“文件排序”
mysql> explain select * from person order by lastName\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: person partitions: NULL type: index possible_keys: NULL key: idx_name key_len: 186 ref: NULL rows: 1 filtered: 100.00 Extra: Using index; Using filesort
使用\G代替;结尾可以使执行计划垂直显示。
mysql> explain select * from person order by firstName,lastName\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: person partitions: NULL type: index possible_keys: NULL key: idx_name key_len: 186 ref: NULL rows: 1 filtered: 100.00 Extra: Using index
Using temporary:使用了临时表保存中间结果。MySQL在对查询结果聚合时使用临时表。常见于排序 order by 和分组查询 group by。
mysql> insert into person(firstName,lastName) values('张','三');
mysql> insert into person(firstName,lastName) values('李','三');
mysql> insert into person(firstName,lastName) values('王','三');
mysql> insert into person(firstName,lastName) values('李','明');
mysql> select lastName,count(lastName) from person group by lastName; +----------+-----------------+ | lastName | count(lastName) | +----------+-----------------+ | 三 | 3 | | 明 | 1 | +----------+-----------------+
mysql> explain select lastName,count(lastName) from person group by lastName\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: person partitions: NULL type: index possible_keys: idx_name key: idx_name key_len: 186 ref: NULL rows: 4 filtered: 100.00 Extra: Using index; Using temporary; Using filesort
Using index:表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行(需要读磁盘),效率不错!如果同时出现Using where,表明索引被用来执行索引键值的查找;如果没有同时出现Using where,表明索引用来读取数据而非执行查找动作。
mysql> alter table test add c5 varchar(10) default null, add c6 varchar(10) default null, add c7 varchar(10) default null;
mysql> create index idx_c5_c6_c7 on test(c5,c6,c7);
如果没有左前缀列则不会利用索引:
mysql> explain select * from test where c6=''\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 filtered: 100.00 Extra: Using where
mysql> explain select * from test where c6='' and c7=''\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 filtered: 100.00 Extra: Using where
mysql> explain select * from test where c5='' and c7=''\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test partitions: NULL type: ref possible_keys: idx_c5_c6_c7 key: idx_c5_c6_c7 key_len: 33 ref: const rows: 1 filtered: 100.00 Extra: Using index condition 1 row in set, 1 warning (0.00 sec)
mysql> explain select * from test where c5='' and c7='' and c6=''\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test partitions: NULL type: ref possible_keys: idx_c5_c6_c7 key: idx_c5_c6_c7 key_len: 99 ref: const,const,const rows: 1 filtered: 100.00 Extra: NULL 1 row in set, 1 warning (0.00 sec)
最优的做法是:
mysql> explain select * from test where c5=''\G
mysql> explain select * from test where c5='' and c6=''\G
mysql> explain select * from test where c5='' and c6='' and c7=''\G
3、不在列名上添加任何操作
有时我们会在列名上进行计算、函数运算、自动/手动类型转换,这会直接导致索引失效。
mysql> explain select * from person where left(firstName,1)='张'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: person partitions: NULL type: index possible_keys: NULL key: idx_name key_len: 186 ref: NULL rows: 4 filtered: 100.00 Extra: Using where; Using index
mysql> explain select * from person where firstName='张'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: person partitions: NULL type: ref possible_keys: idx_name key: idx_name key_len: 93 ref: const rows: 1 filtered: 100.00 Extra: Using index
Mysql 实现读写分离的详细教程(amoeba)发布时间:2018-08-17作者:laosun阅读(2220)继上篇文章,mysql实现主从配置之后的读写分离实现方式,文章地址。amoeba是盛大架构师陈思儒独立完成,除此之外还有很多中间件ÿ…
我最近实施了一个小项目,在该项目中,我们必须轮询文件夹中的新文件,然后在文件内容上触发服务流。 Spring Integration非常适合此要求,因为它带有一个通道适配器 ,该适配器可以扫描文件夹中的新文件,然后通…