MySQL偏门但基础的面试题集锦
文章目录
- 1. TIMESTAMP和DATETIME的微妙区别?
- 2. VARCHAR(255)和VARCHAR(256)的存储差异?
- 3. COUNT(*)、COUNT(1)、COUNT(字段)的区别?
- 4. LIMIT 1000000, 10为什么这么慢?
- 5. 为什么InnoDB表必须有主键?
- 6. MySQL的隐式类型转换规则?
- 7. DELETE FROM table和TRUNCATE的隐藏区别?
1. TIMESTAMP和DATETIME的微妙区别?
- TIMESTAMP存储UTC时间,会根据当前时区转换显示
- DATETIME存储的是字面值,不受时区影响
- TIMESTAMP范围:1970-2038年,DATETIME范围:1000-9999年
- TIMESTAMP在UPDATE时可以自动更新为当前时间
2. VARCHAR(255)和VARCHAR(256)的存储差异?
-- VARCHAR(255):长度用1字节存储
-- VARCHAR(256):长度用2字节存储
CREATE TABLE test_varchar (col1 VARCHAR(255), -- 最大占用255+1=256字节col2 VARCHAR(256) -- 最大占用256+2=258字节
);
- VARCHAR长度≤255时,用1字节存储长度信息
- VARCHAR长度>255时,用2字节存储长度信息
3. COUNT(*)、COUNT(1)、COUNT(字段)的区别?
CREATE TABLE test_count (id INT,name VARCHAR(50)
);INSERT INTO test_count VALUES
(1, 'Alice'), (2, NULL), (3, 'Bob');SELECT COUNT(*); -- 结果:3
SELECT COUNT(1); -- 结果:3
SELECT COUNT(id); -- 结果:3
SELECT COUNT(name); -- 结果:2(NULL不计入)
- COUNT(*)和COUNT(1)性能相同,都统计行数
- COUNT(字段)会忽略NULL值
- InnoDB中COUNT(*)有优化,会选择最小的索引来计数
4. LIMIT 1000000, 10为什么这么慢?
-- 这个查询需要先排序前1000010条记录,再取最后10条
SELECT * FROM users ORDER BY id LIMIT 1000000, 10;-- 优化方法:使用子查询 + 主键
SELECT * FROM users
WHERE id >= (SELECT id FROM users ORDER BY id LIMIT 1000000, 1)
ORDER BY id LIMIT 10;-- 或者使用游标分页
SELECT * FROM users WHERE id > 1000000 ORDER BY id LIMIT 10;
5. 为什么InnoDB表必须有主键?
-- 创建没有主键的表
CREATE TABLE test_no_pk (name VARCHAR(50),age INT
) ENGINE=InnoDB;-- MySQL会按以下顺序创建隐藏主键:
-- 1. 选择第一个非NULL的UNIQUE索引作为主键
-- 2. 如果没有,创建一个6字节的隐藏rowid字段作为主键
6. MySQL的隐式类型转换规则?
偏门点: 字符串和数字比较的转换规则
SELECT '123' = 123; -- 结果:1(true)
SELECT '123abc' = 123; -- 结果:1(true)!!!
SELECT 'abc123' = 123; -- 结果:0(false)-- 字符串转数字:从左开始,遇到非数字字符停止
SELECT '123.45abc' + 0; -- 结果:123.45
SELECT 'abc123' + 0; -- 结果:0
- 字符串与数字比较时,字符串会转换为数字
- 转换规则:从左开始取数字部分,遇到非数字停止
7. DELETE FROM table和TRUNCATE的隐藏区别?
-- DELETE会触发触发器,TRUNCATE不会
CREATE TRIGGER tr_delete BEFORE DELETE ON test_table
FOR EACH ROW INSERT INTO log_table VALUES(OLD.id);DELETE FROM test_table;
TRUNCATE test_table; -- AUTO_INCREMENT重置行为不同,都会清空表数据
-- DELETE后AUTO_INCREMENT值保持不变
-- TRUNCATE后AUTO_INCREMENT重置为1