关于这个问题,这里以 MySQL InnoDB 来说,先简单介绍下 MySQL InnoDB 的 B+ 树索引。
B+ 树索引主要可以分为两种索引,聚集索引和非聚集索引。
聚集索引:也就是平常我们说的主键索引,在 B+ 树中叶子节点存的是整行数据。
非聚集索引:也叫二级索引
那我们应该如何避免回表,因为如果用到了回表,就需要二次查询的过程,效率肯定更慢,很简单,回表是因为要查询的字段在非聚集索引里没有,所以在满足需求的情况下,我们尽量使非聚集索引里有要查询的索引字段
所以在查询时,可以尽量用聚集索引来查(也就是用主键来查询),或者根据业务需求,建好的索引,满足索引查询字段。但是实际业务中,很难建立一个索引就能满足所有查询要求,所以,正常情况,回表也没事,只要能用到索引也能大大加快查询速度。
2、IP协议的首部结构
首部协议一共是20个字节(固定)
第一个4字节: 版本号;首部长度; 服务类型;总长度;
第二个4字节:标识;标志;片偏移;
第三个4字节:生存时间;协议;校验和;
第四个4字节:源ip地址;
第五个4字节:目的ip地址;
3、为什么要线程同步?并说一说线程同步的方式
在多线程并发场景下指令执行的先后顺序由内核决定,同一个线程内部指令按照先后顺序执行,但不同线程之间的指令执行先后顺序是不一定的。
如果执行结果依赖于不同线程执行的先后顺序,那么就会形成“竞争条件”,由于竞争条件下计算结果是非预期的,因此我们应该尽量避免竞争条件的形成。
最常解决竞争条件的方式是原子 *** 作,其次便是线程同步。
线程同步主要包括四种方式: 1、互斥锁互斥锁(又名互斥量)强调的是资源之间的访问互斥:每个线程在对共享资源 *** 作前都会尝试先加锁,加锁成功才能 *** 作, *** 作结束之后解锁。
2、读写锁读写锁和互斥量类似,是另一种实现线程同步的方式,但是它将 *** 作分为读、写两种方式,可以多个线程同时占用读模式,这样使得读写锁具有更高的并行性。相较于互斥锁而言读写锁有一定的性能提升,应对的是单写多读模型:
- 写独占:写锁占用时,其他线程加读锁或者写锁时都会阻塞(并非失败)
- 读共享:读锁占用时,其他线程加写锁时会阻塞,加读锁会成功
读写锁有两种策略:
- 强读同步:读锁优先,只要写锁没有占用那么就可以加读锁
- 强写同步:写锁优先,只能等到所有正在等待或者执行的写锁执行完成后才能加读锁
大部分读写锁的实现都采用的是“强写同步”策略,对尝试加锁的 *** 作进行排队,如果前面已经有尝试加写被锁阻塞住的话,后续加读锁也都会被阻塞住(尽管当前时刻是读锁占用的状态)。这样做的目的主要是为了避免“写饥饿”,在“多读少写”的情况下防止数据修改延迟过高。
当然,具体采取哪种策略取决于业务。例如航班订票系统使用强写同步策略,图书馆查阅系统使用强读同步策略。非常适用于对数据结构读的次数远大于写的情况,因为读锁是共享的,这样可以提高并行性。
3、条件变量并发有互斥和等待两大需求,前者是因为线程间存在共享数据依赖而后者是线程间存在依赖,条件变量正是为了解决等待需求。
条件变量本质上也是一个多线程间共享的全局变量,它的功能是阻塞线程,被阻塞的线程直到接收到“条件成立”的信号后才能继续执行。
需要注意的是:
- 条件变量并不是锁(但它几乎总是和互斥量一起使用的),而是线程间的一种通讯机制
- 条件变量本身也不包含条件,它被称为条件变量是因为它经常和条件语句(if/while)一起使用
信号量分为有名信号量和无名信号量,无名信号量用于线程同步,有名信号量一般用于进程之间管理。
信号量本质上是一个非负的整数计数器,用于控制公共资源的访问,也被称为PV原子 *** 作:
- P *** 作:即信号量sem减一,若sem小于等于0则P *** 作被阻塞,直到sem变量大于0为止
- V *** 作:即信号量sem加一
信号量允许多个线程同时进入临界区,而互斥量只允许一个线程进入临界区。
4、索引设计原则和注意事项 一、索引设计原则
1、选择唯一性索引
唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录
如学生的学号是唯一的,而如果使用姓名,可能存在同名现象,从而降低查询速度。
2、为常作为查询条件的字段建立索引(即where后面常用字段)
如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建⽴立索引,可以提⾼高整个表的查询速度
3、为经常需要排序、分组和联合 *** 作的字段建立索引
经常需要order by、group by、distinct和union等 *** 作的字段,排序 *** 作会浪费很多时间。如果为其建立索引,可以有效的避免排序 *** 作
4、小表不建议索引(超过200w数据的表,建立索引)
包含大量的列并且不需要搜索非空值的时候可以考虑不建索引
5、尽量使用数据量少的索引
如果索引的值很长,那么查询的速度会受到影响
例如:对一个char(100)类型的字段进行全文检索需要的时间肯定比对char(10)类型的字段需要的时间更多
6、限制索引的数目
每个索引都需要占⽤用磁盘空间,索引越多,需要的磁盘空间就越大
修改表时,对索引的重构和更新很麻烦
越多的索引,会使更新表变得很浪费时间
7、经常被用来过滤记录的字段
primary key 字段,系统自动创建主键的索引
unique key 字段,系统自动创建对应的索引
foreign key 约束所定义的作为外键的字段
在查询中用来连接表的字段
8、索引的创建必须考虑数据的 *** 作方式
内容很少变动,经常被查询,为它多创建几个索引无所谓
经常性,例行性变动的表而言,则需要谨慎地创建确实必要的索引
9、尽量使用前缀索引
如果索引字段的值很长,最好使用值的前缀来索引
例如:text和blog类型的字段,进行全文检索会浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度
10、删除不再使用或者很少使用的索引
表中数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理理员应当定期找出这些索引,将他们删除,从而减少索引对更新 *** 作的影响
二、合理使用索引注意事项索引是针对数据库表中的某些“列”,因此在创建索引时,需要仔细考虑在哪些列上创建索引,在哪些列上不能创建索引。一般来说,在如下列上可以考虑创建索引:
1、“最左前缀匹配原则”,复合索引(联合索引、多列索引),mysql会从做从左向右匹配直到遇到范围查询(>、<、between、like)就“停止匹配”。比如a = 1 and b = 2 and c > 3 and d = 4 ,如果建立(a,b,c,d)顺序的复合索引,d是用不到索引的;如果建立(a,b,d,c)顺序的复合索引则都可以用到,a,b,d的顺序可以任意调整。
2、在经常需要搜索的列上,可以加快搜索的速度。
3、在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构。
4、在经常用在连接的列上,这些列主要是一些外键,可以加快连表的速度。
5、在经常需要根据范围进行搜索的列上,因为索引已经排序,其指定的范围是连续的。
6、在经常需要排序的列上创建索引,因为索引已经排序,可以利用索引排序加快查询。
7、经常使用在where子句中的列上,加快条件的判断速度。
三、不合理使用索引注意事项1、对于那些在查询中很少使用或者参考的列不应该创建索引。
2、对于那些取值很少的列,如性别等等。
3、对于那些定义为text、image和bit数据类型的列不应该增加索引。
5、B树和B+树有什么区别?为什么使用B+树而不用B树?
1、B树的节点既存储key也存储数据,B+树key只存储key,数据是存在叶子节点上的
2、B树的叶子节点之间是没有关系的,而B+树的叶子节点得相互之间是有一个引用链路的
3、当我们去查找数据的时候查找方式不一样,查找的时候B树可能还不需要查找叶子节点就把数据找到了,而B+树需要查找到叶子节点才能找到数据
6、Explain的作用?
使用Explain关键字可以模拟优化器执行SQL语句,从而知道MySQL是 如何处理你的SQL语句的。分析你的查询语句或是结构的性能瓶颈
不会看 Explain执行计划,劝你简历别写熟悉 SQL优化_程序员小富的博客-CSDN博客
Explain详解_AnEra的博客-CSDN博客_explain详解
7、为什么要分库分表?
分库分表的面试题1 - 百度文库
分库分表的面试题3 - 百度文库
分库分表面试题及答案_JAVA6b的博客-CSDN博客_分库分表面试题
8、处理高并发的六种方法
(1) 系统拆分,将一个系统拆分为多个子系统,用dubbo来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,这样就可以抗高并发;
(2) 缓存,大部分的高并发场景,都是读多写少,读的时候走缓存,redis轻轻松松单机几万的并发;
(3) MQ(消息队列),将请求灌入mq中,控制在mysql承载范围之内,排队后面系统慢慢写,mq单机抗几万并也是可以的;
(4) 分库分表,一个库拆分为多个库,多个库来抗更高的并发;一个表拆分为多个表,减少每个表的数据量,提高sql跑的性能;
(5) 读写分离,可以搞个主从架构读写分离,主库写入,从库读取。流量太多的时候,还可以加更多的从库。
(6) Solrcloud,是solr提供的分布式搜索方案,可以解决海量数据的分布式全文检索,因为搭建了集群,因此具备高可用的特性,同时对数据进行主从备份,避免了单点故障问题。可以做到数据的快速恢复。并且可以动态的添加新的节点,在对数据进行平衡,可以做到负载均衡;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)