1.myIsam和innodb区别
- MyISAM锁的粒度是表级的,而InnoDB支持行级锁
- MyISAM支持全文类型索引,而InnoDB不支持全文索引
- innodb是基于聚簇索引建立的,支持事务,外健,并且通过mvcc支持高并发,索引和数据存储在一起。
- myIsam,不支持事务,支持、压缩、空间函数等。不支持外健,索引和数据分开存储。一般用于大量查询,少量插入。
2.mysql索引有哪些,聚簇索引和非聚簇索引又是什么?
索引按照数据结构主要包含B+树和Hash索引。
聚簇索引:
- 如果表设置了主键,主键就是聚簇索引;
- 如果没有主键,则会默认第一个notnull,且唯一的(UNIQUE)的列作为聚簇索引。
- 以上都没有,则默认创建一个隐藏的row_id作为聚簇索引
- innodb聚簇索引叶子节点存储的是行数据
查找过程:如果按照主键查询,只需要扫描一次B+树就可以通过聚簇索引定位到行记录数据
非聚簇索引:
- innodb的普通索引叶子节点存储的是主键(聚簇索引)的值,而MyIsam普通索引存储的是记录指针。
查找过程:如果按照普通索引需要,扫描两次B+树,第一次通过非聚簇索引找到聚簇索引值,第二次根据聚簇索引找到行数据。
回表查询:
非聚簇索引查找过程,扫描两次B+树。
覆盖索引:
只需要在一棵树上就能获取SQL所需要的数据,无需回表。
explain的输出结果Extra字段为Using index时,能够触发索引覆盖。
将被查询的字段,建立联合索引。B+树上就有相应的行数据。
场景:分页查询,全表count。
3.mysql锁类型
分为共享锁和排他锁,也叫读锁和写锁。
读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写。
写锁是排他的,它会阻塞其他的读锁和写锁。从颗粒度来区分又分为行锁和表锁。
表锁会锁定整张表,并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构,进行锁表。
行锁又可以分为悲观锁和乐观锁。悲观锁通过for update实现,乐观锁则通过版本号实现。
4.分库分表
数据量:每天几万,流水几十万。
先分库再分表。
垂直分库:按照微服务不同模块分库。
垂直分表:表字段过多,将不常用的数据拆分。(不常用,在设计表的时候就要避免)
水平分表:按照500万每张表,按照业务场景决定用什么字段作为分表字段(sharding_key)。
保证各个表ID唯一性:雪花算法id,设置步长。
分布到各个表中:
Hash:比如用户id为100,那我们都经过hash(100),然后对(表数量)取模,就可以落到对应的表上了。
range:固定步长。
分表后非sharding_key查询:
- 做映射表
- es
5.读写分离
使用shrading- JDBC实现读写分离(可以认为是一个增强版的jdbc驱动),数据源完全由shrading托管,写操作自动执行master库,读操作自动执行salve库。
spring:
main:
allow-bean-definition-overriding: true
shardingsphere:
datasource:
names:
master,slave
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_master?characterEncoding=utf-8
username: ****
password: ****
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_slave?characterEncoding=utf-8
username: ****
password: ****
masterslave:
# 负载均衡算法类型:round_robin(轮询),Random(随机)
load-balance-algorithm-type: round_robin
# 最终的数据源名称
name: dataSource
# 主库数据源名称
master-data-source-name: master
# 从库数据源名称列表,多个逗号分隔
slave-data-source-names: slave
props:
# 开启SQL显示,默认false,打印sql,显示执行库的名称
sql:
show: true
6.读写分离架构中读延迟问题
主节点写入数据后需要同步到从数据库,mysql5.7的主从复制采用多线程,但还是可能有延迟。
解决方式:
-
业务层面妥协,是否操作后马上进行读取
-
业务上不能妥协,对这类操作直接走主库,shrding-jdbc可以设置强制走主库。
//-----------------------------------核心 跟pagehelper 分页插件类似 只作用于最近的一条查询语句, HintManager.getInstance().setMasterRouteOnly(); List<Order> byUserId = orderMapper.findByUserId(5);
7.varchar和char区别
1.char长度固定,如果字符不够,会用空格填充到特定长度,检索char值需要删除尾部空格。
2.varchar不会填充空格。
8.like的%放在字符前和后有什么区别?
- 放在字符前,会进行全表扫描。
- 放在字符后,如果是字符类型的字段且加索引,那么会走索引。如果是数字类型,那么不走索引,因为查询时是按照字符查询的。
9.mysql索引类型
- 主键索引
- 唯一索引 unique
- 普通索引 normal
- full text 全文索引
- 索引译B+树存储
10.B树和B+树的区别
B树:每个节点都存储key和data,并且叶子节点指针为null。
B+树:只有叶子节点存储data,叶子节点包含了这颗树的所有键值。
为什么innodb要使用B+树,因为B+树内节点不存储data,这样一个节点就可以存储更多的key。
11.联合索引最左原则
-
mysql会一直向右匹配知道遇到范围查询(>,<,between,like)就停止匹配,
-
=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。
-
选择热度最高的列作为联合索引左列
-
索引的底层是一颗B+树,联合索引的健值数量不是一个,而是多个。构建一颗B+树只能根据一个值来构建,因此数据库依据联合索引最左的字段来构建B+树。例子:假如创建一个(a,b)的联合索引,那么它的索引树是这样的
12.索引规范
- 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。
- 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。