💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 为什么要分库分表? 分库主要针对的在单库情况下并发限制问题或单库的磁盘限制问题; 分表主要针对的是单表的数据量很大,影响读性能; ##分库分表之后事务是如何解决的? 在每个库中记录一张流水表 ## 三大范式是什么? * 第一范式:数据表中的每一列(每个字段)必须是不可拆分的最小单元,也就是确保每一列的原子性; * 第二范式(2NF):满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情; * 第三范式:必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,(表中的每一列只能依赖于主键); ## 怎么区分三大范式? 第 一范式和第二范式在于有没有分出两张表,第二范式是说一张表中包含了所种不同的实体属性,那么要必须分成多张表, 第三范式是要求已经分成了多张表,那么一张表中只能有另一张表中的id(主键),而不能有其他的任何信息(其他的信息一律用主键在另一表查询)。 ## 数据库五大约束是什么? 1.primary KEY:设置主键约束; 2.UNIQUE:设置唯一性约束,不能有重复值; 3.DEFAULT 默认值约束,height DOUBLE(3,2)DEFAULT 1.2 height不输入是默认为1,2 4.NOT NULL:设置非空约束,该字段不能为空; 5.FOREIGN key :设置外键约束。 ## 主键是什么,怎么设置主键? 主键默认非空,默认唯一性约束,只有主键才能设置自动增长,自动增长一定是主键,主键不一定自动增长; 在定义列时设置:ID INT PRIMARY KEY 在列定义完之后设置:primary KEY(id) ## 数据库的外键是什么? 只有INNODB的数据库引擎支持外键。 不见已使用基于mysql的物理外键,这样可能会有超出预期的后果。推荐使用逻辑外键,就是自己做表设计,根据代码逻辑设定的外键,自行实现相关的数据操作。 ## innodb和myisam有什么区别? * InnoDB支持事务,而MyISAM不支持事物,崩溃后无法安全恢复,表锁非常影响性能 * InnoDB支持行级锁,而MyISAM支持表级锁 * InnoDB支持MVCC,实现了四个标准的隔离级别 而MyISAM不支持 * InnoDB 表是基于聚族索引建立的,聚族索引对主键查询有很高的性能 * InnoDB支持外键,而MyISAM不支持 * InnoDB文件结构是.frm和.ibd/.ibdata,而MyISAM是.frm、.myd、.myi * MyISAM 存储引擎已经有了20年的历史,在1995年时,MyISAM 是 MySQL 唯一的存储引擎,服务了20多年,即将退居二线。随着mysql5.7,8版本的提升,myisam优点已经逐渐被 InnoDB 实现了。比如全文索引,表空间优化,临时表优化,高效的count(\*) >独享表空间存储方式使用.ibd文件,并且每个表一个ibd文件 共享表空间存储方式使用.ibdata文件,所有表共同使用一个ibdata文件 ## 什么是索引? 索引是一种数据结构,可以帮助我们快速的进行数据的查找. ## 索引是个什么样的数据结构呢? 索引的数据结构和具体存储引擎的实现有关, 在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引. ## innodb索引的实现原理是什么? InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。 ## btree和hash类型的索引有什么不同? 首先要知道Hash索引和B+树索引的底层实现原理: hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据.B+树底层实现是多路平衡查找树.对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据. 那么可以看出他们有以下的不同: * hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询. 因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围. * hash索引不支持使用索引进行排序,原理同上. * hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测.**AAAA**和**AAAAB**的索引没有相关性. * hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询. * hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低. 因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度.而不需要使用hash索引. ## 什么是覆盖索引? 简单的说,select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。 覆盖索引必须要存储索引列的值,而哈希索引、空间索引和全文索引不存储索引列的值,所以mysql**只能用B-tree索引**做覆盖索引。 ## B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引? 在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引. 在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引.如果没有唯一键,则隐式的生成一个键来建立聚簇索引. 当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询. ## 在建立索引的时候,都有哪些需要考虑的因素呢? 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合.如果需要建立联合索引的话,还需要考虑联合索引中的顺序.此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力.这些都和实际的表结构以及查询方式有关. ## 联合索引/多列索引的注意事项是什么? MySQL可以使用多个字段同时建立一个索引,叫做联合索引.在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引. 具体原因为: MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序. 当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,,,以此类推.因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面.此外可以根据特例的查询或者表结构进行单独的调整. ## 导致索引失效的原因有哪些? * 列参与了数学运算或者函数; * 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因); * 对于多列索引,不符合最左匹配的命中规则; * like查询是以%开头; * 如果直接查比用索引快,那么数据库会自动选择最优方式,不用索引; * in 和 not in 也要慎用,否则会导致全表扫描。 ## 主键使用自增ID还是UUID? 推荐使用自增ID,不要使用UUID. 因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降. 总之,在数据量大一些的情况下,用自增主键性能会好一些. ## 字段为什么要求定义为not null? MySQL官网这样介绍: > NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte. null值会占用更多的字节,且会在程序中造成很多与预期不符的情况. ## drop、delete与truncate分别在什么场景之下使用? 我们来对比一下他们的区别: drop table * 1)属于DDL * 2)不可回滚 * 3)不可带where * 4)表内容和结构删除 * 5)删除速度快 truncate table * 1)属于DDL * 2)不可回滚 * 3)不可带where * 4)表内容删除 * 5)删除速度快 delete from * 1)属于DML * 2)可回滚 * 3)可带where * 4)表结构在,表内容要看where执行的情况 * 5)删除速度慢,需要逐行删除 总结: **不再需要一张表的时候,用drop** **想删除部分数据行时候,用delete,并且带上where子句** **保留表而删除所有数据的时候用truncate** ## 关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过? 在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时,慢查询的统计主要由运维在做,会定期将业务中的慢查询反馈给我们. 慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大? 所以优化也是针对这三个方向来的, * 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写. * 分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引. * 如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表. ## UNION、UNION ALL区别? union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序; union All:对两个结果集进行并集操作,包括重复行,不进行排序; ## 你的sql优化常用技巧有哪些? 1. 去掉不必要的查询和搜索字段 2. 争取命中索引,或者根据已有的查询情景简历合理的索引 3. 不要使用select *:以提高查询效率,减少输出的数据量,提高传输速度 4. 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理和是否分页 5. 减少访问数据库的次数,业务代码逻辑优化,避免for循环 6. 使用表的别名(Alias):当在SQL语句中连接多个表时, 减少解析的时间,减少那些由Column歧义引起的语法错误 7. 字段设计not null 8. 索引可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因此索引并非越多越好,合理有效的使用 9. 尽量避免大事务操作,提高系统并发能力 ## 数据库事务的使用的规范有哪些? 1. 控制事务大小,减少锁定的资源量和锁定时间长度。 2. 所有的数据检索都通过索引来完成,从而避免因为无法通过索引加锁而升级为表锁。 3. 减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的数据。 4. 在业务条件允许下,尽量使用较低隔离级别的事务隔离。减少隔离级别带来的附加成本。 5. 合理使用索引,让innodb在索引上面加锁的时候更加准确。 6. 在应用中尽可能做到访问的顺序执行(串行)。 7. 如果容易死锁,就可以考虑使用表锁来减少死锁的概率。 ## InnoDB怎么实现的事务ACID特性? * redo log重做日志用来保证事务的持久性 * undo log回滚日志保证事务的原子性 * undo log+redo log保证事务的一致性 * 锁(共享、排他)用来保证事务的隔离性 undo log 实现如下两个功能:1.实现事务回滚 2.实现MVCC undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。 推荐阅读,加深理解 :[https://www.cnblogs.com/jianzh5/p/11643151.html]