一、SQL 语法题
1、Count 主键和 Count 非主键结果会不同吗
结果可能会不同,原因在于 count 只统计非空值,而主键不能存储 NULL 值,非主键可能存储 NULL 值,因此统计结果可能不一样。
延伸:从性能上:count (*) = count (1) > count (主键)> count (字段)
原因如下:
count (*) 和 count (1) 性能相同的原因在于 mysql 做了特殊处理:
InnoDB handles SELECT COUNT(\*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
count (1) 比 count (主键) 性能更好的原因在于,count 主键的时候,要读取主键的数据,并且判断是否为 NULL(实际上我理解如果 mysql 做一点特殊处理,判断出 count 的是主键的时候,当成 count (1) 处理,应该性能就和 count (1) 相同了,而且因为主键没有 NULL,所以结果也是相同的。)
count (主键) > count (普通字段)这点我有点存疑:因为 count 普通字段性能好不好我理解是要看有没有索引,如果有索引,直接扫描索引就能 count 了,性能就会好不少。对于主键字段,如果没有其他的二级索引,那只能扫描主键索引,扫描主键索引和扫描全表,感觉差不多了吧。
补充:(后来问了关于微软 Copilot 关于这里,微软说全表扫描的性能还是要比扫描主键索引性能要差一点的)
2、Mysql 内连接和外连接有什么区别
1、内连接只返回两个表共有的数据
2、外连接分为两种:左外连接和右外连接,左外连接保留语法中左表中所有的数据,右表中没有的数据用 NULL 填充;右外连接保留语法中右表中的所有数据,左表中没有的数据用 NULL 填充;
3、外连接时,on 和 where 有什么区别
where 会把两张表中不符合条件的结果都过滤掉,相当于是内连接;on 的话,是先连接,然后如果后面接着 where,才会用 where 过滤条件,on 在作为连接条件的时候,如果是外连接,会保留驱动表中的所有记录,即使在被驱动表中没有相匹配的记录。
4、having 和 where 的区别
having 和 where 都是用于过滤:
区别在于:
1、where 用于 group by 之前对数据进行过滤,having 用于 group by 之后对数据进行过滤
2、where 不能对聚合函数进行筛选,having 可以对聚合函数进行筛选
5、exists 和 in 的区别是什么
以上一个用 in,一个用 exists,结果相同,性能不同;
A 称为外表,B 称为内表:
内表数据多的时候,用 exists,性能更好,因为不用挨个匹配 B 中的数据
内表数据少的时候,用 in 性能更好,因为不用对于 A 中每一条结果再去查询一次 B 数据库
6、mysql 约束有哪些
1、主键约束:用于唯一标记一条数据,不能重复、不能为 NULL,可以是一个字段,也可以是多个字段复合
2、外键约束:一个表中的外键对于另外一张表的主键。外键是可以重复的,也可以为空。
3、唯一性约束:标记某个字段不能重复
4、非空约束:标记某个字段不能为空
5、默认约束:字段的默认值,在插入数据的时候,如果没有指定字段的值,那么会给字段一个默认的值
6、检查约束:mysql 不支持,如果一定要用检查约束,需要使用触发器或视图
7、delete、drop、truncate 有什么区别
1、delete 记录的时候,只是把该记录标记为已删除,并不会吧磁盘空间回收,所以磁盘文件大小是不会变的,而且用 delete 删除全表,性能会很慢。因为删除一条记录之前,需要先记录 undo log,然后 redo log 要记录 undo log 页的变更,然后 msyql 的 server 层还要记录 binlog,所以很慢。
2、drop 直接把表删除了,在 mysql 里面会把.frm 和.idb 两个文件都删除,表结构也不在了,如果想恢复数据,只能去 server 层找 binlog 了。
3、truncate 最终的效果与先 drop 再创建一张空表类似。truncate 删除的数据,也只能去用 binlog 恢复了。
8、联合查询中 union 和 union all 的区别是什么
union 会去除重复的行;
union all 不会去除重复的行;
所以 union 的性能可能差一点,因为去重很消耗性能。
三、索引结构
1、Mysql 有哪些索引类型
根据数据结构分:B + 树索引、fulltext 索引、hash 索引(memory 引擎)
按物理存储:主键索引、二级索引
按字段特性:唯一索引、前缀索引、普通索引、主键索引
按字段个数:单列索引、联合索引
2、InnoDB 引擎的索引数据结构是什么
B + 树
1、数据组织形式:主键索引 B + 树的非叶子节点只存放索引键值和指向子节点的指针,不存储实际数据,叶子节点存储索引键值和行数据
2、叶子节点链表:所有叶子节点通过指针相连、形成一个双向链表,支持快速的顺序访问和范围查询
3、平衡树结构:所有叶子节点在同一层上,树的高度平衡,保证任何数据记录的查找、插入、删除和更新操作的路径长度相同 ,稳定性好
3、B + 树的特性是什么
重点:
1、叶子节点存储索引 + 数据,非叶子节点只存储索引键值,不存储数据
2、叶子节点之间用双向链表组织
B + 树是一个多叉树,一个父节点对应多个子节点,主要特性有三个:
1、B + 树的非叶子节点不会存储数据,叶子节点才会存储数据,中间节点只用于存储到叶子结点的路由信息(即索引),而且每个节点里的数据都是根据索引的值来顺序存放的
2、B + 树所有的叶子节点之间会通过双向指针串联在一起,构成一个双向链表,方便扫表和范围查询
3、B + 树查询稳定,因为所有叶子节点都在同一层,确保了所有数据项的检索都具有相同的 I/O 延迟。B + 树存储千万级别的数据,B + 树的数据高度也只有 3~4 层,可以大幅减少磁盘 I/O 操作次数。
4、B + 树和 B 树有什么区别
B + 树和 B 树最大的区别在于 B + 树所有的数据都存放在叶子节点中,并且叶子节点通过双向指针串联成双向链表。而 B 树的非叶子节点也存放数据,也没有组织成双向链表。
1、由于 B + 树有双向链表,所以很容易实现范围查找,而 B 树要通过中序遍历实现范围查找,显然中序查找的磁盘 I/O 操作次数会多很多。
2、B + 树查询性能稳定,因为最后都要到叶子节点才能把数据返回,而 B 树查询性能不稳定,可能在非叶子节点就找到数据就返回了。另外还有一点,就是因为 B + 树的非叶子节点只存储索引,这样体积小很多,这样在定位数据的过程中,就避免了读入很多无用的数据记录,同时,减少了磁盘的 I/O 操作开销。
5、mysql 为什么用 B + 树
1、对比于红黑树,B + 树的高度更小,这样对应的磁盘 I/O 操作次数也少,可以大幅减少磁盘 I/O 开销
2、相比于 B 树,B + 支持范围查找
3、相比于跳表:跳表的多级列表高度也是有点高的,对于磁盘 I/O 来说性能差,同样查询性能也不稳定,存在极端情况下,查询性能退化成链表的情况