一、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都是用于过滤:
SELECT department, SUM(salary)
FROM employees
WHERE hire_date >= '2020-01-01'
GROUP BY department
HAVING SUM(salary) > 50000;
区别在于:
1、where用于group by之前对数据进行过滤,having用于group by之后对数据进行过滤
2、where不能对聚合函数进行筛选,having可以对聚合函数进行筛选
5、exists和in的区别是什么
select * from A where id in (select id from B);
select * from A where exists (select 1 from where A.id = B.id);
以上一个用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来说性能差,同样查询性能也不稳定,存在极端情况下,查询性能退化成链表的情况