SQL面试实战地图:50题背后的数据库思维与性能真相

发布时间:2026/9/18 8:31:31

SQL面试实战地图:50题背后的数据库思维与性能真相 1. 这不是题库是SQL面试的实战地图我带过三十多届校招和社招面试从初级开发到架构师岗每年筛掉的简历里80%在SQL环节卡死——不是不会写SELECT而是根本没搞懂“面试官到底想看什么”。很多人把“SQL面试必会50题”当成刷题清单背答案、抄解析、临阵抱佛脚结果一进面试间就被一句“你这道题的执行计划怎么画”问得哑口无言。其实这50题根本不是考你能不能写出正确语句而是用50个典型切口检验你对数据模型的理解深度、对查询逻辑的拆解能力、对性能边界的直觉判断以及——最关键的——你是否具备真实业务场景中调试慢查询、重构冗余逻辑、规避隐式转换的实操经验。核心关键词SQL、面试、50题、答案、学习链接表面是知识点罗列背后是一套完整的数据库思维训练体系从单表过滤的WHERE执行顺序到多表JOIN时驱动表选择对性能的千倍影响从GROUP BY聚合时NULL值的特殊处理到窗口函数中ORDER BY与ROWS BETWEEN的微妙差异从INSERT INTO SELECT的事务一致性风险到DELETE无WHERE条件的线上事故复盘。这些题目不是孤立的语法练习而是50个微型业务场景的快照——电商订单状态流转、用户行为漏斗分析、金融交易对账校验、物流轨迹时间序列统计……每一道题都对应着真实系统里一个可能出问题的节点。适合谁如果你是刚学完《SQL必知必会》准备投简历的应届生这套题能帮你绕过“理论懂但写不出”的陷阱如果你是工作2-3年、总被DBA叫去优化慢SQL的后端工程师它能帮你补上执行计划、索引下推、统计信息这些被忽略的底层逻辑如果你是转行做数据分析的运营/产品它能让你真正理解“为什么这个指标要这样算”而不是只会复制粘贴报表SQL。我见过太多人花三个月刷完500道题却在面试时连EXPLAIN输出里的typeALL和typeref的区别都说不清——因为没把题目当“线索”只当“答案”。2. 题目设计逻辑50道题如何覆盖SQL面试全战场2.1 不是随机堆砌而是按能力维度分层建模市面上很多“SQL面试题集”把题目按难度标为“简单/中等/困难”但实际面试中难度标签毫无意义。真正决定你能否过关的是能力维度的覆盖完整性。这50题严格按四个能力层递进设计第一层语法肌肉记忆1-15题聚焦基础语法的“零容错”能力。比如第3题“查询所有学生的姓名、学号、课程名、成绩”看似简单但考察点在于是否意识到SELECT *在多表JOIN时字段重复的风险是否习惯用表别名避免歧义是否知道MySQL 5.7默认开启ONLY_FULL_GROUP_BY导致GROUP BY后SELECT非聚合字段直接报错这类题不考技巧考的是日常编码形成的肌肉反射——就像程序员写for循环从不加括号一样自然。第二层逻辑拆解能力16-30题进入真实业务复杂度。典型如第22题“找出每个部门工资最高的员工含并列”。新手直接写MAX(salary) GROUP BY dept结果只能返回最高工资数值无法关联员工信息。这里考察的是对“聚合结果与原始行关联”这一核心矛盾的理解要么用窗口函数RANK() OVER(PARTITION BY dept ORDER BY salary DESC)要么用子查询关联要么用LEFT JOIN自连接。三种解法没有优劣但面试官会追问“如果数据量从1万涨到1000万哪种方案执行计划更优为什么”——这已经跳出了语法进入执行引擎层面。第三层性能敏感度31-42题直接暴露线上事故高频雷区。第35题“查询近30天未登录的用户”常被写成WHERE last_login_time DATE_SUB(NOW(), INTERVAL 30 DAY)但若last_login_time字段无索引或存在大量NULL值会导致全表扫描。更致命的是第38题“用IN查询1000个ID”很多人不知道MySQL 5.6对IN列表长度有阈值默认1000超限会退化为OR逻辑且无法走索引范围扫描。这些题的答案不重要重要的是你能否说出“我查过执行计划发现typeALL于是给last_login_time加了联合索引覆盖了WHERE和ORDER BY字段”。第四层工程边界意识43-50题检验你是否具备生产环境思维。第47题“删除订单表中3年前的记录”看似简单但真实场景中必须考虑是否要分批删除避免锁表是否要先备份再删DELETE和TRUNCATE在事务回滚、自增ID重置、触发器执行上的差异第49题“导出身份证号显示为科学计数法”直指数据类型设计缺陷——CHAR(18)和VARCHAR(18)在Excel导入时的行为差异以及前端展示时如何用FORMAT函数强制字符串化。这些题没有标准答案只有“我经历过”的解决方案。2.2 题目来源全部来自真实故障现场这50题里32道直接脱胎于我处理过的线上事故。比如第18题“统计每个商品类目的销量TOP3”源于某电商大促期间报表服务超时DBA抓到慢SQL发现是窗口函数未加索引导致排序耗尽内存第27题“查询连续登录7天的用户”来自某社交App用户留存分析需求最初用自连接实现单日数据量2亿时执行超40分钟最终改用LAG()函数日期差计算耗时压到3秒内第41题“UPDATE多字段时部分失败如何回滚”源自某支付系统因网络抖动导致金额更新成功但状态未更新引发资金差错。每道题的答案里都藏着一个“当时我们怎么定位的”故事——比如用pt-query-digest分析慢日志用SHOW PROCESSLIST观察锁等待用EXPLAIN FORMATJSON看索引合并策略。2.3 答案设计拒绝“正确就行”强调可验证性所有答案都附带可验证的执行证据而非单纯语法正确。例如第8题“查询选修了‘数学’和‘英语’的学生”常见错误解法是用AND连接两个EXISTS子查询但答案会明确写出-- 正确解法用GROUP BY HAVING COUNT DISTINCT SELECT s.student_id, s.name FROM students s JOIN scores sc ON s.student_id sc.student_id JOIN courses c ON sc.course_id c.course_id WHERE c.course_name IN (数学, 英语) GROUP BY s.student_id, s.name HAVING COUNT(DISTINCT c.course_name) 2;并补充验证步骤“执行EXPLAIN确认typerefkeyidx_course_namerows500对比错误解法的执行计划发现其typeALL且ExtraUsing temporary在100万学生表上实测正确解法耗时0.12s错误解法耗时8.7s”。这种答案设计强迫你关注“为什么这个解法更快”而不是“为什么这个语法没错”。3. 核心细节解析50题背后的12个关键认知盲区3.1 WHERE执行顺序90%的人不知道的隐式转换陷阱几乎所有SQL教程都告诉你“WHERE在FROM之后执行”但没人讲清WHERE内部的运算优先级如何影响索引使用。第5题“查询手机号以‘138’开头的用户”常见写法SELECT * FROM users WHERE SUBSTR(phone, 1, 3) 138;这会导致全表扫描因为SUBSTR是函数对phone字段施加函数后即使phone有索引也无法使用。正确解法是SELECT * FROM users WHERE phone LIKE 138%;但这里埋着第二个坑如果phone字段是VARCHAR(11)而传入参数是CHAR(3)MySQL会进行字符集隐式转换可能导致索引失效。实测案例某次上线后慢查询突增排查发现DBA将phone字段从utf8mb4改为utf8而应用层传参仍是utf8mb4导致WHERE条件隐式转换执行计划从typerange退化为typeALL。提示用EXPLAIN EXTENDED SHOW WARNINGS查看隐式转换警告。真正的高手会在建表时就约定手机号统一用CHAR(11)存储避免变长字段带来的排序开销。3.2 JOIN驱动表选择小表驱动大表不是教条是成本计算第12题“查询订单及其用户信息”标准写法SELECT o.order_id, u.user_name FROM orders o JOIN users u ON o.user_id u.user_id;但面试官会追问“如果orders表1000万行users表10万行这个JOIN会怎么执行”很多人答“小表驱动大表”这是错误认知。MySQL的BNLJBlock Nested-Loop Join算法中驱动表选择取决于WHERE条件过滤后的行数而非原始表大小。如果WHERE先过滤orders表得到100行那么orders就是驱动表如果WHERE只过滤users表得到100行则users是驱动表。验证方法在EXPLAIN中看两表的rows值较小者即为实际驱动表。实操心得我在线上优化过一个报表SQL原写法是LEFT JOIN大表导致驱动表错误。改成先用子查询过滤大表再JOIN执行时间从23秒降到0.8秒。关键不是记住“小表驱动”而是学会看执行计划里的rows预估。3.3 GROUP BY的隐式排序MySQL 5.7 vs 8.0的兼容性断崖第25题“按部门统计平均工资并降序排列”很多人写SELECT dept, AVG(salary) FROM employees GROUP BY dept ORDER BY AVG(salary) DESC;在MySQL 5.7上能跑在8.0会报错“Expression #1 of ORDER BY clause is not in GROUP BY clause”。这是因为8.0默认开启sql_modeONLY_FULL_GROUP_BY要求ORDER BY字段必须在GROUP BY中出现或为聚合函数。解决方案不是关掉模式而是显式声明SELECT dept, AVG(salary) as avg_salary FROM employees GROUP BY dept ORDER BY avg_salary DESC;更深层的问题是GROUP BY本身不保证排序很多老代码依赖“GROUP BY后自然有序”这在MySQL 5.7是偶然在8.0是幻觉。真实场景中某金融系统升级MySQL 8.0后对账报表因GROUP BY结果乱序导致资金核对失败。3.4 窗口函数的ROWS BETWEEN陷阱时间范围计算的精度丢失第33题“计算每个用户最近3次订单的平均金额”正确解法SELECT user_id, order_amount, AVG(order_amount) OVER ( PARTITION BY user_id ORDER BY order_time ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) as avg_3_orders FROM orders;但这里有个致命细节ROWS BETWEEN是按物理行数计算不是按时间范围。如果用户某天下了10单另两天各1单那么“最近3次”可能全是同一天的订单完全偏离业务需求。正确解法必须用RANGEAVG(order_amount) OVER ( PARTITION BY user_id ORDER BY UNIX_TIMESTAMP(order_time) RANGE BETWEEN 259200 PRECEDING AND CURRENT ROW -- 3天259200秒 )然而RANGE在MySQL 8.0.22才支持低版本需用自连接模拟。这个细节暴露出一个普遍误区把窗口函数当万能药却忽略其底层实现机制。3.5 NULL值的三值逻辑WHERE条件中的隐形杀手第7题“查询未填写邮箱的用户”错误写法SELECT * FROM users WHERE email NULL;这永远返回空集因为NULL参与任何比较都返回UNKNOWN而WHERE只接受TRUE。正确写法是SELECT * FROM users WHERE email IS NULL;但更隐蔽的陷阱在第19题“统计有邮箱和无邮箱用户的占比”如果用COUNT(email)/COUNT(*)计算COUNT(email)会自动忽略NULL结果看似正确。但如果业务要求“邮箱为空字符串也算未填写”则需SELECT COUNT(CASE WHEN email IS NULL OR email THEN 1 END) / COUNT(*) as null_ratio FROM users;我在某CRM系统遇到过类似问题销售录入时习惯填空格导致IS NULL查不到但LENGTH(TRIM(email))0才能捕获。NULL处理不是语法问题是业务语义理解问题。3.6 子查询的执行时机相关子查询的N1性能黑洞第29题“查询每个部门工资高于部门平均工资的员工”常见解法SELECT e1.name, e1.salary, e1.dept FROM employees e1 WHERE e1.salary ( SELECT AVG(e2.salary) FROM employees e2 WHERE e2.dept e1.dept );这是相关子查询对e1的每一行都要执行一次子查询。如果e1有10万行子查询执行10万次正确解法是用JOINSELECT e.name, e.salary, e.dept FROM employees e JOIN ( SELECT dept, AVG(salary) as avg_salary FROM employees GROUP BY dept ) dept_avg ON e.dept dept_avg.dept WHERE e.salary dept_avg.avg_salary;实测数据10万员工表相关子查询耗时42秒JOIN解法耗时0.3秒。这个案例说明子查询不是不能用而是要清楚它的执行模型——相关子查询是嵌套循环非相关子查询才可能被优化为哈希连接。3.7 LIMIT OFFSET的深分页灾难为什么第10000页查询慢如蜗牛第45题“分页查询订单列表”很多人写SELECT * FROM orders ORDER BY create_time DESC LIMIT 10000, 20;当OFFSET10000时MySQL必须先扫描前10000行再取20行I/O成本线性增长。真实案例某电商平台订单页跳转到第500页时响应时间超15秒。解决方案不是加索引而是用游标分页SELECT * FROM orders WHERE create_time 2023-01-01 00:00:00 ORDER BY create_time DESC LIMIT 20;用上一页最后一条记录的时间戳作为下一页的WHERE条件避免OFFSET。这个技巧在面试中极少被提及却是高并发系统的标配。3.8 INSERT SELECT的事务隔离为什么批量插入会锁表第48题“将用户表数据迁移到新表”写法INSERT INTO users_new SELECT * FROM users;在InnoDB中这会持有源表的读锁和目标表的写锁且锁持续到事务结束。如果users表有1亿行整个过程可能锁表数小时。安全做法是分批INSERT INTO users_new SELECT * FROM users WHERE id BETWEEN 1 AND 10000; -- 循环执行每次处理1万行更优方案是用pt-archiver工具它能自动控制事务大小、监控复制延迟、避免主从同步中断。3.9 字符集与排序规则中文排序的诡异现象第11题“按姓名拼音首字母分组统计”很多人用ORDER BY name COLLATE utf8mb4_unicode_ci却发现“张”排在“王”前面。这是因为Unicode排序规则对中文按Unicode码点排序而非拼音。正确解法是创建拼音列ALTER TABLE users ADD COLUMN name_pinyin VARCHAR(100) GENERATED ALWAYS AS (pinyin(name)) STORED; CREATE INDEX idx_name_pinyin ON users(name_pinyin);用pinyin()函数需安装mysql-pinyin插件生成拼音再按拼音排序。这个细节暴露了数据库设计的基本功字符集选择不是为了存汉字而是为了高效检索。3.10 统计信息过期为什么执行计划突然变差第37题“优化一个原本很快的查询”答案往往指向统计信息。MySQL的优化器依赖information_schema.STATISTICS表中的cardinality值估算行数。当表数据变更超过10%默认阈值统计信息可能过期。验证命令SHOW INDEX FROM orders; -- 查看Cardinality值 ANALYZE TABLE orders; -- 手动更新统计信息某次线上事故营销活动导致订单表单日新增500万行统计信息未更新优化器误判WHERE条件过滤率90%选择全表扫描而非索引QPS暴跌。DBA执行ANALYZE后立即恢复。3.11 隐式类型转换数字与字符串比较的性能雪崩第14题“查询id为123的用户”如果id字段是VARCHAR而传参是数字123MySQL会把所有id转为数字再比较SELECT * FROM users WHERE id 123; -- id是VARCHAR(20)这导致索引失效因为索引是按字符串排序的转换后无法利用B树结构。正确做法是传参时加引号SELECT * FROM users WHERE id 123;更彻底的方案是在建表时约定主键ID一律用BIGINT避免字符串ID带来的所有隐患。3.12 SQL注入的本质不是拼接字符串是语法结构破坏第50题“防止SQL注入”标准答案是参数化查询。但很多人不理解为什么// 危险写法 String sql SELECT * FROM users WHERE name name ; // 安全写法 String sql SELECT * FROM users WHERE name ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, name);本质区别在于前者把用户输入当作SQL语法的一部分后者把用户输入当作数据值。当nameadmin OR 11时危险写法会变成SELECT * FROM users WHERE name admin OR 11而安全写法中?被替换为字符串字面量OR条件不会被执行。这个原理决定了任何动态拼接SQL的地方如MyBatis的${}都是高危点而#{}才是安全的。4. 实操过程从题目到落地的完整闭环4.1 环境准备为什么必须用MySQL 8.0而非SQL Server 2008 R2网络热词里频繁出现“sql server 2008 r2下载”、“sql server 2019安装教程”但我要明确说不要用SQL Server 2008 R2练这50题。原因有三窗口函数支持残缺2008 R2不支持ROW_NUMBER()、RANK()等核心窗口函数而50题中12道涉及窗口函数如第33、36、40题。强行用子查询模拟代码复杂度翻倍且无法体现现代SQL的表达力。执行计划解读困难SQL Server的Execution Plan XML结构比MySQL的EXPLAIN复杂得多初学者难以快速定位typeALL、keynull等关键指标。MySQL的EXPLAIN输出简洁直观rows、key、Extra字段一目了然。社区资源断层当前主流技术栈阿里云PolarDB、腾讯云TDSQL、美团Leaf均基于MySQL生态SQL Server更多用于传统企业ERP。练SQL Server 2008 R2相当于用诺基亚功能机学5G通信原理。推荐环境Docker一键部署MySQL 8.0.32docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD123456 \ -v /data/mysql:/var/lib/mysql \ -d mysql:8.0.32配套工具MySQL Workbench可视化执行计划、pt-query-digest慢日志分析、sys schema性能诊断视图。4.2 题目实操四步法从写对到写好每道题的实操必须经历四个阶段缺一不可阶段一语法通关5分钟目标写出能返回正确结果的SQL。不追求最优先跑通。例如第1题“查询所有学生信息”直接写SELECT * FROM students验证表结构和数据。阶段二执行计划验证10分钟目标用EXPLAIN确认执行路径。重点检查type字段ALL全表扫描→ 需优化ref索引查找→ 合理const主键查询→ 最优key字段是否命中预期索引rows字段预估扫描行数是否符合数据分布Extra字段出现Using filesort或Using temporary需警惕阶段三压力测试15分钟目标用真实数据量验证性能。本地生成10万行测试数据-- 生成students测试表 CREATE TABLE students_test AS SELECT * FROM students LIMIT 0; INSERT INTO students_test SELECT id100000, CONCAT(stu, id100000), FLOOR(RAND()*100) FROM students a JOIN students b LIMIT 100000;执行SQL用SELECT BENCHMARK(1000000, (SELECT ...))模拟高并发。阶段四线上对标20分钟目标对照生产环境同类SQL。例如第22题“部门最高薪员工”找到线上报表SQL对比执行计划、QPS、慢查询占比。我的经验是把50题答案打印出来贴在显示器边框每次写业务SQL前对照检查——是否用了窗口函数替代自连接是否加了必要的索引提示是否规避了隐式转换4.3 关键题型实操详解以第22、33、47题为例第22题每个部门工资最高的员工含并列错误解法GROUP BY陷阱SELECT dept, MAX(salary) FROM employees GROUP BY dept; -- 只返回工资数值丢失员工姓名正确解法一窗口函数推荐SELECT dept, name, salary FROM ( SELECT dept, name, salary, RANK() OVER (PARTITION BY dept ORDER BY salary DESC) as rn FROM employees ) t WHERE rn 1;执行计划验证EXPLAIN FORMATJSON显示windowing节点rows10000typeALL因需全表扫描排序但内存排序可控。正确解法二自连接兼容旧版本SELECT e1.dept, e1.name, e1.salary FROM employees e1 LEFT JOIN employees e2 ON e1.dept e2.dept AND e1.salary e2.salary WHERE e2.salary IS NULL;执行计划typeALLe1 typerefe2rows10000*100100万远不如窗口函数。线上对标某HR系统真实SQL用窗口函数后报表生成时间从47秒降至3.2秒DB CPU使用率下降60%。第33题每个用户最近3次订单的平均金额错误解法ROWS BETWEEN失效-- 按物理行数计算业务语义错误 AVG(amount) OVER (PARTITION BY user_id ORDER BY create_time ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)正确解法RANGE时间范围-- MySQL 8.0.22支持 AVG(amount) OVER ( PARTITION BY user_id ORDER BY UNIX_TIMESTAMP(create_time) RANGE BETWEEN 259200 PRECEDING AND CURRENT ROW )降级方案MySQL 5.7SELECT o1.user_id, o1.amount, (SELECT AVG(o2.amount) FROM orders o2 WHERE o2.user_id o1.user_id AND o2.create_time o1.create_time - INTERVAL 3 DAY AND o2.create_time o1.create_time) as avg_3day FROM orders o1;注意此方案需在user_idcreate_time上建联合索引否则子查询全表扫描。第47题删除3年前的订单危险操作单次大事务DELETE FROM orders WHERE create_time DATE_SUB(NOW(), INTERVAL 3 YEAR); -- 可能锁表数小时阻塞所有写操作安全方案分批删除-- 方案1用主键ID分片 DELETE FROM orders WHERE create_time DATE_SUB(NOW(), INTERVAL 3 YEAR) AND id BETWEEN 1 AND 100000; -- 方案2用pt-archiver生产环境首选 pt-archiver --source hlocalhost,Dshop,torders \ --where create_time 2021-01-01 \ --limit 10000 \ --bulk-delete \ --statistics实测数据1亿订单表分批删除每次1万行耗时23分钟全程QPS稳定在1200单次删除耗时47分钟期间QPS跌至200。4.4 学习链接的筛选逻辑为什么只推荐这5个资源网络热词中充斥着“头哥实践教学平台答案”、“头歌操作系统linux答案”等刷题网站但这些资源最大的问题是缺乏执行计划验证和线上对标。我筛选学习链接的三个硬标准必须提供EXPLAIN截图如《MySQL技术内幕InnoDB存储引擎》配套实验每道题都附执行计划对比图。必须有生产环境案例如Percona博客的“Optimizing Slow Queries”直接分析真实慢日志。必须支持交互式验证如db-fiddle.com可在线运行SQL并查看执行计划。推荐链接MySQL官方文档EXPLAIN Output Format —— 唯一权威解释每天读一段PerconaHow to Read EXPLAIN in MySQL —— 用真实慢查询演示db-fiddle.com —— 在线验证50题支持MySQL 8.0MySQL Performance Blog —— 每周更新的性能优化案例《高性能MySQL》第3版第8章 —— 窗口函数和优化器原理的终极指南注意所有链接都经过实测确保能打开且内容未过期。那些标榜“Java面试八股文”、“前端面试”的资源虽然热度高但与SQL深度无关一律排除。5. 常见问题与排查技巧实录面试官最常问的7个灵魂拷问5.1 “这道题你写的SQL在1000万数据量下会慢吗为什么”这是50题中最高频的追问。回答模板先说结论“会慢因为执行计划显示typeALL需要扫描全表”展示证据“这是EXPLAIN输出rows10000000keynull”分析根因“WHERE条件中的date_sub函数导致索引失效”给出方案“改用date字段范围查询并在date字段建索引”验证效果“优化后rows1200耗时从8.2秒降至0.03秒”切忌说“应该不会慢”必须用数据说话。我面试过一个候选人被问第35题时直接掏出手机现场连上公司测试库执行EXPLAIN这种实操感比背答案强十倍。5.2 “如果线上这条SQL突然变慢你怎么排查”标准排查链路确认现象用SHOW PROCESSLIST看是否有长时间运行的查询抓慢日志SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 1;分析执行计划EXPLAIN FORMATJSON看key、rows、Extra检查统计信息SHOW INDEX FROM table_name看Cardinality是否异常验证锁竞争SELECT * FROM performance_schema.events_waits_current WHERE EVENT_NAME LIKE wait/synch/mutex%对比历史用pt-query-digest分析一周慢日志趋势真实案例某次慢查询执行计划显示keyidx_user_id但rows500万。排查发现idx_user_id是单列索引而WHERE条件是user_id123 AND statusactive需改成联合索引(user_id, status)。5.3 “GROUP BY和DISTINCT哪个性能更好”这不是选择题是场景题。答案数据量小1万行DISTINCT略快因无需排序数据量大且有索引GROUP BY更快因可利用索引排序数据量大且无索引两者都慢但GROUP BY的临时表可能更小验证方法在相同数据集上分别执行用SELECT last_insert_id获取执行时间需开启profiling。5.4 “LEFT JOIN和NOT EXISTS哪个更适合查不存在的记录”经典陷阱题。答案LEFT JOIN适合需要返回左表所有字段的场景但右表为NULL时仍会扫描右表NOT EXISTS适合仅需判断存在性的场景可提前终止性能对比10万左表100万右表NOT EXISTS耗时0.15秒LEFT JOIN耗时0.82秒。因为NOT EXISTS在找到第一个匹配就停止而LEFT JOIN必须完成全部连接。5.5 “为什么加了索引查询还是慢”五大原因隐式类型转换如VARCHAR字段传数字参数最左前缀失效联合索引(a,b,c)WHERE只用b和c统计信息过期ANALYZE TABLE未执行索引选择性低性别字段建索引区分度只有2查询返回大量数据SELECT * 导致网络传输瓶颈排查命令-- 查看索引选择性 SELECT COUNT(DISTINCT gender)/COUNT(*) as selectivity FROM users; -- 查看索引是否被使用 SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage WHERE OBJECT_SCHEMAtest AND OBJECT_NAMEusers;5.6 “UNION和UNION ALL什么时候必须用UNION”答案只有需要去重时才用UNION。UNION ALL性能永远优于UNION因为它省去了排序去重步骤。真实场景中90%的UNION都可以换成UNION ALL。例如第16题“查询数学或英语成绩大于90的学生”用UNION ALLSELECT student_id FROM scores WHERE course_id1 AND score90 UNION ALL SELECT student_id FROM scores WHERE course_id2 AND score90;比UNION快3倍且业务上允许同一学生出现两次因为可能两科都90。5.7 “你如何保证写的SQL在不同MySQL版本都兼容”三原则禁用版本特有语法如MySQL 8.0的RANGE窗口函数在5.7用子查询替代显式声明SQL_MODE在连接字符串中加sql_modeSTRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION用标准化工具测试用mysql-test-run脚本在5.7/8.0/8.4三个版本上跑回归测试我的团队实践所有SQL提交前必须通过GitHub Action在三个MySQL版本上执行任一版本失败即阻断合并。6. 实操心得踩过的11个坑比50题答案更值钱6.1 坑1在WHERE中用NOW()函数导致执行计划无法复用写WHERE create_time NOW() - INTERVAL 7 DAY每次执行NOW()值不同MySQL无法缓存执行计划。正确写法SET seven_days_ago NOW() - INTERVAL 7 DAY; SELECT * FROM orders WHERE create_time seven_days_ago;这样执行计划可复用且变量在会话内保持不变。6.2 坑2用COUNT(*)统计行数却忽略NULL值影响COUNT(*)统计所有行COUNT(column)忽略NULL。某次统计用户注册数用COUNT(email)得到98万实际注册用户102万——因为2万用户注册时未填邮箱但email字段允许NULL。正确统计必须用COUNT(*)。6.3 坑3ORDER BY字段未建索引却以为有覆盖索引SELECT id,name FROM users ORDER BY name如果只在name上建
延伸阅读

更多相关文章

2026/9/18 8:31:31

Oracle OPatch 版本管理与补丁升级:从下载到验证的必知细节

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 8:31:31

Agent开发是风口还是深坑?理性看待AI Agent的落地现实

1. 先说结论:这个行当被捧得太高了最近大半年,我身边至少有七八个人问过我同一个问题:“现在学Agent开发是不是风口?我要不要转过去?”他们有的是做前端的老同事,也有刚毕业的后端新人,还有一两…

2026/9/18 9:31:35

DeepSeek Harness v0.5.2 插件加载失败根因与修复指南

1. 项目概述:这不是一个普通插件报错,而是本地大模型工作流的“心脏骤停”你点开 DeepSeek Harness 启动器,界面刚弹出来,底部状态栏突然飘出一行红字:“Plugin loading failed: Cannot resolve module ‘deepseek-har…

2026/9/18 9:31:35

uC/OS-II事件控制块、信号量与互斥量源码实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 9:31:35

VoiceStudio 三段式语音合成:编码器、合成器与声码器实战

有人问我:"手里有几十段自己录的语音,能不能让程序用我的声音念出新稿子?"这类需求这两年冒出来的频率明显变高——做自媒体的想批量出配音,做课程的要给几十节课统一声线,还有人单纯想给家里的老人留下一份…

2026/9/18 9:26:34

open-code-review:用自动化规则引擎终结形式化代码评审

团队里的代码评审,基本就是“看起来没问题,合并吧”。说难听点,大多数人的 review 是在 PR 页面上做一次恐怖片式快进,只关注有没有冲突、测试能不能过,真正的逻辑漏洞、安全隐患、历史包袱,全靠 reviewer …

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/18 0:01:09

Google Colab 实战:运行模型、数据加载与报错排查

1. 为什么我劝你先搞懂 Colab 的运行模型1.1 Colab 到底是什么,跟本地跑代码差在哪Google Colab 简单说就是一台跑在浏览器里的 Linux 虚拟机,你打开一个 Notebook,背后就连上了一台带 GPU 的远程机器。你在单元格里敲的每一行 Python&#x…

2026/9/18 0:01:09

C语言数据类型与表达式详解

1. C语言数据与数据类型概述在C语言编程中,数据是程序处理的核心对象。理解数据的分类和特性是掌握C语言的基础。C语言中的数据主要分为四大类:常量、变量、表达式和函数。这些数据类型构成了C语言程序的基本元素,每种类型都有其独特的特性和…

2026/9/18 0:01:09

SQL时间字段指定时间段查询:区间语义、索引与时区避坑

上周排查一个线上问题&#xff0c;用户反馈"昨天的订单一条都没查到"&#xff0c;但数据库里明明躺着两千多条。最后定位下来&#xff0c;不是数据丢了&#xff0c;也不是接口挂了&#xff0c;而是那个查询条件把时间段写成了> 2024-05-20 00:00:00 AND < 2024…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码