一、Sql的执行顺序是什么
FROM:首先,系统会从指定的表中获取数据。这个步骤包括从表中读取数据行以供后续处理。
WHERE:系统会应用WHERE子句中的条件来筛选行。只有满足WHERE条件的行将被包含在结果集中,而不满足条件的行将被排除。
GROUP BY:如果有GROUP BY子句,系统将按照指定的列对数据进行分组。这通常伴随着聚合函数的使用(如SUM、AVG、COUNT等),以计算每个组的汇总值。
HAVING:如果有HAVING子句,系统将使用它来筛选分组后的结果。只有满足HAVING条件的组才会包括在结果中。
SELECT:系统会选择要包括在结果中的列,这通常包括从表中检索的原始列,以及任何聚合函数的结果。
DISTINCT:如果使用SELECT DISTINCT,系统将去除结果中的重复行,只保留唯一的行。
ORDER BY:如果有ORDER BY子句,系统将对结果进行排序。这会根据指定的列或表达式按升序或降序对结果进行排序。
LIMIT / OFFSET:最后,系统会根据LIMIT和OFFSET子句来选择一定数量的结果行,通常用于分页或限制返回的结果数量。
需要注意的是,虽然这些步骤表示了通常的SQL执行顺序,但在实际查询执行过程中,数据库管理系统可能会进行优化,以提高性能。例如,数据库可能会重新排列步骤以减少不必要的计算和I/O操作。这些优化通常由查询优化器来执行。
此外,对于多表联接,查询执行顺序可能会有所不同,取决于查询中使用的连接类型(INNER JOIN、LEFT JOIN等)。查询优化器将根据表之间的关系和连接类型来决定最佳的执行计划。
二、mysql都有什么锁,死锁判定原理和具体场景,死锁怎么解决?
MySQL有三种锁的级别:页级、表级、行级。
- 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
- 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
什么情况下会造成死锁?
1.什么是死锁?
死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等着的进程称为死锁进程。
表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。
2. 死锁的解决办法?
- 查出的线程杀死 kill: SELECT trx_MySQL_thread_id FROM information_schema.INNODB_TRX;
- 设置锁的超时时间Innodb 行锁的等待时间,单位秒。可在会话级别设置,RDS 实例该参数的默认值为 50(秒)。生产环境不推荐使用过大的 innodb_lock_wait_timeout参数值该参数支持在会话级别修改,方便应用在会话级别单独设置某些特殊操作的行锁等待超时时间,如下set innodb_lock_wait_timeout=1000; —设置当前会话 Innodb 行锁等待超时时间,单位秒。
- 指定获取锁的顺序
三.#和$的区别
#{}是预编译处理,{}是字符串替换。mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;mybatis在处理 { } 时,就是把 ${ } 替换成变量的值。使用 #{} 可以有效地防止SQL注入,提高系统安全性 。
四、expian解析sql
1、IDID是表示语句执行顺序的标识:不同的id值,id越大的优先执行;相同的id值,则由上往下执行,排在上面的语句先执行。
2、select_type此列主要用于区分查询语句的类型,通过这个列可以区分SQL属于简单的select、联合查询、子查询等。
SIMPLE: 简单的select查询,不包含任何子查询或联合查询。
PRIMARY:主查询,如果有子查询的话,最外层的查询会被标记为PRIMARY。
SUBQUERY: 该语句属于子查询语句。
DERIVED: 生成的临时表的查询语句会被标记为DERIVED 。
UNION: 标记为UNION类型的查询语句。
UNION RESULT: 从UNION语句中获取结果。
3、table显示这一行的数据是来源于哪张表的
4、type(重要)type列是定位SQL性能因素最重要的一个指标,通过type我们可以直观的判断一个SQL的性能的基本情况,type包括以下几种类型的查询system 、const 、eq_ref、ref、Range、Index、All,他们的性能依次从高到低,简单来讲我们进行SQL优化的第一步就是要在type列上定位SQL的性能。
System:表只有一行记录(日常基本上不会出现)。
Const:通过索引一次就找到了数据,一般出现在使用了primary key或者unique索引匹配到了数据,匹配的条件是常量(字符串、数字)。
eq_ref:使用了主键索引,或者非空唯一索引,在表中只有一条记录与索引键相匹配,匹配条件是某个表的列(需要转义替换才能拿到值)。
ref:非唯一性索引扫描,和eq_ref 不同的是eq_ref 匹配的是唯一索引,ref它返回所有匹配某个单独值的行,它可能会找到多个符合条件的行。
range:范围数据扫描。index: 全索引扫描,通过扫描整棵索引树获取到结果。
All:全表扫描。
Const 和eq_ref 的区别
两个都是在用到了主键索引或唯一索引的情况下出现,不同的是Const 的where 条件是常量,eq_ref 的where 条件是其他表的某个列,需要对这个列进行转义才能拿到匹配条件的值,也可以简单的理解为,eq_ref 一般为关联查询。5、possible_keys,key,key_len(重要)possible_keys: 可能使用到的索引 。Key: 实际使用的索引。如果为空,则说明没有使用索引。key_len:使用到的索引key的长度,如果为联合索引则显示已命中的联合索引长度之和(如:联合索引为a+b+c ,如果索引命中了a+b ,那么长度就为a+b的索引长度,通常可以通过key_len 来分析联合索引所命中的情况)。关于possible_keys 和key的三种关系场景:
- possible_keys !=null&& key!=null ,这是正常使用到索引的情况。
- possible_keys !=null&& key==null ,这种情况一般说明通过索引并不能提升多少效率,一般而言是表的数据量很少,或者是索引的字段离散性不高,执行计划发现用索引和扫表差不多。
- possible_keys ==null&& key!=null , 这种情况一般为where条件没有命中索引,但是查询的列是索引字段,也就是查询的列命中覆盖索引情况。
6、ref实际用到的索引是哪个表的列, const代表常量
7、row扫描的数据行数,一般来说扫描的数据行数越少,性能越好。
8、Extra列(重要)Extra 可以说是对整个SQL做了一个概括性的总结,包括你用了什么索引、排序方式、使用了临时表包含不适合在其他列显示,但是十分重要的信息
using where :使用了where条件。using index:使用了覆盖索引 (通常情况下这是一种好现象,意味着查询的数据直接在二级索引返回了,从而减少了回表的过程)。
using filesort :文件排序,意思就是使用了非索引的字段进行排序(通常这种情况需要优化)。
using index sort :使用索引排序 (通常情况下这是一种好现象,索引天然有序,所以避免了通过sort buffer来排序的流程)。
using temporary :使用了临时表(常见于group by、order by)。using join buffer :使用了join buffer缓存(这种情况关注一下关联查询的字段是不是没有建索引)。
五、什么是临时表,临时表什么时候删除?
临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。
下列操作会使用到临时表:
- union查询
- 对于视图的操作,比如使用一些TEMPTABLE算法、union或aggregation
- 子查询
- join 包括not in、exist等
- 查询产生的派生表
- 复杂的group by 和 order by
- Insert select 同一个表,mysql会产生一个临时表缓存select的行
- 多个表更新
- GROUP_CONCAT() 或者 COUNT(DISTINCT) 语句
六、有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?
它锁与共享锁相对应,就是指对于多个不同的事务,对同一个资源只能有一把锁。与共享锁类型,在需要执行的语句后面加上 for update就可以了。在数据库管理中,常见的锁可以分为两大类:悲观锁和乐观锁。这些锁用于控制并发访问数据库时的数据一致性和完整性。悲观锁:
- 共享锁(Shared Lock):也称为读锁,允许多个事务同时获取共享锁,但不允许事务获取排他锁。共享锁用于保护数据的一致性读操作,不阻塞其他共享锁的获取,但会阻塞排他锁的获取。
- 排他锁(Exclusive Lock):也称为写锁,只允许一个事务获取排他锁,其他事务无法同时获取共享锁或排他锁。排他锁用于保护数据的写操作,阻塞其他锁的获取,包括共享锁和排他锁。
乐观锁:
- 乐观锁不实际上对数据进行锁定。它基于一种假设,即数据在被修改期间不会被其他事务修改。在乐观锁中,你通常会使用版本号或时间戳等机制,以确保在提交修改之前,数据没有被其他事务修改。如果检测到冲突,事务将回滚。
要在SELECT语句中添加排他锁,通常可以使用以下方法,具体取决于数据库系统:
-
For Update:在大多数数据库中,你可以在SELECT语句中使用FOR UPDATE子句,它将获取排他锁
-
Lock in Share Mode:如果你希望获取共享锁,可以使用LOCK IN SHARE MODE子句。例如:
这些语句将在查询过程中锁定满足条件的数据,以防止其他事务同时获取相同数据的锁。请注意,不同数据库管理系统可能具有不同的语法,上述示例基于通用SQL语法,具体数据库可能有自己的扩展或不同的语法。确保查阅你所使用数据库管理系统的文档以了解如何实现排他锁。
七、数据库三范式,根据某个场景设计数据表
数据库三范式是一种用于设计关系型数据库表结构的标准化方法,它旨在减少数据冗余并确保数据的一致性。在根据某个场景设计数据库表时,通常可以遵循以下三个范式:
- 第一范式 (1NF) :确保每个列都包含原子性数据,不包含重复组或数组。每一列都应该是不可再分的。
- 第二范式 (2NF) :在满足第一范式的基础上,每个非主键列都必须完全依赖于整个候选键。这意味着没有部分依赖。
- 第三范式 (3NF) :在满足第二范式的基础上,消除了传递依赖。任何非主键列不应该依赖于其他非主键列,即没有传递依赖关系。
根据某个具体场景设计数据库表时,首先要理解场景的数据需求和关系。以下是一个示例场景和如何设计数据库表以满足三范式的示例:场景:假设你要设计一个图书馆管理系统,需要记录图书、作者和借阅记录。第一范式 (1NF):确保每个列都包含原子性数据。创建以下表:
- Books表包含图书信息,每本书有一个唯一的图书ID。
- Authors表包含作者信息,每个作者有一个唯一的作者ID。
- BorrowedBooks表用于记录借阅记录,每条借阅记录有一个唯一的借阅ID。
- 在每个表中,确保每个列包含原子性数据,例如:
- Books表包含BookID、Title、ISBN等原子性列。
- Authors表包含AuthorID、FirstName、LastName等原子性列。
- BorrowedBooks表包含BorrowID、BookID、UserID等原子性列。
第二范式 (2NF):确保每个非主键列完全依赖于整个候选键。在这个示例中,主键可能是每个表中的ID列,如BookID、AuthorID、BorrowID。第三范式 (3NF):消除传递依赖。确保没有传递依赖关系。例如,BorrowedBooks表中的UserID列应该直接依赖于借阅记录(BorrowID),而不应该依赖于BookID或其他非主键列。这个设计满足了数据库三范式的要求,以确保数据的一致性和减少数据冗余。它为图书馆管理系统提供了合理的数据模型。需要根据实际需求和数据库系统的特点进行调整和优化,以满足特定场景的需求。
八、什么是 内连接、外连接、交叉连接、笛卡尔积
在关系型数据库中,内连接(Inner Join)、外连接(Outer Join)、交叉连接(Cross Join),以及笛卡尔积(Cartesian Product)是用于组合两个或多个表中数据的不同方式。它们用于执行联接操作,将表中的数据组合在一起,以满足特定查询需求。内连接(Inner Join) :
- 内连接是最常用的联接类型。它仅返回两个表中满足连接条件的匹配行。如果没有匹配的行,这些行将不包括在结果中。
- 内连接使用一个连接条件,通常是两个表之间的某些列相等的条件。
例子:
外连接(Outer Join) :
- 外连接用于返回连接两个表的所有行,以及满足连接条件的匹配行。如果没有匹配的行,将用NULL填充缺失的值。
- 外连接有左外连接(Left Outer Join)、右外连接(Right Outer Join)和全外连接(Full Outer Join)等不同类型,根据你需要的行为来选择。
例子(左外连接):
交叉连接(Cross Join):
- 交叉连接返回两个表的笛卡尔积,即表1中的每一行与表2中的每一行组合在一起。
- 交叉连接通常用于生成所有可能的组合,通常需要小心使用,因为它可能导致大量的结果行。
例子:
笛卡尔积(Cartesian Product):
- 笛卡尔积是两个表的交叉连接的结果。它返回两个表中所有可能的组合,而不考虑连接条件。
- 笛卡尔积通常不是有意而为之的操作,因为它可能会生成大量的结果,而且通常不是查询的预期结果。
这些连接操作允许在关系数据库中组合不同表中的数据,以便满足各种查询需求。根据查询的特定需求,你可以选择适当的联接类型。内连接用于查找相关数据,外连接用于包含不匹配的数据,交叉连接用于生成组合,而笛卡尔积通常要避免使用,因为它可能导致不必要的复杂性。