https://note.youdao.com/ynoteshare/index.html?id=53cd90b2a1d930e1f5c7558a3f595696&type=notebook&_time=1655133645036 于航章笔记

设计思想(分层、扩展)

实际上我们的理解的mysql就是存储数据的,我们可以通过可视化工具方便的对mysql进行数据的操作,但是mysql也是一个服务,对于开发mysql的人员来说以及我们后续开发服务时可以学习到的设计思想是分层,以及扩展性,mysql的扩展性主要体现在多种存储引擎的任意使用(可插拔的方式)
查询时小表驱动大表,因为每次表之间的关联操作实际上是IO操作,因此减少IO处理。

服务结构

mysql server的分层:连接层、服务层(分析器、优化器)、存储引擎(事务实现是在该层)、文件存储

其中服务层的Optimizer会对sql做一些优化

存储引擎(MyISAM、INNODB)

存储引擎的设置实际上是基于表的,不同的表可设置不同的存储引擎

为什么选择B+树

mysql的存储引擎都是采用B树的结构,并且使用的都是B+树(B树的改进),其特点就是只有在叶子节点存储数据
那么mysql为什么会选择采用B+树存储?而不使用二叉树、红黑树、hash表
1、使用二叉树带来的问题,要是使用二叉树存储聚簇索引(主键索引)的话,并且要是递增的情况下,那么二叉树就成了链表的形式了,查询效率就非常慢了。
2、红黑树:虽然是自平衡的二叉树,但是由于每一个节点都是存储的一个数据,那么对于要是存储大数据量时,I/O操作的次数也是会非常多的
3、hash表:存在hash冲突,更重要的是hash表存储的话不支持范围查找,因为存储在hash桶中的数据就是按照hash值存储的,没有任何的规则,所以要是想查询年龄>5的数据,有可能在不同的桶中都有。
4、B+树:采用页存储的方式,一个节点或者说是一次I/O操作会查询出多个数据

B-Tree和B+树的区别

相同点: 每个节点都会使用磁盘页的方式,可以存储多个数据
不同点:1、B树不光是在叶子节点存储数据,也可以在非叶子节点存储数据,而B+树首先只在叶子节点存储数据,使得每个磁盘页存储的页指针更多(因为少存了数据),因为mysql的存储结构有一个原则就是减少I/O操作。同时对于非叶子节点不存储数据的情况下,mysql会首先将非叶子节点的数据拿到内存。
2、B+树相邻的叶子节点间也会存储指向下一相邻叶子节点的指针;这样的话方便了范围查找,由于B+树是顺序的,所以在查找时,要是叶子节点有指针,可以继续往后找了,否则对于不在一个磁盘页的数据还需要从根节点重新遍历找。
3、B+树中页存储数据有重复值(冗余),但是B树没有重复值
4、对于千万级的数据,B+树的高度可控制在3层内,并且每个叶子节点的高度是相同的

MyISAM和INNODB的B+Tree的对比

其中存储引擎有很多种,比较常用的是MyISAM、INNODB(5.5之后默认的)

myISAM

INNODB

两个存储引擎B+树存储数据的区别

对比项 MyISAM INNODB
维护的表数量 frm文件:存储的是建表的语句,myI :存储的是索引文件,myd:存储的是真实的文件。索引文件和数据文件是分离的 frm还是建表语句,idb:索引和数据
叶子节点存储内容 主键索引/普通索引叶子节点都是存储的磁盘地址 主键索引存储了一整行数据;普通索引存储了索引值同时存储了主键值

解释:存储的磁盘地址,主要依赖于数据的存储位置,要是存储位置变了,磁盘地址就需要改变,但是存储的是主键值时,不管数据的实际存储位置如何改变,都不会影响索引的调整。
MyISAM 的B+树只存储磁盘地址,这样不管查询的内容是否是索引内容,都需要再根据指针查询真正的数据,而INNODB要是在查询的字段或者排序的字段是索引列时,只需要在索引文件中查询就可以得到数据,只有查询索引列以外的字段,才需要根据主键索引去数据文件中找。

常见问题

  • 什么是回表
    在非聚簇索引下通过主键到聚簇索引中查询数据的过程

  • 为什么INNODB表建议都要创建一个主键索引?
    因为INNDB底层存储索引的结构就是使用B+树,因为在构建B+树的时候终归是要找到一个基点,要是不创建主键索引的话,mysql会自己找到一列不重复的作为唯一索引处理,要是所有列都没有完全不重复的数据,那么mysql就会自动的创建一列,自增

  • 为什么建议使用整型自增?
    在构建B+树时,总会有数据的比较,因为B+树是要构建成有序的,字符串的比较还要转换为ASCII码,显然整数的比较要比字符串快;自增的主要是为了防止页分裂

数据库的存储结构-页

磁盘与内存交互基本单位:页

InnoDB将数据划分为若千个页,InnoDB中页的大小默认为16KB。
以页作为磁盘和内存之间交互的基本单位

  • 也就是一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。
  • 也就是说,在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载。
  • 也就是说,数据库管理存储空间的基本单位是页(Page) ,数据库I/O操作的最小单位是页。一个页中可以存储多个行记录。
    数据库中不光是有页,还有区、段、表空间的概念。数据库是由多个表空间组成的,每个表空间又是由多个段组成的,每个段是由多个区组成的,每个区是由连续的64个页组成的,每个页大小默认为16KB。

页的结构

索引

索引分类

聚簇索引、非聚簇索引、唯一索引、联合索引、单值索引、覆盖索引、前缀索引

sql性能分析(explain)

正常的sql select * from a where XX前添加explain关键字就可以对该条sql进行性能分,执行结果如下字段:
explain 关键字-mysql的解释执行,可以用此来分析sql的效率,其结果为:
id、select_type、table 、type 、possiable_keys、key、key_len、ref、rows、extra
id参数主要是用来判断一条多表查询sql,执行的先后顺序
id 相同时,表的执行顺序是从上到下
id不同时,id值越大的,越先执行,优先级越大

select_type 指明select的类型:simple、primary、subquery、derived(衍生 from结构的子查询)、union、union result

type 指明索引的级别:级别从大到小
system>const>eq_ref>ref>range>index>all(全表扫描),还会有Index_merge(同一张表中对多个索引做的优化处理)
在分析sql时,至少要达到ref、range
ref :使用索引并查询出多条数据,eq_ref:使用索引只查询出一条数据,一般都是唯一索引
between > < in like‘a%’等级别是range
index虽然也是全表扫描,但是其走的是索引,all走的是硬盘

extra 其他比较重要的属性
Using filesort(不好):一般在使用了order by /group by 时,会出现该属性,该属性表明sql在执行的时候进行内部排序了,一般情况就是在使用复合索引的时候,最好是按照顺序和个数同时使用,比如复合索引共有3个字段,where 1= order by 3(执行时有Using filesort),但是where 1= order 2,3(无Using filesort)
说明:order可以结合where 条件共同使用复合索引,group by和order by 基本是一样的,group by在分组时首先做了排序,然后又进行的分组
Using temporary(不好):一般在使用group by 的时候,要是没有完全按照复合索引的顺序,不但会引来Using filesort,也会引来Using temporary,都是比较影响性能的。
Using index(好事):使用到覆盖索引的就会有该参数,什么是覆盖索引,就是select d的字段是复合索引(或者是复合索引的部分,顺序可不一致,索引type=index),但是要求是复合索引的字段数量一定要>=select的字段数量才叫覆盖索引,因此这也是select 时候尽量不要使用*的其中一个原因
特殊说明下:在对于多表关联查询时,比如使用的join语句,那么关联条件需要建索引的时候,在从表建索引会生效,否则索引不生效。
union 不光有合并的作用,同时还有去重的作用

索引失效场景

执行了explain的语句,一般情况下通过type,key,extra等字段就可以看sql是否走索引,同时key_len可以判断索引使用字段的个数,一般情况下,使用的查询条件越多,key_len的值越大
索引失效的原因:

1)like:查询条件中有like的,要是like的索引生效,如:like ‘ab%’,则type类型是range,但是和>不同的是,>也是range ,但是>后面的查询条件不走索引了,但是like ‘ab%’ 自身和like后面的都会走索引的。要是使用like ‘%ab’,那个like自身的条件也不走索引了,并且后面的也不走了,sql最终是否走索引需要看like 之前的条件是否使索引。
2)where 条件后的查询条件顺序可以不和索引顺序完全一致,mysql会自动将顺序排好,mysql在执行的时候会有优化器将sql进行优化,同时不会引来Using filesort。
3)一条sql在执行的时候,可能会使用到多个索引,在对于同一张表的多个索引时,会出现索引合并的情况,不同表中是不会合并的,要是出现索引合并的情况type属性写的是Index_merge,key也会列举出所有使用到的索引。
4)in 是可以正常走索引的,type = range,但是not in不走索引了,所以在使用not in时可以使用not exists替换
5)关于使用in还是exists的区别:
“外层查询表小于子查询表,则用exists,外层查询表大于子查询表,则用in,如果外层和子查询表差不多,则爱用哪个用哪个。”
6)使用is null 或者是is not null 会导致索引失效,所以我们在创建表结构的时候尽量要定义为非null,并且要设置默认值,同时对于库表中可为null的字段,在存储的时候也会额外占用空间,使用bit位进行存储。

如何正确的创建索引

1)索引是排序好的快速查询的数据结构,不光是应用于查询,还用于排序
2)在更新操作的时候有索引会影响效率,因为mysql不光要维护数据,还要维护索引,要是做更新操作,索引文件就会重新生成

索引下推(ICP)

介绍

介绍
Index Condition Pushdown(ICP)是MySQL 5.6中新特性,是一种在存储引擎层使用索引过滤数据的优化方式。索引下推的下推其实就是指将部分上层(服务层)负责的事情,交给了下层(引擎层)去处理。索引下推的目的是为了减少回表操作

使用场景

Join详细用法

join分为inner join、left join、right join、full join,在进行join时首先遵从2个原则,一个是用小结果集的表作为驱动表,另外一个就是尽量在被驱动表关联字段上添加索引
join连接多个表有不同的方式,但本质都是各个表之间数据的循环匹配。MySQL5.5 版本之前,MySQL只支持一种表间关联方式,就是嵌套循环(Nested Loop Join)。如果关联表的数据量很大,则join关联的执行时间会非常长。在MySQL5.5以后的版本中,MySQL通过引入BNLJ算法来优化嵌套执行。

inner join

mysql的优化器在进行inner join时,首先会优化使用哪张表作为驱动表,哪张作为被驱动表,原则:小表作为驱动表

left join/right join

前面的表作为驱动表

嵌套循环(Nested-Loop)

嵌套循环主要做的操作就是用驱动表,匹配被驱动表

简单嵌套循环

索引嵌套循环

要求:为了减少内表数据的匹配次数,在被驱动表中的关联条件上建立索引

块嵌套循环

小结

数据库事务

数据库事务四大特性(ACID)


说明:一致性是事务的最终目标,而隔离性是事务要达到目标的手段,原子性是对一个事务的简单说明

ACID是如何实现的

AICD主要是通过InnoDb存储引擎的不同日志保证的,同时mysql的binlog日志也有一定的作用
A(原子性):undo log,要是事务需要回滚,执行undo log的数据即可,这里当前事务执行前一版数据
C(一致性):最终目标,由其他三个特性决定
I(隔离性):MVCC+锁决定
D(持久性):内存+redo log日志(commit标志)+binlog

事务的隔离级别



mysql默认使用的是rr,oracle默认是rc
更正下,幻读是两次读取结果集的行数发生了改变,多了或者少了

幻读的解决办法(快照读-MVCC,当前读-Next-Key Lock)

幻读的解决办法:https://www.cnblogs.com/xuwc/p/13873293.html

sql读取分为当前读和快照读,而mvcc是在快照读的情况下解决了幻读,但是在当前读的情况下需要通过间隙锁+行锁解决幻读
1)a事务两次select,b事务insert,由于readview的原因可以使得两次select结果相同。
2)再就可以利用当前读也可以做到,select update select ,另外一个事务insert,要是update的操作可以产生间隙锁,并且insert的恰好是间隙锁间数据,会导致a事务提交前,insert被阻塞
出现幻读的情况:
1、select (insert) update(由于是当前读,获取的是最新数据,并且在修改后将那条数据的事务ID修改成当前事务) select
当前读:
select * for update
select * lock in share mode
insert delete update
对于范围条件筛选的,可以通过间隙锁方法阻止insert等操作
对于单条件的查询要是唯一索引查询,那么使用的行锁,要是非唯一索引则是使用的间隙锁。
mvcc是多版本并发控制,主要是将版本链+readview(是一组活跃事务的id),mysql在事务开启的时候,认为就会产生readview,并且在当前事务没有结束时始终使用的都是同一个readview。而快照读依赖的就是这个readview,当我们要去访问一条数据时,首先会判断该条数据记录的最大的事务ID,然后拿该值和readview中的事务ID进行比较,要是在readview的左边说明是当前事务开始前已经完成的事务,可以对该条数据进行访问。要是在readview中或者是在这之后说明在当前事务开始之后,有别的事务对该条数据进行过修改,所以就要访问这条数据上一个版本的信息。至于多个版本的生成,实际上个人理解应该是该条数据的主键是不变的,不然无法定位到这条数据。

日志文件(redo.log,undo.log,bin.log)

redo log叫做重做日志,是保证事务持久性的重要机制。当mysql服务器意外崩溃或者宕机后,保证已经提交的事务,确定持久化到磁盘中的一种措施。

binlog和redolog的区别

  • redo log它是物理日志,是在事务执行过程中一直会记录的,记录内容是“在某个数据页上做了什么修改”,属于InnoDB存储引擎层产生的。
  • 而binlog是逻辑日志,只有在事务提交时才会写入binlog,记录内容是语句的原始逻辑,类似于“给ID=2这一行的c字段加1”, 属于MySQL Server层
  • 虽然它们都属于持久化的保证,但是则重点不同。
    redo log让InnoDB存储引擎拥有了崩溃恢复能力。
    binlog 保证了MySQL集群架构的数据一致性。主要是做主从复制的

如何确保数据恢复时数据不一致问题

mysql采用两阶段提交的方式,预防数据恢复时数据不一致的问题

数据库锁

读锁和写锁(表级别锁)

对于当前事务来说,读锁和写锁都是从权限上有限定的。
1、两种锁对锁表的事务有不同的权限,读锁只能读锁定表,写锁可以读写锁定表
2、不管是读锁还是写锁对于当前在使用锁的事务,都不可以对其他表做任何操作

从别的事务的操作来看,只对上锁的表会出现阻塞的情况,其他没有上锁的表是可以正常访问的。读锁是共享锁,可以读不可写,写锁是排他锁,读写都不可以

总结:读锁会阻塞写,写锁会阻塞读写,myISAM在进行查询操作前都会加上读锁,在进行更新操作时都会记上写锁
show open tables;–查看哪些表被锁,0-未锁,1-锁

行锁

MyISAM支持表锁,INNODB支持行锁,一般也都是给更新语句加行锁,要是给select语句加行锁的话,需要手动的添加for update,注意:对于行锁使用不当的情况下,会升级为表锁

间隙锁

在进行范围更新/select for update的时候,那么会产生间隙锁,间隙锁的范围是按照当前列的实际value值,(n,X)X为本次查询条件,n为上一个最近的value值,即使不存在的列也会上锁,那么此时你要操作该值的数据会产生阻塞。例:主键数据有1 3 4,更新时条件为>=1 and <=3,此时虽然没有2,但是也会产生间隙锁,要是insert 2时就会有阻塞了。或者select * from table where id = 3 for update;此时会产生间隙锁,insert 2时也会阻塞。

sql执行过程

查看缓存

  • MySQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以key-value对的形式,被直接缓存在内存中。key 是查询的语句, value 是查询的结果。如果你的查询能够直接在这个缓存中找到key,那么这个value就会被直接返回给客户端。如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后, 执行结果会被存入查询缓存中。所以,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。
  • 此外,既然是缓存,那就有它缓存失效的时候。MySQL的缓存系统会监测涉及到的每张表,只要该表的结构或者数据被修改,如对该表使用了INSERT、UPDATE、 DELETE、 TRUNCATE TABLE TABLE或DROP DATABASE 语句,那使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除!对于更新.压力大的数据库来说,查询缓存的命中率会非常低。
    总之,因为查询缓存往往弊大于利,查询缓存的失效非常频繁。

服务层分析器(词法分析和语法分析)

如果没有命中查询缓存,就要开始真正执行语句了。MySQL 需要知道你要做什么,因此需要对SQL语句做解析。
SQL语句的分析分 为词法分析与语法分析。

  • 分析器先做“词法分析”。你输入的是由多个字符串和空格组成的一条SQL语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。MySQL从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名T”,把字符串“ID”识别成“列ID”。
  • 接着,要做“语法分析”。根据词法分析的结果,语法分析器(比如: Bison) 会根据语法规则,判断你输入的这个SQL语句是否满足MySQL 语法。
    如果你的语句不对,就会收到“You have an error in your SQL syntax’的错误提醒,比如下面这个语句from写成了“rom”
    如果SQL语句正确会生成语法树:

    语法树在后面被回滚的时候会用到

服务层优化器

  • 一条查询可以有很多种执行方式,最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。比如:优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join) 的时候,决定各个表的连接顺序,还有表达式简化、子查询转为连接、外连接转为内连接等。
  • 在查询优化器中,可以分为逻辑查询优化阶段和物理查询优化阶段。
  • 逻辑查询优化就是通过改变SQL语句的内容来使得SQL查询更高效,同时为物理查询优化提供更多的候选执行计划。通常采用的方式是对SQL语句进行等价变换,对查询进行重写,而查询重写的数学基础就是关系代数。对条件表达式进行等价谓词重写、条件简化,对视图进行重写,对子查询进行优化,对连接语义进行了外连接消除、嵌套连接消除等。
  • 物理查询优化是基于关系代数进行的查询重写,而关系代数的每-步都对应着物理计算, 这些物理计算往往存在多种算法,因此需要计算各种物理路径的代价,从中选择代价最小的作为执行计划。在这个阶段里,对于单表和多表连接的操作,需要高效地使用索引,提升查询效率。

执行器

  • 执行器这里主要操作是先记录undo.log日志,然后执行sql(要是在8之前有缓存的情况,再将查询的结果放在缓存中一份),再记录redolog日志,最后记录binlog日志,完成事务提交

数据库缓冲池-Buffer Pool

重要性及作用(减少IO)

InnoDB存储弓|擎是以页为单位来管理存储空间的,我们进行的增删改查操作其实本质上都是在访问页面(包括读页面、写页面、创建新页面等操作)。而磁盘I/O需要消耗的时间很多,而在内存中进行操作,效率则会高很多,为了能让数据表或者索引中的数据随时被我们所用,DBMS会申请占用内存来作为数据缓冲池,在真正访问页面之前,需要把在磁盘上的页缓存到内存中的Buffer Pool 之后才可以访问。
这样做的好处是可以让磁盘活动最小化,从而减少与磁盘直接进行I/O 的时间。要知道,这种策略对提升SQL语句的查询性能来说至关重要。如果索引的数据在缓冲池里,那么访问的成本就会降低很多。

原则(减少IO提高效率)

  • 位置决定效率,提供缓冲池就是为了在内存中可以直接访问数据
  • 频次决定优先级顺序。因为缓冲池的大小是有限的,比如磁盘有200G,但是内存只有16G,缓冲池大小只有1G,就无法将所有数据都加载到缓冲池里,这时就涉及到优先级顺序,会优先对使用频次高的热数据进行加载

刷盘机制(checkpoint)

实际上,当我们对数据库中的记录进行修改的时候,首先会修改缓冲池中页里面的记录信息,然后会以一定的频率刷新到磁盘上。注意并不是每次发生更新操作,都会立刻进行磁盘回写。缓冲池会采用一种叫做checkpoint的机制将数据回写到磁盘上,这样做的好处就是提升了数据库的整体性能。
比如,当缓冲池不够用时,需要释放掉一些不常用的页,此时就可以强行采用checkpoint的方式,将不常用的脏页回写到磁盘上,然后再从缓冲池中将这些页释放掉。这里脏页(dirty page)指的是缓冲池中被修改过的页,与磁盘上的数据页不一致。

#查看缓存池大小 默认大小128M
show variables like 'innodb_buffer_pool_size';
#修改缓存大小
set global innodb_buffer_pool_size = number;
#或者修改配置文件,重启mysql
[server]
innodb_buffer_pool_size = number;

多实例

Buffer Pool本质是InnoDB向操作系统申请的一块连续的内存空间,当缓存池的大小>1G时,建议将实例调大,默认为1,因为数据量变大或者并发访问量高时,要是只有一个实例,会影响访问效率的,但是也不是越多越好,适当即可

#查看实例个数
show variables like 'innodb_buffer_pool_instances';
#或者修改配置文件,重启mysql
[server]
innodb_buffer_pool_instances = 2;

主从复制(同步)

对于mysql来说,最主要是配置文件,windows下是mysql.ini,linux下是mysql.cnf

要求:1、主从数据库版本一致
2、必须是同一网段,最起码能ping通

搭建主从数据库

1、修改主库配置文件
必填的就是server-id = 1 (一般情况下主的都设置为1)
log-bin = 设置自己的数据库data目录/mysqlbin
2、修改从库配置文件
server-id = 2
log-bin = mysql-bin (该值尽量不要修改)
3、由于配置文件都修改过,所以重启服务
4、master、slave都关闭防火墙
5、master上建立账号授权给slave,直接用mysql的命令行执行

show master status; – 查看主机的状态,重要的两个参数就是file和position,这里是作为同步的位置,需告知slave

6、slave 连接master做同步

start slave;
show slave status:
show-IO,show-sql 必须同时为YES,否则会导致同步失败
7、接下来正常在master上做操作即可,自动会同步到slave

数据库的备份和恢复

  • 1、手动的备份,直接将数据存储位置的文件进行复制操作,在Linux下数据库文件的存放目录一般为/var/lib/mysql
    备份文件前,需要将MySQL服务停止,然后将数据库目录拷贝即可
  • 2、使用命令行工具

数据备份 : mysqldump –user=root –password=root密码 –lock-all-tables 数据库名 > 备份文件.sql
数据恢复:mysql -u root –password=root密码 数据库名 < 备份文件.sql

sql函数使用注意事项

concat(str,substr) 字符串拼接

当str为null时,不能成功拼接,因此拼接时需要使用IFNULL()判断下

locate(substr,str) 判断子串是否包含

str为数据库中字段名称,substr就是要判断的字符串,若str字段中不包含substr的值则返回0,若包含则返回1,但需要注意当str(数据库字段)为null时,返回null

常用指令

# 查看字符集
show variables like '%char%';
# 查看当前数据库的存储引擎
show variables like '%storage_engine%';
# 查询页大小,默认是16KB
show variable like '%innodb_page_size%';
# 查看某张表的索引
show index from hcm_person;
# 查看表字段定义
desc f_work_permit_info;
# 查询慢日志是否开启
show variables like '%slow_query_log%';
# 查询慢查询日志的阈值
show variables like '%long_query_time%';
# 查询事务隔离级别
show variables like 'tx_isolation';
# 查询当前存在行锁的事务数量,以及总的等待次数
show status like 'innodb_row_lock%';
# 查询当前存在表锁的事务数量,以及总的等待次数
show status like 'table%';
#mysql 查询等待锁
select * from information_schema.innodb_trx where trx_state='LOCK_WAIT';

慢sql查询

  • 1、检查慢sql日志是否开启,以及慢sql的阈值,可直接在查询
    查询慢日志是否开启
    show variables like ‘%slow_query_log%’;
    查询慢查询日志的阈值
    show variables like ‘%long_query_time%’;
  • 2、要是测试环境中,慢sql的情况也比较少,可以直接查看上面查询到的慢sql日志记录;但是对于生产中或者比较大量的sql时,就需要依赖mysql提供的工具
    实际使用:

sql优化

子查询优化

由于子查询会将子查询的查询结果生成一张临时表,并且要是对于大结果集查询来说,性能都会收到影响,因此建议使用join连接替换子查询

排序优化

  • 排序时也会走到索引,比如建一个联合索引时,可以结合where条件一起使用,但是需要注意的是排序时避免引入filesort
  • 不加limit,索引失效

group by 优化

  • group by使用索引的原则几乎跟order by一致,group by即使没有过滤条件用到索引,也可以直接使用索引。
  • group by先排序再分组,遵照索引建的最佳左前缀法则。
  • 当无法使用索引列,增大max_length_for_sort_data 和sort_buffer_size参数的设置。
  • where效率高于having,能写在where限定的条件就不要写在having中了。
  • 减少使用order by,和业务沟通能不排序就不排序,或将排序放到程序端去做。Order by、group by、distinct这些语句较为耗费CPU,数据库的CPU资源是极其宝贵的。
  • 包含了order by: group by、distinct这些查询的语句, where条件过滤出来的结果集请保持在1000行以内,否则SQL会很慢。

建表设计

  • 根据要求选择合适的数据库,比如选择mysql还是oracle,再次选择好存储引擎,要是支持事务的选择Innodb,要是不选择事务的可以使用MyISAM
  • 建表时尽量遵从数据库三范式,适当冗余字段
  • 合理创建索引,避免全表查询,或者是行锁升级为表锁。定义数据类型尽量使用数值型,要是使用字符型,尽量按照长度指定大小

数据库结构

  • 采用读写分离方式(一般是在千万级以上)
  • 分库分表(mysql自带的分库分表功能,垂直分表、水平分表、垂直+水平)
  • 数据库参数设置(DBA的工作),注意修改后需要重启
  • 结合缓存
  • 冷热数据分离(历史表)
  • 避免全表查询

Mysql数据库高级、sql优化相关推荐

  1. MySQL数据库高级SQL语句(三)

    MySQL数据库高级SQL语句 SELECT TRIM 连接查询 CREATE VIEW UNION 交集值 无交集值 CASE SELECT TRIM SELECT TRIM (位置 '想移除掉的字 ...

  2. MySQL数据库与SQL优化

    一.MySQL 数据库与 SQL 优化 1.结构图 二.MySQL 数据库引擎简介 1.ISAM(IndexedSequentialAccessMethod)     ISAM 是一个定义明确且历经时 ...

  3. MySQL数据库:SQL优化与索引优化

    一.索引优化: 1.like语句的前导模糊查询不使用索引: select * from doc where title like '%XX':   --不能使用索引 select * from doc ...

  4. mysql 判断字段为null表示 false 其它为true_日拱一卒,MySQL数据库 常用SQL优化技巧 十一式...

    本文中所提到的SQL优化技巧均是基于Mysql 索引 BTree类型 .将从以下几个方面介绍常用的SQL优化技巧: 避免在 WHERE 子句中使用 != 或 <> 操作符. 避免在 WHE ...

  5. 千万级的mysql数据库与sql优化方法

    http://www.111cn.net/database/110/32932.htm 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应 ...

  6. MySQL数据库高级SQL查询语句(单表查询,多表联合查询)

    目录 SQL查询语句 基础查询 条件查询 模糊查询 字段控制查询 排序 聚合函数 分组查询 having子句 limit分页查询 多表连接查询 SQL查询语句 数据查询语言. 数据库执行DQL语句不会 ...

  7. Mysql数据库以及sql语言

    mysql 安装请点击 mysql下载速度慢请点击 可视化工具请点击(不想用命令行的) mysql和java集成:jdbc mysql 索引的创建以及含义 mysql一般函数的使用(需要一定的sql基 ...

  8. 数据库应用+SQL优化+Git

    数据库应用 1.1 概念 1.1.1 什么是数据库 1.1.2 关系型和非关系型 1.1.3 关系型数据库 1.2 Mysql数据库 1.2.1 MySQL数据存放在哪里? 1.2.2 MySQL服务 ...

  9. 高级SQL优化(二) ——《12年资深DBA教你Oracle开发与优化——性能优化部分》

    目录: Oracle数据完整性和锁机制  索引及优化之表分析  表分析.约束及表间关系  Oracle体系结构1 Oracle体系结构2  海量数据库及分区1  海量数据库及分区2  海量数据库及分区 ...

  10. 高级SQL优化(三) 常用优化工具 ——《12年资深DBA教你Oracle开发与优化——性能优化部分》...

    目录: Oracle数据完整性和锁机制  索引及优化之表分析  表分析.约束及表间关系  Oracle体系结构1 Oracle体系结构2  海量数据库及分区1  海量数据库及分区2  海量数据库及分区 ...

最新文章

  1. python berkeley 操作——尤其提示 需版本匹配
  2. Jacobian矩阵和Hessian矩阵的理解
  3. Scala-Spark digamma stackoverflow问题
  4. JAVA单向链表实现
  5. 线性动态电路的复频域分析
  6. python多个判断条件体重_python基础之如何用if语句判断多个条件?
  7. LeetCode 1114. 按序打印
  8. undefined reference to 'modbus_new_tcp'
  9. c语言练习题库网站,c语言练习题库网站_0.doc
  10. oracle支持sha256加密算法,Sha256 加密算法
  11. 【无标题】Access control configuration prevents your request from being allowed at this time.
  12. 《VR/AR技术与应用》笔记 001
  13. SDK完整环境下载安装及ADB常用命令
  14. 使用opencv的viz模块显示3d点云
  15. 论坛mysql cpu100_解决 MYSQL CPU 占用 100% 的经验总结
  16. 众所周知的广告屏蔽神器uBlock/Adguard,为啥你装上后和没装一样?
  17. Linux利用filename=${fileuser:-filename}设置文档名
  18. 石膏板建筑材料英国UKCA认证—EN 520
  19. linux如何开放端口和关闭端口
  20. Unity-奥义技能背景变黑效果

热门文章

  1. vscode暂存的代码保存在哪里_在vs code中配置git,便于代码的保存
  2. Greenplum创建表空间
  3. android动态设置imageview大小,ImageView动态设置宽高
  4. 科学上网后之后无法正常连接网络
  5. T1500,T1522,T3266,T1279
  6. 【面经】联想大数据开发面经
  7. web端原生js实现全屏和退出全屏(F11功能)
  8. Linux下去掉^M的方法
  9. 最详细的Android图片压缩攻略,让你一次过足瘾
  10. wrs-jpush极光推送原生app插件