目录
- 连接查询
- MySQL常用函数汇总
- [SQL Select 语句的执行顺序](#SQL Select 语句的执行顺序)
- 聚集索引和非聚集索引的区别
- 数据库三范式
- [MyISAM 存储引擎 与 InnoDB 引擎区别](#MyISAM 存储引擎 与 InnoDB 引擎区别)
- 索引
- 数据库锁
- [MySql 优化](#MySql 优化)
连接查询
MySQL常用函数汇总
SQL Select 语句的执行顺序
聚集索引和非聚集索引的区别
- 聚集索引:包含主键和非主键数据以及索引
- 非聚集索引:只包含主键和索引,当没有实现索引覆盖时会进行回表,走聚集索引
数据库三范式
-
第一范式
1NF 原子性,列或者字段不能再分,要求属性具有原子性,不可再分解; -
第二范式
2NF 唯一标识。即每个表只描述一种实体,每个记录都有唯一标识,不存在部分依赖关系。 主要是解决行的冗余。- 每个表必须有一个主键
- 非主键字段要完全依赖于主键
-
第三范式
3NF 直接性,非主键字段不依赖于其它非主键字段, 主要是解决列的冗余.
MyISAM 存储引擎 与 InnoDB 引擎区别
-
事务支持:MyISAM 不支持事务处理,而 InnoDB 支持事务处理,可以通过使用事务来确保数据的完整性和一致性。
-
锁定机制(锁的粒度):MyISAM 表级锁在执行 SELECT 操作时会对 表 进行读锁定,而执行 INSERT、UPDATE 或 DELETE 操作时会对 表 进行写锁定,因此在写操作执行时,读操作会被阻塞。而 InnoDB 支持行级锁,不会对整个表进行锁定,可以减少锁定冲突和死锁的发生。
-
外键支持:MyISAM 不支持外键约束,而 InnoDB 支持外键约束,可以通过外键约 束来保证数据的引用完整性
-
并发性能:在并发性能方面,InnoDB 要优于 MyISAM。由于 InnoDB 支持行级锁定 和 事务处理,因此在高并发情况下,InnoDB 的并发性能更高。
因此,在设计数据库时,需要考虑具体情况选择适合的 存储引擎。
- 如果需要支持事务处理** 和 外键约束,以及具有更好的并发性能,则应选择 InnoDB**。
- 如果只是进行简单的读写操作**,并且需要更快的查询速度,则可以选择 MyISAM**。
索引
索引存储在 内存 中,为服务器存储引擎为了快速找到记录的一种数据结构。
索引的主要作用是 加快数据查找速度,提高数据库的性能。 空间换时间
索引的优缺点
优点:加快查询效率
-
创建唯一性索引,保证数据库表中每一行数据的唯一性
-
大大加快数据的检索速度,这也是创建索引的最主要的原因
-
加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
-
在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
缺点:
- 占用内存空间
- 影响增删改,效率低下.
索引的分类
-
普通索引:最基本的索引,它没有任何限制。(值可重复)
-
唯一索引:与普通索引类似,不同的就是索引列的值必须唯一,但允许有空值。
-
主键索引:它是一种特殊的唯一索引,用于唯一标识数据表中的某一条记录,不允许有空值,一般用 primary key 来约束。
-
联合索引(又叫复合索引):多个字段上建立的索引,能够加速复合查询条件的检索,遵循最左匹配原则(定义联合索引时左边的字段可单独使用索引,右边的字段不能单独使用索引)。
使用场景:
- 登录时,手机号+密码
- 商品表中,类型+状态
- 订单表中,订单号+用户Id
-
全文索引:老版本 MySQL 自带的全文索引只能用于数据库引擎为MyISAM 的数据表,新版本 MySQL 5.6 的 InnoDB 1支持全文索引。默认 MySQL不支持中文全文检索,可以通过扩展 MySQL,添加中文全文检索或为中文内容表提供一个对应的英文索引表的方式来支持中文,一般使用ElasticSearch做搜索引擎库。
索引结构
Mysql 目前提供了以下 4 种索引:
- B+Tree 索引: 最常见的索引类型, 大部分索引都支持 B+树索引.
- Hash 索引: 只有 Memory 引擎支持, 使用场景简单.
- R-Tree 索引(空间索引): 空间索引是 MyISAM 引擎的一个特殊索引类型, 主要地理空间数据, 使用也很少.
- S-Full-text(全文索引): 全文索引也是 MyISAM的一个特殊索引类型, 主要用于全文索引, InnoDB 从 Mysql5.6 版本开始支持全文索引.
B树与B+树的区别
- 存储数据的位置:
- B树: 数据既存储在所有节点中(叶子节点和非叶子节点都有数据)
- B+树: 所有的数据记录都存储在叶子节点中,非叶子节点仅包含索引信息。叶子节点包含了完整的数据和索引键。
- 叶子节点之间的链接:
- B树: 叶子节点之间没有链接。
- B+树: 叶子节点之间通过指针相互链接,形成一个 链表 或 循环链表,这使得范围查询和遍历变得高效。
补充:动画演示数据结构
索引失效的几种情况
-
范围条件查询
当查询到的记录大于总记录数30%时,就不再使用索引,直接会扫描全表
-
索引列上操作(使用函数、计算等)导致索引失效
-
字符串不加引号, 造成索引失效
-
尽量使用 索引覆盖 ,避免
select *
,这样能提高查询效率.
- 索引覆盖: 索引中直接包含所需数据
- 回表:通过索引不能完全拿出你要的信息,需要通过数据表再次查询一次才能获取到.
-
OR 关键字连接
OR关键字两边的字段必须都要有索引,任一个字段没索引就会进行全表扫描
-
使用
!=
导致索引失效 -
like以通配符开头
('%abc...')
导致索引失效 -
排序列包含不同索引的列
数据库锁
-
行锁和表锁
主要是针对锁粒度划分的,一般分为:行锁、表锁、库锁
-
行锁:访问数据库的时候,锁定整个行数据, 防止并发错误。
-
表锁:访问数据库的时候,锁定整个表数据,防止并发错误。
行锁 和 表锁 的区别:
- 行锁:
开销大,加锁慢,会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高 - 表锁:
开销小,加锁快,不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
-
-
悲观锁和乐观锁
- 悲观锁:每次去拿数据的时候都认为会进行修改,所有每次在拿数据的时候都会上锁.
- 乐观锁:每次去拿数据的时候都认为不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间有没有更新这个数据,使用版本号机制,如何版本号不支持舍弃这次操作,并且设置 重试机制,乐观锁适用于多读的应用类型 ,这样可以提高吞吐量 。
MySql 优化
-
定位执行效率慢的 sql 语句
- explain + sql语句查询sql执行过程,可了解到:
- 哪些步骤花费的成本比较高
- 这条sql语句是否走索引
- 慢查询日志(常用)
慢 查 询 日 志 记 录 了 所 有 执 行 时 间 超 过 参 数long_query_time
的 sql 语 句 的 日 志- 可使用
xxl-job
查询慢日志 - 通过
skyWalking
监控慢日志 - 也可以使用
elk
查看哪个接口比较慢
- 可使用
- explain + sql语句查询sql执行过程,可了解到:
-
优化索引
- 对查询频次较高, 且数据量比较大的表, 建立索引.
- 索引字段的选择, 最佳候选列应当从 where 子句的条件中提取, 如果 where 子句中的组合比较多, 那么应当挑选最常用, 过滤效果最好的列的组合.
- 使用唯一索引, 区分度越高, 使用索引的效率越高,能建唯一索引就建唯一索引,或者普通索引
- 索引并非越多越好, 如果该表赠,删,改操作较多, 慎重选择建立索引, 过多索引会降低表维护效率. 不是越多越好
- 使用短索引, 提高索引访问时的 I/O 效率, 因此也相应提升了 Mysql 查询效率.
如果 where 后有多个条件经常被用到, 建议建立复合索引, 复合索引需要遵循最左前缀法则, N 个列组合而成的复合索引, 相当于创建了 N 个索引.
复合索引命名规则 index _ 表名 _ 列名 1 _ 列名 2 _ 列名 3
-
Sql 语句调优
-
根据业务场景建立复合索引只查询业务需要的字段,如果这些字段被索引覆盖,将极大的提高查询效率.
-
多表连接的字段上需要建立索引,这样可以极大提高表连接的效率.
-
where 条件字段上需要建立索引, 但 Where 条件上不要使用运算函数,以免索引失效.
-
排序字段上, 因为排序效率低, 添加索引能提高查询效率.
-
优化 order by 语句: 在使用 order by 语句时, 不要使用 select *, select 后面要查有索引的列, 如果一条 sql 语句中对多个列进行排序, 在业务允许情况下, 尽量同时用升序或同时用降序.
-
优化 group by 语句: 在我们对某一个字段进行分组的时候, Mysql 默认就进行了排序,但是排序并不是我们业务所需的, 额外的排序会降低效率. 所以在用的时候可以禁止排序, 使用
order by null
禁用.sqlselect age, count(*) from emp group by age order by null
-
尽量避免子查询, 可以将子查询优化为 join 多表连接查询.
-
-
合理的数据库设计
-
保留冗余字段。当两个或多个表在查询中经常需要连接时,可以在其中一个表上增加若干冗余的字段,以 避免表之间的连接过于频繁,一般在冗余列的数据不经常变动的情况下使用。
-
增加派生列。派生列是由表中的其它多个列的计算所得,增加派生列可以减少统计运算,在数据汇总时可以大大缩短运算时间, 前提是这个列经常被用到, 这也就是反第三范式。
-
分割表。
数据表拆分:主要就是垂直拆分和水平拆分。- 水平切分:将记录散列到不同的表中,各表的结构完全相同,每次从分表中查询, 提高效率。
- 垂直切分:将表中大字段单独拆分到另外一张表, 形成一对一的关系。
-
字段设计
-
表的字段尽可能用
NOT NULL
-
字段长度固定的表查询会更快
-
把数据库的大表按时间或一些标志分成小表
-
-
相关文章:数据库事务相关面试题