1,在 MySQL 中统计数据表的行数的三种方式:SELECT COUNT(*)、SELECT COUNT(1)和SELECT COUNT(具体字段),一般情况下,三者执行的效率为 COUNT(*)= COUNT(1)> COUNT(字段)。应尽量使用COUNT(*),如果要统计COUNT(*),尽量在数据表上建立二级索引,系统会自动采用key_len小的二级索引进行扫描,这样当我们使用SELECT COUNT(*)的时候效率就会提升,有时候可以提升几倍甚至更高。
2,LIMIT用法。如果确定结果集只有一条,那么加上LIMIT 1的时候,当找到一条结果的时候就不会继续扫描了,这样会加快查询速度。(针对的是会扫描全表的 SQL 语句,如果数据表已经对字段建立了唯一索引,那么可以通过索引进行查询,不会全表扫描的话,就不需要加上LIMIT 1了。)
3,为什么在 ORDER BY 字段上加索引以增加查询效率?在 MySQL 中,支持两种排序方式,分别是 FileSort 和 Index 排序。在 Index 排序中,索引可以保证数据的有序性,不需要再进行排序,效率更高。而 FileSort 排序则一般在内存中进行排序,占用 CPU 较多。如果待排结果较大,会产生临时文件 I/O 到磁盘进行排序的情况,效率较低。所以使用 ORDER BY 子句时,应该尽量使用 Index 排序,避免使用 FileSort 排序。(可以使用 explain 来查看执行计划,看下优化器是否采用索引进行排序。)
4,SELECT 语句内部的执行步骤:一条完整的 SELECT 语句内部的执行顺序是这样的:
FROM 子句组装数据(包括通过 ON 进行连接);
WHERE 子句进行条件筛选;
GROUP BY 分组 ;
使用聚集函数进行计算;
HAVING 筛选分组;
计算所有的表达式;
SELECT 的字段;
ORDER BY 排序;
LIMIT 筛选。
5,哪种情况下应该使用 EXISTS,哪种情况应该用 IN?
选择与否还是要看表的大小,标准为小表驱动大表。
SELECT * FROM A WHERE cc IN (SELECT cc FROM B)
SELECT * FROM A WHERE EXISTS (SELECT cc FROM B WHERE B.cc=A.cc)
当 A 小于 B 时,用 EXISTS。因为 EXISTS 的实现,相当于外表循环,实现的逻辑类似于
for i in A
for j in B
if j.cc == i.cc then ...
当 B 小于 A 时用 IN,因为实现的逻辑类似于
for i in B
for j in A
if j.cc == i.cc then ...
6,Mysql默认的事务隔离级别:Repeatable Read
7,MySQL InnoDB 存储引擎具有的特性:
插入缓冲(Insert Buffer)
二次写 (Double Write)
自适应哈希索引(Adaptive Hash Index)
预读(Read Ahead)
8,Redis与Memcached比较:
作为常见的 NoSQL 数据库,Redis 支持的数据类型比 Memcached 丰富得多,在 I/O 性能上,Redis 采用的是单线程 I/O 复用模型,而 Memcached 是多线程,可以利用多核优势。而且在持久化上,Redis 提供了两种持久化的模式,可以让数据永久保存。
9,为什么redis单线程模型也能效率这么高?
纯内存操作,核心是基于非阻塞的IO多路复用机制,单线程反而避免了多线程的频繁上下文切换问题。
10,redis和mongodb的差别
总的来说redis效率更高,mongodb能承载的数据量更大。
Redis是Key-Value数据库,数据存放在内存中,查询和写入都是在内存中进行操作。可以把Redis称之为缓存。支持的数据类型丰富,包括字符串、哈希、列表、集合、有序集合,同时还支持基数统计,地理空间以及索引半径查询,数据流等。
MongoDB是面向文档数据库,功能强大,是非关系型数据库中最像关系型数据库的,处理增删改查也可以增加条件,类似于RDBMS一样灵活。
存储方式上,
Redis将数据放在内存中的,通过RDB或者AOF方式进行持久化。
MongoDB实际上数据是存放在磁盘上的,只是通过mmap调用将数据映射到内存中,所以你可以将mmap理解成为加速的方式。mmap调用可以使得对普通文件的操作像是在内存中进行读写一样,这是因为它将文件映射到调用进程的地址空间中,实现了文件所在的磁盘物理地址与进程空间的虚拟地址一一映射的关系,这样就可以直接在内存中进行操作,然后写完成之后同步一下就可以存放到文件中,效率非常高。
11,InnoDB 中的自适应 Hash 相当于“索引的索引”,采用 Hash 索引存储的是 B+ 树索引中的页面的地址。如下图所示:
![](https://img.haomeiwen.com/i4177216/25aa38d0aefbdb5b.png)
采用自适应 Hash 索引目的是方便根据 SQL 的查询条件加速定位到叶子节点,特别是当 B+ 树比较深的时候,通过自适应 Hash 索引可以明显提高数据的检索效率。
12,关于联合索引的最左原则
联合索引的最左前缀匹配原则针对的是创建的联合索引中的顺序,如果创建了联合索引(x,y,z),那么如果在条件语句中只有 y 和 z,那么就用不上联合索引。
SQL 条件语句中的字段顺序并不重要,因为在逻辑查询优化阶段会自动进行查询重写。
查询“z=7 AND y=8 AND x=9”的时候,如果三个字段 x、y、z 在条件查询的时候是乱序的,但采用的是等值查询(=)或者是 IN 查询,那么 MySQL 的优化器可以自动帮我们调整为可以使用联合索引的形式。
查询“x=9 AND y>8 AND z=7”的时候,如果建立了 (x,y,z) 顺序的索引,这时候 z 是用不上索引的。MySQL 在匹配联合索引最左前缀的时候,如果遇到了范围查询,比如(<)(>)和 between 等,就会停止匹配。索引列最多作用于一个范围列,对于后面的 Z 来说,就没法使用到索引了。
13,关于缓冲池
在 InnoDB 存储引擎中有一部分数据会放到内存中,缓冲池则占了这部分内存的大部分,它用来存储各种数据的缓存,如下图所示:
![](https://img.haomeiwen.com/i4177216/91aba4550b3ba01e.png)
InnoDB 缓冲池包括了数据页、索引页、插入缓冲、锁信息、自适应 Hash 和数据字典信息等。
(使用缓冲池技术的原因。InnoDB 存储引擎基于磁盘文件存储,访问物理硬盘和在内存中进行访问,速度相差很大,为了尽可能弥补这两者之间 I/O 效率的差值,我们就需要把经常使用的数据加载到缓冲池中,避免每次访问都进行磁盘 I/O。)
14,什么是查询缓存?
查询缓存是提前把查询结果缓存起来,这样下次不需要执行就可以直接拿到结果。在 MySQL 中的查询缓存,不是缓存查询计划,而是查询对应的结果。这意味着查询匹配的鲁棒性大大降低,只有相同的查询操作才会命中查询缓存。因此 MySQL 的查询缓存命中率不高,在 MySQL8.0 版本中已经弃用了查询缓存功能。
缓冲池并不等于查询缓存,它们的共同点都是通过缓存的机制来提升效率。但缓冲池服务于数据库整体的 I/O 操作,而查询缓存服务于 SQL 查询和查询结果集的,命中率低。
15,为什么需要主从同步?
提升数据库高并发访问的效率,首先考虑如何优化SQL 和索引,其次是采用缓存的策略,比如使用 Redis,通过 Redis 高性能的优势将热点数据保存在内存数据库中,最后是对数据库采用主从架构,进行读写分离。
主从同步设计不仅可以提高数据库的吞吐量,还有以下 3 个方面的作用
a.读写分离
通过主从复制的方式来同步数据,然后通过读写分离提高数据库并发处理能力。
原本所有的读写压力都由一台服务器承担,现在有多个处理读请求,这样就减少了对(Master)的压力。
同时,还能对从服务器进行负载均衡,让不同的读请求按照策略均匀地分发到不同的从服务器上,让读取更加顺畅。
读取顺畅的另一个原因,就是减少了锁表的影响,比如让主库负责写,当主库出现写锁的时候,不会影响到从库进行 SELECT 的读取。
b.数据备份
通过主从复制将主库上的数据复制到了从库上,相当于是一种热备份机制,也就是在主库正常运行的情况下进行的备份,不会影响到服务。
c.具有高可用性
数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,也就是当服务器出现故障或宕机的情况下,可以切换到从服务器上,保证服务的正常运行。
16,主从同步的原理是怎样的
Binlog 二进制日志,它记录了对数据库进行更新的事件。(它虽然叫二进制日志,实际上存储的是一个又一个事件(Event),这些事件分别对应着数据库的更新操作,比如 INSERT、UPDATE、DELETE 等。)实际上主从同步的原理就是基于 Binlog 进行数据同步的。在主从复制过程中,会基于 3 个线程来操作,一个主库线程,两个从库线程。
二进制日志转储线程(Binlog dump thread)是一个主库线程。当从库线程连接的时候,主库可以将二进制日志发送给从库,当主库读取事件的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。
从库 I/O 线程会连接到主库,向主库发送请求更新 Binlog。这时从库的 I/O 线程就可以读取到主库的二进制日志转储线程发送的 Binlog 更新部分,并且拷贝到本地形成中继日志(Relay log)。从库 SQL 线程会读取从库中的中继日志,并且执行日志中的事件,从而将从库中的数据与主库保持同步。
网友评论