MySQL常见面试题汇总(建议收藏!!!)(二)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 笔记

三、锁相关


(1)对 MySQL 的锁了解吗?

当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制.


就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用.


(2)MySQL 锁的分类

Mysql中锁的分类按照不同类型的划分可以分成不同的锁:


按照 锁的粒度 划分可以分成:


行锁

表锁

页锁

按照 使用的方式 划分可以分为:


共享锁

排它锁

按照 思想 的划分:


乐观锁

悲观锁


(3)行级锁、表级锁、页级锁的描述与特点

行级锁:


描述:行级锁是mysql中锁定粒度最细的一种锁。表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁

特点:开销大,加锁慢,会出现死锁。发生锁冲突的概率最低,并发度也最高。

表级锁:


描述:表级锁是mysql中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)

特点: 开销小,加锁快,不会出现死锁。发生锁冲突的概率最高,并发度也最低。

页级锁:


描述:页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。BDB 支持页级锁。


特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。


(4)共享锁 、 排他锁的描述

共享锁:


描述:


共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。

如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。

用法:


SELECT … LOCK IN SHARE MODE;

在查询语句后面增加LOCK IN SHARE MODE,MySQL 就会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。

排他锁:


描述:

排他锁又称写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。

用法:

SELECT … FOR UPDATE;

在查询语句后面增加FOR UPDATE,MySQL 就会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。

用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的. 一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以.


(5)悲观锁与乐观锁

乐观锁(Optimistic Lock):假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁不能解决脏读的问题。

乐观锁, 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。


悲观锁(Pessimistic Lock):假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。

悲观锁,顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。


(6)数据库悲观锁和乐观锁的原理和应用场景分别有什么?

悲观锁,先获取锁,再进行业务操作,一般就是利用类似 SELECT … FOR UPDATE 这样的语句,对数据加锁,避免其他事务意外修改数据。当数据库执行SELECT … FOR UPDATE时会获取被select中的数据行的行锁,select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。


乐观锁,先进行业务操作,只在最后实际更新数据时进行检查数据是否被更新过。Java 并发包中的 AtomicFieldUpdater 类似,也是利用 CAS 机制,并不会对数据加锁,而是通过对比数据的时间戳或者版本号,来实现乐观锁需要的版本判断。


(7)MySQL常用存储引擎的锁机制?

MyISAM和MEMORY采用表级锁(table-level locking)

BDB采用页面锁(page-level locking)或表级锁,默认为页面锁

InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁


(8)InnoDB 存储引擎有几种锁算法?

Record Lock — 单个行记录上的锁;

Gap Lock — 间隙锁,锁定一个范围,不包括记录本身;

Next-Key Lock — 锁定一个范围,包括记录本身。


(9)什么是死锁?

是指二个或者二个以上的进程在执行时候,因为争夺资源造成相互等待的现象,进程一直处于等待中,无法得到释放,这种状态就叫做死锁。


(10)死锁出现的案列?

批量入库,存在则更新,不存在则插入,insert into tab(xx,xx) on duplicate key update xx=‘xx’。


(11)如何处理死锁?

通过innodblockwait_timeout来设置超时时间,一直等待直到超时

发起死锁检测,发现死锁之后,主动回滚死锁中的事务,不需要其他事务继续


(12)如何避免死锁?

为了在单个innodb表上执行多个并发写入操作时避免死锁,可以在事务开始时,通过为预期要修改行,使用select …for update语句来获取必要的锁,即使这些行的更改语句是在之后才执行的

在事务中,如果要更新记录,应该直接申请足够级别的锁,即排他锁,而不应先申请共享锁,更新时在申请排他锁。因为这时候当用户在申请排他锁时,其他事务可能又已经获得了相同记录的共享锁

如果事务需要修改或锁定多个表,则应在每个事务中以相同的顺序使用加锁语句。在应用中,如果不同的程序会并发获取多个表,应尽量约定以相同的顺序来访问表,这样可以大大降低产生死锁的机会

通过 select …lock in share mode获取行的读锁后,如果当前事务在需要对该记录进行更新操作,则很有可能造成死锁

改变事务隔离级别


(13)Innodb默认是如何对待死锁的?

innodb默认是使用设置死锁时间来让死锁超时的策略,默认innodblockwait_timeout设置的时长是50s


(14)如何开启死锁检测?

设置innodbdeadlockdetect设置为on可以主动检测死锁,在innodb中这个值默认就是on开启的状态


(15)什么是全局锁?它的应用场景有哪些?

全局锁就是对整个数据库实例加锁,它的典型使用场景就是做全库逻辑备份,这个命令可以使用整个库处于只读状态,使用该命令之后,数据更新语句,数据定义语句,更新类事务的提交语句等操作都会被阻塞。


(16)使用全局锁会导致的问题?

如果在主库备份,在备份期间不能更新,业务停止,所以更新业务会处于等待状态

如果在从库备份,在备份期间不能执行主库同步的binlog,导致主从延迟


(17)优化锁方面你有什么建议?

尽量使用较低的隔离级别。

精心设计索引, 并尽量使用索引访问数据, 使加锁更精确, 从而减少锁冲突的机会。

选择合理的事务大小,小事务发生锁冲突的几率也更小。

给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁。

不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会。

尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响。

不要申请超过实际需要的锁级别。

除非必须,查询时不要显示加锁。 MySQL 的 MVCC 可以实现事务中的查询不用加锁,优化事务性能;MVCC 只在 COMMITTED READ(读提交)和 REPEATABLE READ(可重复读)两种隔离级别下工作。

对于一些特定的事务,可以使用表锁来提高处理速度或减少死锁的可能。


四、存储引擎相关


(1)MySQL 支持哪些存储引擎?

MySQL 支持多种存储引擎,比如InnoDB,MyISAM,Memory,Archive等等。在大多数的情况下,直接选择使用 InnoDB 引擎都是最合适的,InnoDB 也是 MySQL 的默认存储引擎。


(2)InnoDB 和 MyISAM 有什么区别?

InnoDB


是 MySQL 默认的事务型存储引擎,只有在需要它不支持的特性时,才考虑使用其它存储引擎。

实现了四个标准的隔离级别,默认级别是可重复读(REPEATABLE READ)。在可重复读隔离级别下,通过多版本并发控制(MVCC)+ 间隙锁(Next-Key Locking)防止幻影读。

主索引是聚簇索引,在索引中保存了数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。

内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够加快读操作并且自动创建的自适应哈希索引、能够加速插入操作的插入缓冲区等。

支持真正的在线热备份。其它存储引擎不支持在线热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。

MyISAM


设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用它。

提供了大量的特性,包括压缩表、空间数据索引等。

不支持事务。

不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入(CONCURRENT INSERT)。

总结:


InnoDB 支持事物,而 MyISAM 不支持事物

InnoDB 支持行级锁,表锁,而 MyISAM 支持表级锁

InnoDB 支持 MVCC,而 MyISAM 不支持

InnoDB 支持外键,而 MyISAM 不支持

InnoDB5.7之前不支持全文索引,而 MyISAM 支持

nnoDB必须有主键,没有指定会默认生成一个隐藏列作为主键,而MyISAM可以没有


(3)你了解MySQL的内部构造吗?一般可以分为哪两个部分?

可以分为服务层和存储引擎层两部分,其中:


服务层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。


存储引擎层负责数据的存储和提取。 其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB,它从MySQL5.5.5版本开始成为了默认的存储引擎。

30.png

(4)说一下MySQL是如何执行一条SQL的?具体步骤有哪些?

Server层按顺序执行sql的步骤为:

1.客户端请求->
2.连接器(验证用户身份,给予权限) ->
3.查询缓存(存在缓存则直接返回,不存在则执行后续操作)->
4.分析器(对SQL进行词法分析和语法分析操作) ->
5.优化器(主要对执行的sql优化选择最优的执行方案方法) ->
6.执行器(执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口)->
7.去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)

简单概括:


连接器:管理连接、权限验证;

查询缓存:命中缓存则直接返回结果;

分析器:对SQL进行词法分析、语法分析;(判断查询的SQL字段是否存在也是在这步)

优化器:执行计划生成、选择索引;

执行器:操作引擎、返回结果;

存储引擎:存储数据、提供读写接口。


(5)SQL 的执行顺序?

SELECT DISTINCT
    < select_list >
FROM
    < left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
    < where_condition >
GROUP BY
    < group_by_list >
HAVING
    < having_condition >
ORDER BY
    < order_by_condition >
LIMIT < limit_number >

它的执行顺序你知道吗?这道题就给你一个回答。


FROM 连接


首先,对 SELECT 语句执行查询时,对FROM 关键字两边的表执行连接,会形成笛卡尔积,这时候会产生一个虚表VT1(virtual table)


ON 过滤


然后对 FROM 连接的结果进行 ON 筛选,创建 VT2,把符合记录的条件存在 VT2 中。


JOIN 连接


第三步,如果是 OUTER JOIN(left join、right join) ,那么这一步就将添加外部行,如果是 left join 就把 ON 过滤条件的左表添加进来,如果是 right join ,就把右表添加进来,从而生成新的虚拟表 VT3。


WHERE 过滤


第四步,是执行 WHERE 过滤器,对上一步生产的虚拟表引用 WHERE 筛选,生成虚拟表 VT4。


GROUP BY


根据 group by 字句中的列,会对 VT4 中的记录进行分组操作,产生虚拟机表 VT5。果应用了group by,那么后面的所有步骤都只能得到的 VT5 的列或者是聚合函数(count、sum、avg等)。


HAVING


紧跟着 GROUP BY 字句后面的是 HAVING,使用 HAVING 过滤,会把符合条件的放在 VT6


SELECT


第七步才会执行 SELECT 语句,将 VT6 中的结果按照 SELECT 进行刷选,生成 VT7


DISTINCT


在第八步中,会对 TV7 生成的记录进行去重操作,生成 VT8。事实上如果应用了 group by 子句那么 distinct 是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所以的记录都将是不相同的。


ORDER BY


应用 order by 子句。按照 order_by_condition 排序 VT8,此时返回的一个游标,而不是虚拟表。sql 是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。


SQL 语句执行的过程如下:31.png

(6)简述触发器、函数、视图、存储过程?

触发器:使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为,触发器无法由用户直接调用,而知由于对表的【增/删/改】操作被动引发的

函数:是MySQL数据库提供的内部函数(当然也可以自定义函数)。这些内部函数可以帮助用户更加方便-的处理表中的数据

视图:视图是虚拟表或逻辑表,它被定义为具有连接的SQL SELECT查询语句。

存储过程:存储过程是存储在数据库目录中的一坨的声明性SQL语句,数据库中的一个重要对象,有效提高了程序的性能

(6)听说过视图吗?那游标呢?

视图是一种虚拟的表,通常是有一个表或者多个表的行或列的子集,具有和物理表相同的功能 游标是对查询出来的结果集作为一个单元来有效的处理。


一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。


(6)视图的作用是什么?可以更改吗?

视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询;不包含任何列或数据。使用视图可以简化复杂的 sql 操作,隐藏具体的细节,保护数据;视图创建后,可以使用与表相同的方式利用它们。


视图不能被索引,也不能有关联的触发器或默认值,如果视图本身内有order by 则对视图再次order by将被覆盖。


创建视图:

create view xxx as xxxx

对于某些视图比如未使用联结子查询分组聚集函数Distinct Union等,是可以对其更新的,对视图的更新将对基表进行更新;但是视图主要用于简化检索,保护数据,并不用于更新,而且大部分视图都不可以更新。


五、表结构相关


(1)为什么要尽量设定一个主键?

主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的 ID 列作为主键.设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全。


(2)主键使用自增 ID 还是 UUID?

推荐使用自增ID,不要使用 UUID。


因为在 InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降.


总之,在数据量大一些的情况下,用自增主键性能会好一些。


图片来源于《高性能MySQL》: 其中默认后缀为使用自增ID,_uuid为使用 UUID为主键的测试,测试了插入 100w 行和 300w 行的性能。




(3)字段为什么要求定义为not null?

null 值会占用更多的字节,且会在程序中造成很多与预期不符的情况。


(4)如果要存储用户的密码散列,应该使用什么字段进行存储?

密码散列,用户身份证号等固定长度的字符串应该使用 char 而不是 varchar 来存储,这样可以节省空间且提高检索效率。


(5)说一说Drop、Delete与Truncate的共同点和区别?

Drop直接删掉表;

Truncate删除表中数据,再插入时自增长id又从1开始 ;

Delete删除表中数据,可以加where字句。

(6)数据库中的主键、超键、候选键、外键是什么?

超键:在关系中能唯一标识元组的属性集称为关系模式的超键


候选键:不含有多余属性的超键称为候选键。也就是在候选键中,若再删除属性,就不是键了!


主键:用户选作元组标识的一个候选键程序主键


外键:如果关系模式R中属性K是其它模式的主键,那么k在模式R中称为外键。


六、其他问题


(1)MySQL 中的 varchar 和 char 有什么区别?

char 是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用 10 个字符,而 varchar 是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度 +1,最后一个字符存储使用了多长的空间


在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用 char,否则应该尽量使用 varchar。例如存储用户 MD5 加密后的密码,则应该使用 char。


(2)varchar(10) 和 int(10) 代表什么含义?

varchar的10代表了申请的空间长度,也是可以存储的数据的最大长度,而int的10只是代表了展示的长度,不足10位以0填充.也就是说,varchar(10) 和int(10)所能存储的数字大小以及占用的空间都是相同的,只是在展示时按照长度展示.

32.png

(3)MySQL的binlog有有几种录入格式?分别有什么区别?

有三种格式:statement、row和mixed.


statement模式下,记录单元为语句.即每一个sql造成的影响会记录.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制.

row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大.

mixed. 一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row.

(4)超大分页怎么处理?

超大的分页一般从两个方向上来解决.:


数据库层面,这也是我们主要集中关注的(虽然收效没那么大),类似于select * from table where age > 20 limit 1000000,10这种查询其实也是有可以优化的余地的. 这条语句需要load1000000数据然后基本上全部丢弃,只取10条当然比较慢. 当时我们可以修改为select * from table where id in (select id from table where age > 20 limit 1000000,10).这样虽然也load了一百万的数据,但是由于索引覆盖,要查询的所有字段都在索引中,所以速度会很快. 同时如果ID连续的好,我们还可以select * from table where id > 1000000 limit 10,效率也是不错的,优化的可能性有许多种,但是核心思想都一样,就是减少load的数据.

从需求的角度减少这种请求…主要是不做类似的需求(直接跳转到几百万页之后的具体某一页.只允许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连续被人恶意攻击.

(5)说一说三个范式?

第一范式: 每个列都不可以再拆分。

第二范式: 非主键列完全依赖于主键,而不能是依赖于主键的一部分。

第三范式: 非主键列只依赖于主键,不依赖于其他非主键。

在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能,事实上我们经常会为了性能而妥协数据库的设计。


(6)left join、right join以及inner join的区别?

left join:左关联,主表在左边,右边为从表。如果左侧的主表中没有关联字段,会用null 填满

right join:右关联 主表在右边和letf join相反

inner join: 内关联只会显示主表和从表相关联的字段,不会出现null

(7)什么是数据库约束,常见的约束有哪几种?

数据库约束用于保证数据库、表数据的完整性(正确性和一致性)。

可以通过定义约束\索引\触发器来保证数据的完整性。总体来讲,约束可以分为:


主键约束:primary key;

外键约束:foreign key;

唯一约束:unique;

检查约束:check;

空值约束:not null;

默认值约束:default;

(8)什么是sql注入?

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。


(9)简述数据库的读写分离?

读写分离为了确保数据库产品的稳数据定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作。


(10)MySQL数据库cpu飙升的话,要怎么处理呢?

排查过程:


使用top 命令观察,确定是mysqld导致还是其他原因。

如果是mysqld导致的,show processlist,查看session情况,确定是不是有消耗资源的sql在运行。

找出消耗高的 sql,看看执行计划是否准确, 索引是否缺失,数据量是否太大。

处理:


kill 掉这些线程(同时观察 cpu 使用率是否下降),

进行相应的调整(比如说加索引、改 sql、改内存参数)

重新跑这些 SQL。

(11)MYSQL的主从延迟,你怎么解决?

主从复制分了五个步骤进行:

33.png

步骤一:主库的更新事件(update、insert、delete)被写到binlog

步骤二:从库发起连接,连接到主库。

步骤三:此时主库创建一个binlog dump thread,把binlog的内容发送到从库。

步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log

步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db

主从同步延迟的原因:


一个服务器开放N个链接给客户端来连接的,这样有会有大并发的更新操作, 但是从服务器的里面读取binlog的线程仅有一个,当某个SQL在从服务器上执行的时间稍长 或者由于某个SQL要进行锁表就会导致,主服务器的SQL大量积压,未被同步到从服务器里。这就导致了主从不一致, 也就是主从延迟。


主从同步延迟的解决办法:


主服务器要负责更新操作,对安全性的要求比从服务器要高,所以有些设置参数可以修改,比如sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之类的设置等。

选择更好的硬件设备作为slave。

把一台从服务器当度作为备份使用, 而不提供查询, 那边他的负载下来了, 执行relay log 里面的SQL效率自然就高了。

增加从服务器,这个目的还是分散读的压力,从而降低服务器负载。

(12)如果让你做分库与分表的设计,简单说说你会怎么做?

分库分表方案:


水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。

水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。

垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。

垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。

常用的分库分表中间件:


sharding-jdbc

Mycat

分库分表可能遇到的问题:


事务问题:需要用分布式事务

跨节点Join的问题:解决这一问题可以分两次查询实现

跨节点的count,order by,group by以及聚合函数问题:分别在各个节点上得到结果后在应用程序端进行合并。

数据迁移,容量规划,扩容等问题

ID问题:数据库被切分后,不能再依赖数据库自身的主键生成机制,最简单可以考虑UUID

跨分片的排序分页问题

(13)count(1)、count(*)与count(列名)的执行区别

执行效果上 :


count(*):包括了所有的列,相当于行数,在统计结果的时候, 不会忽略列值为NULL

count(1):包括了忽略所有列,用1代表代码行,在统计结果的时候, 不会忽略列值为NULL

count(列名):只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数, 即某个字段值为NULL时,不统计。

执行效率上:


列名为主键,count(列名)会比count(1)快

列名不为主键,count(1)会比count(列名)快

如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*)

如果有主键,则 select count(主键)的执行效率是最优的

如果表只有一个字段,则 select count(*)最优。

(14)sql 语句中where 1=1的作用

SQL注入


语法规范


拷贝表


复制表结构


1=1的坏处


见文章:


https://blog.csdn.net/SeizeeveryDay/article/details/109523669?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-10.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-10.essearch_pc_relevant

(15)sql中null与空值的区别

1.占用空间区别:空值(’’)的长度是0,是不占用空间的;而的NULL长度是NULL,是占用空间的

2.插入/查询方式区别:NULL值查询使用is null/is not null查询,而空值(’’)可以使用=或者!=、<、>等算术运算符。

3.COUNT 和 IFNULL函数:使用 COUNT(字段) 统计会过滤掉 NULL 值,但是不会过滤掉空值。

4.索引字段说明:在有NULL值的字段上使用常用的索引,如普通索引、复合索引、全文索引等不会使索引失效。在官网查看在空间索引的情况下,说明了 索引列必须为NOT NULL。


七、优化相关


(1)日常工作中你是怎么优化SQL的?

(1.1)表结构优化

尽量使用数字型字段

若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。


尽可能的使用 varchar 代替 char

变长字段存储空间小,可以节省存储空间。


当索引列大量重复数据时,可以把索引删除掉

比如有一列是性别,几乎只有男、女、未知,这样的索引是无效的。


(1.2)查询优化

应尽量避免在 where 子句中使用!=或<>操作符

应尽量避免在 where 子句中使用 or 来连接条件

任何查询也不要出现select *

避免在 where 子句中对字段进行 null 值判断

(1.3)索引优化

对作为查询条件和 order by的字段建立索引

避免建立过多的索引,多使用组合索引

(1.4)慢查询优化

分析语句,是否加载了不必要的字段/数据

分析 SQL 执行句话,是否命中索引等

如果 SQL 很复杂,优化 SQL 结构

如果表数据量太大,考虑分表





相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
29天前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
22天前
|
SQL 缓存 关系型数据库
美团面试:Mysql 有几级缓存? 每一级缓存,具体是什么?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴因未能系统梳理MySQL缓存机制而在美团面试中失利。为此,尼恩对MySQL的缓存机制进行了系统化梳理,包括一级缓存(InnoDB缓存)和二级缓存(查询缓存)。同时,他还将这些知识点整理进《尼恩Java面试宝典PDF》V175版本,帮助大家提升技术水平,顺利通过面试。更多技术资料请关注公号【技术自由圈】。
美团面试:Mysql 有几级缓存? 每一级缓存,具体是什么?
|
16天前
|
SQL 算法 关系型数据库
面试:什么是死锁,如何避免或解决死锁;MySQL中的死锁现象,MySQL死锁如何解决
面试:什么是死锁,死锁产生的四个必要条件,如何避免或解决死锁;数据库锁,锁分类,控制事务;MySQL中的死锁现象,MySQL死锁如何解决
|
24天前
|
SQL 关系型数据库 MySQL
美团面试:Mysql如何选择最优 执行计划,为什么?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴面试美团时遇到了关于MySQL执行计划的面试题:“MySQL如何选择最优执行计划,为什么?”由于缺乏系统化的准备,小伙伴未能给出满意的答案,面试失败。为此,尼恩为大家系统化地梳理了MySQL执行计划的相关知识,帮助大家提升技术水平,展示“技术肌肉”,让面试官“爱到不能自已”。相关内容已收录进《尼恩Java面试宝典PDF》V175版本,供大家参考学习。
|
1月前
|
SQL 关系型数据库 MySQL
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
尼恩,一位40岁的资深架构师,通过其丰富的经验和深厚的技術功底,为众多读者提供了宝贵的面试指导和技术分享。在他的读者交流群中,许多小伙伴获得了来自一线互联网企业的面试机会,并成功应对了诸如事务ACID特性实现、MVCC等相关面试题。尼恩特别整理了这些常见面试题的系统化解答,形成了《MVCC 学习圣经:一次穿透MYSQL MVCC》PDF文档,旨在帮助大家在面试中展示出扎实的技术功底,提高面试成功率。此外,他还编写了《尼恩Java面试宝典》等资料,涵盖了大量面试题和答案,帮助读者全面提升技术面试的表现。这些资料不仅内容详实,而且持续更新,是求职者备战技术面试的宝贵资源。
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
|
1月前
|
SQL 关系型数据库 MySQL
京东面试:什么情况下 mysql RR不能解决幻读? RR隔离mysql如何实现?
老架构师尼恩在其读者交流群中分享了关于MySQL事务隔离级别的深入解析,特别针对RR级隔离如何解决幻读问题进行了详细讨论。文章不仅解释了ACID中的隔离性概念,还列举了四种事务隔离级别(未提交读、提交读、可重复读、串行读)的特点及应用场景。尼恩通过具体的例子和图表,清晰地展示了不同隔离级别下的并发事务问题(脏读、不可重复读、幻读)及其解决方案,特别是RR级隔离下的MVCC机制如何通过快照读和当前读来防止幻读。此外,尼恩还提供了相关面试题的解答技巧和参考资料,帮助读者更好地准备技术面试。更多详细内容和实战案例可在《尼恩Java面试宝典》中找到。
|
1月前
|
SQL 安全 关系型数据库
MySQL 增删操作面试题
MySQL 增删操作面试题
121 1
|
1月前
|
SQL 关系型数据库 MySQL
美团面试:mysql 索引失效?怎么解决? (重点知识,建议收藏,读10遍+)
本文详细解析了MySQL索引失效的多种场景及解决方法,包括破坏最左匹配原则、索引覆盖原则、前缀匹配原则、`ORDER BY`排序不当、`OR`关键字使用不当、索引列上有计算或函数、使用`NOT IN`和`NOT EXISTS`不当、列的比对等。通过实例演示和`EXPLAIN`命令分析,帮助读者深入理解索引失效的原因,并提供相应的优化建议。文章还推荐了《尼恩Java面试宝典》等资源,助力面试者提升技术水平,顺利通过面试。
|
1月前
|
存储 关系型数据库 MySQL
面试官:MySQL一次到底插入多少条数据合适啊?
本文探讨了数据库插入操作的基础知识、批量插入的优势与挑战,以及如何确定合适的插入数据量。通过面试对话的形式,详细解析了单条插入与批量插入的区别,磁盘I/O、内存使用、事务大小和锁策略等关键因素。最后,结合MyBatis框架,提供了实际应用中的批量插入策略和优化建议。希望读者不仅能掌握技术细节,还能理解背后的原理,从而更好地优化数据库性能。
下一篇
无影云桌面