内连接(两者交集)
select * from tableA a inner join tableB b on a.key=b.key;
左外连接(左表a独有部分加上两者交集,独有部分对应另一个表字段为null)
select * from tableA a left join tableB b on a.key=b.key;
左连接(左表a独有部分)
select * from tableA a left join tableB b on a.key=b.key where b.key is null;
右外连接(右表b的独有加上两者交集)
select * from tableA a right join tableB b on a.key=b.key;
右连接(右表b独有部分)
select * from tableA a right join tableB b on a.key=b.key where a.key is null;
全连接(a表独有加b表独有加两者交集)
select * from tableA a left join tableB b on a.key=b.key
union
select * from tableA a right join tableB b on a.key=b.key;
各自独有部分
select * from tableA a left join tableB b on a.key=b.key where b.key is null
union
select * from tableA a right join tableB b on a.key=b.key where a.key is null;
索引是帮助数据库高效获得数据的数据结构(排好序的快速查找数据结构,有B树结构、哈希),索引一般本身也很大,往往以索引文件的形式存在磁盘。
索引优势:提高检索效率、降低数据排序成本
索引劣势:实际是索引也是一张表,保存了主键和索引字段,并指向实体表记录,也要占空间;降低更新表的速度
单值索引:索引只包含单列
唯一索引:列值必须唯一,但允许有空值
复合索引:索引包含多列
可以使用create index 和alter table add index
BTree、hash、full-text全文、R-Tree
适合建索引:
主键自动建立唯一索引
频繁作为查询条件的字段
与其它表关联的查询字段
高并发下倾向创建组合索引
索引字段与排序字段、统计分组字段一致,可以提供排序速度
不适合建索引:
数据太少
频繁更新的字段
字段值重复太多(比如性别字段只有男女)
where条件里用不到的字段
1.id:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。id相同的执行顺序由上往下;id不同,如果是子查询,id号会自增,值越大优先执行
2.select_type:查询类型,有6种
simple:简单的select查询,不包含子查询和union
primary:查询中包含复杂的字子部分,最外层则被标记为primary
subquery:select或者where中包含子查询
derived:在from列表中包含的子查询被标记为derived(衍生)
union:若 第二个select出现在union之后,则被标记为union;若union包含在from子句的子查询中,最外层select被标记为derived
union result:从union表获得结果的select
3.table:执行的表名
4.type:查询类型,从好到差的排序是system>const>eq_ref>ref>range>index>all,一般来说得保证查询到达range级别,最好ref。
system:表只有一行记录(等于系统表),这是const的特例
const:通过索引一次就找到了,用于比较primary key或者unique索引。如将主键置于where列表中,MySQL就能将该查询转换为一个常量
eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或者唯一索引扫描
ref:非唯一性索引扫描,返回匹配某个单独值所有行,本质上也是一种索引访问
range:只检索给定范围的行,使用一个索引来选择行。一般是在where中出现了between、<、>、in等的查询
index:全索引扫描,index和all都是读全表,但是index只遍历索引数,是从索引中读取,而all是从硬盘读取。index通常比all快,因为索引文件通常比数据文件小。
all:全表扫描
5.possible_keys:可能应用到的索引,若查询字段存在索引,则会被列出来,但不一定会真的使用到。
6.key:实际使用的索引,若为null,则没有使用索引。查询中若使用了覆盖索引(覆盖索引是select查询的字段和顺序,跟创建的复合索引字段和顺序一样),则该索引仅出现在key列表中
7.key_len:显示为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。在不失精度的条件下,长度越短越好。
8.ref:显示索引的哪一列被使用了,如果可能的话,是一个常量。哪些列或常量被用于查找索引列上的值
9.rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需读取的行数。
10.Extra:包含不适合在其他列显示,但十分重要的额外信息
Usring filesort:mysql对数据使用了一个外部的索引排序,不是按照表内的索引顺序进行读取。mysql中无法利用索引完成的排序操作称为“文件排序”。
Using temporary:在对查询结果排序时使用了临时表,常见于排序order by和分组查询group by
Using index:表示相应的select操作中使用了覆盖索引,效率不错!如果同时出现using where,表明索引被用来执行索引键值的查找;如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。
Using where:使用了where过滤
Using join buffer:使用连接缓存
impossible where:where子句的值总是false,不能返回任务数据
1、两表left join查询,在右边关联字段上建索引,这是因为左连接左表一定有,关键点是如何从右表搜索。右连接相反再在左表建索引。
2、如何避免索引失效:
(1)遵守最佳左前缀法则:如果索引了多列(复合索引),查询条件的列从索引的最左前开始并且不跳过索引的列。
(2)不在索引列上做任何的操作(计算、函数、类型转换(自动or手动))
(3)索引字段使用范围查询其后面字段索引无效。
(4)索引列使用不等于(!=或者<>)会导致索引失效
(5)is null,is not null无法使用索引
(6)like以通配符开头(%abc)索引失效,以常量开头可以使用索引(abc%)。如果必须like %abc% ,可以使用覆盖索引(即查询的列就是索引列)
(7)索引列配置时条件类型不一致索引失效
(8)少用or,连接时会索引失效
1、查询优化
(1)优化原则:小表驱动大表
当A表数据大于B时,用in优于exists(用in是先执行B表子查询,再匹配A表主查询)
select * from A where id in (select id from B)
当A表数据小于B时,用exists优于in(exists先执行A表主查询,验证主查询的结果是否在A表)
select * from A where id exists(select 1 from B whre B.id=A.id)
(2) order by关键字优化
2、慢查询日志
(1)查看是否开启:
show variables like '%slow_query_log%'(默认是关闭)
(2)开启慢查询:
set global slow_query_log=1(只对当前数据库生效,mysql重启后失效)
永久生效修改配置my.cnf,global slow_query_log=1和slow_query_log_file=日志路径(如果没有指定默认文件是 host_name-show.log)
(3)查看慢查询sql阈值时间(大于阈值sql才会记录):
show variables like '%slow_query_time%'(默认是10秒)
(4)设置阈值时间:
set global slow_query_time=5
(修改后看不到变化:需要重新连接会话或者使用命令show variables like '%slow_query_time%')
(5)查看有多少条慢sql:
show global status like '%slow_queries%'
(6)日志分析工具mysqldumpslow
3、show profile
(1)是MySQL提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于sql的调优的测量。默认是关闭状态,并保存最近15次的运行结果
(2)查询是否开启
show variables like 'profiling'
(3)设置开启
set profiling=on
(4)查看sql运行结果
show profiles
(5)诊断sql
show profile cpu,block io for query 上面运行结果的query_id
出现问题的信号:
converting heap to myisam 查询结果太大,内存不够用
creating temp table 创建临时表(拷贝数据到临时表,用完再删除)
coping to tmp table on disk把内存中临时表复制到磁盘
locked
(1)读锁(共享)
一个会话锁了A表,当前会话只能查询A表,不能修改A表,也不能操作其他表;其他会话可以查询A表和数据库其他表,修改A表会堵塞等待
(2)写锁(独有)
一个会话锁了A表,当前会话只能查询、修改A表,不能操作其他表;其他会话不能操作A表会堵塞等待,可以操作数据库其他表
(3)命令
查看哪些表锁了:show open tables
分析表锁定:show status like 'table%'
Table_locks_immediate:产生表锁的次数
Table_locks_waited:锁争用而等待的次数
总结:读锁会堵塞写,不会堵塞读;写锁会堵塞读写。myisam的读写调度是写优先,它不适合做以写为主的引擎。
(1)与myisam区别
innodb支持事务和采用行锁
(2)索引失效,导致行锁变表锁
比如一个vachar2字段建立索引,修改where 匹配时输入是number,类型不匹配
(3)间隙锁
当使用范围条件的时候,会锁定整个范围内所有的索引键值,即使这个键值不存在。会导致无法插入锁定内范围的任何数据。
(4)锁查看分析
1、事物隔离级别
读未提交:read uncommitted :事物A和事物B,事物A未提交的数据,事物B可以读取到
读已提交:read committed:事物A和事物B,事物A提交的数据,事物B才能读取到
可重复读:repeatable read:事务A和事务B,事务A提交之后的数据,事务B读取不到,事务B是可重复读取数据
串行化:serializable:事务A和事务B,事务A在操作数据库时,事务B只能排队等待
脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说,
后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据
注:InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了可重复读下幻读问题
大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle.
少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎
2、事物传播行为
PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。