列的别名
1、在原字段后使用空格,空格后放置别名 使用,分割字段
2、使用as关键字
3、使用双引号,将别名引起来
着重号
当列名或者表名和关键字重名的时候可以使用``来解决
IFNULL
IFNULL(id,0):如果id为null,就替换成0。NULL值参与运算结果为NULL:100+NULL=NULL
查询常量
查询表结构:
DESCRIBE finance_project;
DESC也可以。
UNION和UNION ALL:
两者都是对相同列数的数据对两个结果集进行并集操作,union会去除重复行,并使用默认规则排序;union all 不会去除重复行,不排序
HAVING
1、如果过滤条件中,使用了聚合函数,则必须使用HAVING来替换WHERE
2、HAVING必须放在GROUP BY 的后边
MyISAM和Innodb的区别
1、Inodb支持外键
2、Innodb支持事务,可以确保事务提交或者回滚,MyISAM不支持事务,崩溃后无法恢复。
3、Innodb是行锁,MyISAM是表锁
4、Innodb是为处理巨大数据量的最佳设计。
5、MyISAM使用count(*)的效率很高,因为自己额外维护了一个字段,只读或者以读为主的业务建议使用MyISAM。.myd存储数据 .myi存储索引 .frm 存储表结构
缺点就是:Innodb对于新增和查询的性能不如MyISAM,而且对内存的要求比较高,因为Innodb索引和数据存放在一起,MyISAM数据和索引不存放在一起。
聚集索引和非聚集索引
聚集索引:定义:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。
非聚集索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
区别
区别一:
聚集索引:就是以主键创建的索引,在叶子节点存储的是表中的数据,缺点是插入速度严重依赖插入顺序,更新主键的代价很高,二级索引访问需要两次索引查找。
非聚集索引:就是以非主键创建的索引(也叫做二级索引),在叶子节点存储的是主键和索引列。
区别二:
聚集索引中表记录的排列顺序和索引的排列顺序一致;所以查询效率快。
非聚集索引中表记录的排列顺序和索引的排列顺序不一致。
区别三:
聚集索引每张表只能有一个,非聚集索引可以有多个。
MySQL使用InnoDb存储引擎,InnoDb将数据划分为若干个页,页的默认大小为16kb,页与页在物理地址上不相连,通过双向链表链接,每个数据页中的数据会按照主键值由小到大组成单向链表。
根页面位置万年不动
根页面的位置是不会发生变化的,最开始一颗B+树,存储记录,当存储满了之后,会把根页面的数据复制,根页面不在存储数据,存储页记录。我们还要保证内节点目录项的记录唯一。、
Innodb本身不支持Hash索引,但是提供自适应Hash索引,如果某个数据经常被访问,当满足一定条件时,就会将这个数据也的地址放到hash表中,这样下次查询的时候,就可以直接找到这个页面的位置,时B+树具备了hash索引的优势。
覆盖索引
覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。
我们可以看到下边这个很简单的查询语句,对name字段建立了一个普通索引,这个语句正常找到name列之后会进行回表操作,从主键索引上查询出age列的值。
EXPLAIN SELECT name,age from ceshi where name='张三';
下边我们将age列去掉,我们发现执行计划输出的Extra中出现了Using index这样一个提示,说明使用了覆盖索引,没有进行回表操作。因为我们需要查询出的列的数据,就在name索引上。无需回表。
EXPLAIN SELECT name from ceshi where name='张三';
索引下推
Extra 中出现了Using index condition 表示使用了索引下推,下边这个例子建立了联合索引,(age,name),正常来讲%号放在前面查询到age等于1的记录之后就会回表,查询出所有数据进行比较,使用索引下推之后,就会将name的条件也进行筛选之后在进行回表。
EXPLAIN SELECT * from ceshi where age =1 AND name LIKE '%张';
索引失效的场景
1、最左前缀原则
在查询的过程中,联合索引遵循最左前缀原则,联合索引中,在进行数据检索时从索引的最左端开始匹配。联合索引有多个列,对于多列索引,查询过滤条件的字段,必须顺序的包含索引中的字段,一旦跳过某个字段,则索引后面的字段就会失效。如果过滤条件中没有使用联合索引中的第一个字段,则这个索引不会被使用到。
2、计算\函数会使索引失效
3、类型转换导致索引失效
4、查询条件出现<>/!=会使索引失效(不一定)
例如:age!=5 ,其实查询是(负无穷,5)与(5,到正无穷)这两个区间 ,例如有10条数据,9条都是5,这个时候只需要回表一次,是有可能会走二级索引的
5、is not null/is null 可能走索引也可能不走索引,主要看数据分布
6、模糊匹配前边是%会使索引失效
7、or的前后列不是索引列会使索引失效,or必须前后全是索引才会生效
回表
在上边多次出现一个操作叫做回表,回表就是先通过数据库二级索引扫描出数据所在的行,再通过行主键id到主键索引上取出二级索引中未提供的数据,即基于非主键索引的查询需要多扫描一棵索引树.
分析表
分析关键字的分布, 分析并存储MyISAM和BDB表中键的分布:
我们可以看到现在数据的分布是5,代表着name有5个不同的值,我们更改一下数据,是表中不同的name达到6个,再次运行show index 语句发现数据没有发生变化。
我们使用下面的语句对表进行分析:
ANALYZE TABLE ceshi(表名);
再次show index 发现数据已经改变
检查表
CHECK table ceshi;
检查表的错误,并且为MyISAM更新键的统计内容
优化表
OPTIMIZE TABLE ceshi;
优化表主要作用是消除删除或者更新造成的空间浪费,清除空间碎片
redo日志
为什么需要REDO日志
我们都知道数据库读取数据是从磁盘加载到内存中,在内存中进行读取,因为操作内存的速度要快很多,写入的时候同样是要先写入到内存中,然后刷盘到磁盘。但是如果在这个过程中发生宕机,就会造成内存和磁盘的数据不一致,或者数据丢失,这是非常可怕的。所以我们需要使用redo log 日志来记录,内存中数据发生的变化。还有一点就是刷盘也会占用性能,我们也不需要时时刻刻进行刷盘。所以redo log也提供了rodo log buffer 来在内存中先记录,然后写入到磁盘中的redo log file 中;
REDO日志的好处、特点
1. 好处
-
redo日志降低了刷盘频率
-
redo日志占用的空间非常小
2. 特点
-
redo日志是顺序写入磁盘的
-
事务执行过程中,redo log不断记录
redo的组成
Redo log可以简单分为以下两个部分:
-
重做日志的缓冲 (redo log buffer)
,保存在内存中,是易失的。
参数设置:innodb_log_buffer_size:
redo log buffer 大小,默认16M
,最大值是4096M,最小值为1M。
-
重做日志文件 (redo log file)
,保存在硬盘中,是持久的。 -
参数设置:
参数 | 描述 |
innodb_log_group+home_dir | 指定 redo log 文件组所在的路径,默认值为./ ,表示在数据库的数据目录下。MySQL的默认数据目录(var/lib/mysql )下默认有两个名为ib_logfile0 和ib_logfile1 的文件,log buffer中的日志默认情况下就是刷新到这两个磁盘文件中。此redo日志文件位置还可以修改。 |
innodb_log_files_in_group | 指明redo log file的个数,命名方式如:ib_logfile0,ib_logfile1... ib_logfilen。默认2个,最大100个。 |
innodb_flush_log_at_trx_commit | 控制 redo log 刷新到磁盘的策略,默认为1 。 |
innodb_log_file_size | 单个 redo log 文件设置大小,默认值为 48M 。最大值为512G,注意最大值指的是整个 redo log 系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size )不能大于最大值512G。 |
刷盘策略
redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到文件系统缓存
(page cache)或者叫(os cache)中去(这是现代操作系统为了提高文件写入效率做的一个优化),真正的写入会交给系统自己来决定(比如page cache足够大了)。那么对于InnoDB来说就存在一个问题,如果交给系统来同步,同样如果系统宕机,那么数据也丢失了(虽然整个系统宕机的概率还是比较小的)。
针对这种情况,InnoDB给出innodb_flush_log_at_trx_commit
参数,该参数控制 commit提交事务时,如何将 redo log buffer 中的日志刷新到 redo log file 中。它支持三种策略:
-
设置为0
:表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次重做日志的同步) -
设置为1
:表示每次事务提交时都将进行同步,刷盘操作(默认值
) -
设置为2
:表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。
1.4 redo的整体流程
第1步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝
第2步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
第3步:当事务commit时,将redo log buffer中的内容刷新到 redo log file,对 redo log file采用追加写的方式
第4步:定期将内存中修改的数据刷新到磁盘中
Write-Ahead Log(预先日志持久化):在持久化一个数据页之前,先将内存中相应的日志页持久化。
checkpoint
这是真正将数据从缓冲池中写到磁盘中,也提供了几种策略:
查看系统默认的存储引擎:
SHOW VARIABLES LIKE 'default_storage_engine%';
mysql事务的七种传播行为
什么是事务的传播行为:事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
-
PROPAGATION_REQUIRED 表示当前方法必须在一个具有事务的 上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。( 如果被调用端发生异常,那
么调用端和被调用端事务都将回滚)
-
PROPAGATION_SUPPORTS 表示当前方法不必需要具有一个事务 上下文,但是如果有一个事务的话,它也可以在这个事务中运行
-
PROPAGATION_MANDATORY 表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常
-
PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
-
PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。
-
PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常
-
PROPAGATION_NESTED表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中 ,被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同propagation. required的一样