第五章:数据查询基础 (DQL) —— SQL 的核心力量
核心摘要DQL (Data Query Language) 是 SQL 语言中最复杂、最灵活也是对性能影响最大的部分。本章将带你从“会写 SELECT”进化到“理解 SQL 执行原理”。我们将深入探讨SELECT *的性能隐患、NULL值的逻辑陷阱、模糊查询的索引失效问题以及深分页 (Deep Paging)的性能杀手与优化方案。环境准备请确保已执行前几章的建表语句。为了方便演示查询我们将先初始化一批更丰富的测试数据。5.0 数据准备 (Data Seeding)为了让查询结果更有说服力我们需要往products表里多塞点数据。USEshop_biz;-- 清空表慎用仅限测试环境TRUNCATETABLEproducts;-- 插入多条不同类型的商品数据INSERTINTOproducts(sku_code,product_name,price,stock_qty,status,created_at)VALUES(IPHONE13,iPhone 13 128G 黑色,4999.00,100,1,2023-01-01 10:00:00),(IPHONE14,iPhone 14 256G 紫色,5999.00,50,1,2023-02-01 12:00:00),(XM_13,Xiaomi 13 Pro,3999.00,200,1,2023-03-01 09:00:00),(XM_REDMI,Redmi K60,1999.00,500,1,2023-03-15 14:00:00),(DELL_XPS,Dell XPS 13 Laptop,8999.00,20,1,2023-04-01 08:00:00),(LOGI_M590,Logitech M590 Mouse,159.00,1000,1,2023-05-01 11:00:00),(KEY_K3,Keychron K3 Keyboard,499.00,300,0,2023-06-01 16:00:00),-- status0 下架(TEST_NULL,残次品数据,0.00,0,0,NULL);-- 故意留 NULL 用于测试5.1 基础查询 (Basic Query)5.1.1SELECT *的原罪-- 偷懒写法查询所有字段SELECT*FROMproducts;为什么禁止在生产环境代码中使用SELECT *网络 I/O 浪费如果表里有TEXT或JSON大字段即使你不需要它们也会被传输消耗带宽。覆盖索引 (Covering Index) 失效如果只查SELECT id, price FROM productsMySQL 可以直接从索引树上拿数据不需要回表回表意味着随机磁盘 I/O。写了*就必须回表。Schema 变更风险如果应用层代码依赖字段顺序如row[2]数据库加减字段会导致代码崩溃。正确写法-- 按需查询指定列名SELECTsku_code,product_name,priceFROMproducts;5.1.2 别名 (Alias) 的艺术别名不仅仅是为了少打字更是为了代码的可读性和多表关联时的消歧义。SELECTproduct_nameASname,-- 列别名前端展示可能直接用这个 keyprice*stock_qtyAStotal_value-- 计算字段必须给别名否则结果集列名会很乱FROMproductsASp;-- 表别名常用于 Join 查询5.1.3 去重 (DISTINCT) 的代价-- 查询所有的商品价格档位SELECTDISTINCTpriceFROMproducts;底层原理DISTINCT会让 MySQL 对结果集进行排序或建立临时表来去重。在大数据量下这是一个非常消耗 CPU 和内存Sort Buffer的操作。优化建议如果业务允许尽量在应用层Java/Python去重或者通过GROUP BY优化。5.2 条件查询 (WHERE) —— 数据的过滤器5.2.1 比较与逻辑运算SELECT*FROMproductsWHEREprice2000-- 价格大于等于 2000ANDstatus1-- 且 状态为上架ANDstock_qty100;-- 且 库存紧张5.2.2NULL的陷阱 —— 必须掌握的知识点在 SQL 中NULL代表“未知”。任何与 NULL 进行的算术比较, !, , 结果都是 NULL即 False。-- 错误写法这查不到 created_at 为 NULL 的记录SELECT*FROMproductsWHEREcreated_atNULL;-- 正确写法使用 IS NULL / IS NOT NULLSELECT*FROMproductsWHEREcreated_atISNULL;实战思考这就是为什么我们在第三章建表时强烈建议字段NOT NULL DEFAULT 。NULL不仅让代码逻辑变复杂必须特判还会影响索引效率。5.2.3 模糊查询 (LIKE) 与索引失效-- 1. 前缀匹配推荐可以使用索引-- 查找所有以 iPhone 开头的商品SELECT*FROMproductsWHEREproduct_nameLIKEiPhone%;-- 2. 后缀匹配/全模糊性能杀手索引失效-- 查找名字里包含 Pro 的商品SELECT*FROMproductsWHEREproduct_nameLIKE%Pro%;原理B 树索引是按照字母顺序排列的。iPhone%我知道去索引树的哪里找找 I 开头的。%Pro%我怎么知道它在开头、中间还是结尾只能全表扫描 (Full Table Scan)。注对于 5.7 版本全模糊搜索建议使用 Full Text Index全文索引或 ElasticSearch。5.3 排序 (ORDER BY) 与 SQL 执行顺序5.3.1 多字段排序-- 先按状态排序上架的在前再按价格从高到低排SELECTproduct_name,price,statusFROMproductsORDERBYstatusDESC,priceDESC;5.3.2 SQL 执行顺序之谜初学者常遇到的报错-- 错误Unknown column total in where clauseSELECTprice*stock_qtyAStotalFROMproductsWHEREtotal10000;为什么报错这涉及 SQL 的逻辑执行顺序FROM(找到表)WHERE(过滤行) -- 此时total还没算出来呢GROUP BYHAVINGSELECT(计算列、生成别名) -- 这里才生成totalORDER BY(排序) -- 所以 ORDER BY 可以用别名LIMIT修正-- 写法 1WHERE 里重复计算逻辑SELECTprice*stock_qtyAStotalFROMproductsWHEREprice*stock_qty10000;-- 写法 2 (高级)用 HAVING (通常配合 GROUP BY但此处也能用但不推荐)-- 写法 3 (推荐)嵌套子查询 (Derived Table)SELECT*FROM(SELECTprice*stock_qtyAStotalFROMproducts)AStWHEREt.total10000;5.4 分页查询 (LIMIT) —— 性能优化的深水区5.4.1 基础分页MySQL 的分页语法很简单LIMIT offset, count-- 第 1 页每页 2 条SELECT*FROMproductsLIMIT0,2;-- 第 2 页每页 2 条 (跳过前2条取2条)SELECT*FROMproductsLIMIT2,2;-- 第 3 页SELECT*FROMproductsLIMIT4,2;5.4.2 深分页 (Deep Paging) 性能问题当你的数据量达到百万级时翻到第 100 万页会发生什么-- 极其慢可能需要几秒甚至几十秒SELECT*FROMproductsLIMIT1000000,10;原理MySQL 执行LIMIT 1000000, 10的逻辑是先扫描读取 1,000,010 行数据。抛弃前 1,000,000 行。返回最后 10 行。这意味着大量的磁盘 I/O 和 CPU 浪费。5.4.3 优化方案延迟关联 (Deferred Join)我们利用覆盖索引先只查主键 ID速度快再通过 ID 回表查完整数据。SELECTp.*FROMproducts pINNERJOIN(-- 子查询只查主键利用覆盖索引不用回表速度极快SELECTproduct_idFROMproductsLIMIT1000000,10)AStmpONp.product_idtmp.product_id;或者如果 ID 是连续且递增的且无 WHERE 条件可以使用游标法-- 记录上一页最后一条的 ID (last_id)SELECT*FROMproductsWHEREproduct_id1000000LIMIT10;这种方式性能最好O(1)但只适用于特定场景。5.5 综合案例构建商品搜索列表我们将模拟一个电商后台的商品搜索接口 SQL。需求搜索名称包含 “iPhone” 的商品。状态必须是上架 (status1)。价格在 4000 到 8000 之间。按创建时间倒序排列。查询第 1 页每页 10 条。SELECTproduct_id,sku_code,product_name,price,created_atFROMproductsWHEREstatus1ANDpriceBETWEEN4000AND8000ANDproduct_nameLIKEiPhone%-- 注意把模糊匹配放在最后或者利用最左前缀ORDERBYcreated_atDESCLIMIT0,10;索引设计思考预告为了让这条 SQL 跑得快我们可能需要创建一个联合索引INDEX idx_status_price_created (status, price, created_at)关于索引的详细设计我们将在第八章深入探讨通过本章你已经掌握了从单表获取数据的核心能力。但真实世界的数据往往分散在多张表中如何把它们拼起来下一章我们将解锁 SQL 最强大的功能多表连接 (Joins) 与 高级查询。

相关新闻

[pta]L2-002 链表去重

[pta]L2-002 链表去重

L2-002 链表去重分数 25作者 陈越单位 浙江大学给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→…

2026/7/3 14:24:24 阅读更多 →
【Linux系统】进程间通信:基于匿名管道实现进程池

【Linux系统】进程间通信:基于匿名管道实现进程池

1. 进程池介绍 ​ 1.1 核心定义 进程池(Process Pool) 是一种预创建复用式的进程管理技术,其本质是操作系统中预分配的进程资源容器。它包含两大核心组件: 资源进程:池中预先创建的空闲进程,随时待命执…

2026/7/2 22:16:06 阅读更多 →
Java Web +乡政府管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

Java Web +乡政府管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展,乡镇政府管理工作的信息化需求日益增长。传统的乡镇政府管理模式依赖纸质文档和人工操作,效率低下且容易出错,难以满足现代化管理的需求。特别是在乡村振兴战略背景下,乡镇政府需要更高效、透明和便…

2026/7/3 14:24:25 阅读更多 →

最新新闻

LeetCode:买卖股票的最佳时机(1-3) - Python

LeetCode:买卖股票的最佳时机(1-3) - Python

121. Best Time to Buy and Sell Stock(买卖股票的最佳时机) 问题描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计…

2026/7/4 18:55:26 阅读更多 →
Git-Crypt与GitPod结合:云端IDE安全开发工作流实践

Git-Crypt与GitPod结合:云端IDE安全开发工作流实践

1. 项目概述:当云端IDE遇上加密仓库作为一名常年和代码、密钥、配置文件打交道的开发者,我深知一个痛点:如何在享受云端开发环境(如Gitpod)带来的极致便利时,又能确保敏感信息(如API密钥、数据库…

2026/7/4 18:53:26 阅读更多 →
高效率AI写专著:实用工具合集,轻松产出20万字优质专著!

高效率AI写专著:实用工具合集,轻松产出20万字优质专著!

学术专著写作难题与AI工具解决方案 对于那些第一次尝试撰写学术专著的研究者而言,写作过程就像一场在未知领域探险的旅程,充满了各式各样的挑战。选题的困扰让人感到无从下手,如何在“有意义”和“可行性”之间找到一个合适的平衡点成了难题…

2026/7/4 18:53:26 阅读更多 →
STM32F405RG与25CSM04 EEPROM的高效数据检索方案

STM32F405RG与25CSM04 EEPROM的高效数据检索方案

1. 项目背景与核心需求在嵌入式系统开发中,快速精确的数据检索是一个永恒的话题。当我们需要在资源受限的环境中实现高效数据存取时,选择合适的存储器件和控制器至关重要。25CSM04作为一款4Mbit的SPI接口EEPROM,与STM32F405RG这款高性能ARM C…

2026/7/4 18:49:25 阅读更多 →
Java面试通关⑨:SpringBoot核心全集

Java面试通关⑨:SpringBoot核心全集

📖 前言导读 SpringBoot是目前Java后端项目主流开发框架、面试高频核心考点,几乎所有企业新项目均基于SpringBoot搭建,是后端开发必备核心技能。多数开发者仅会简单引入依赖、编写业务代码,对SpringBoot自动配置原理、Starter机制…

2026/7/4 18:49:25 阅读更多 →
音乐情绪识别实战:从声学特征到VA坐标系的端到端落地

音乐情绪识别实战:从声学特征到VA坐标系的端到端落地

1. 这不是科幻,是正在发生的音乐情绪解码实践“Can AI Recognize Our Emotions Through the Music We Are Listening To?”——这个标题乍看像一篇哲学思辨或心理学论文的提问,但在我过去三年深度参与多个音频智能分析项目后,它早已不是假设…

2026/7/4 18:47:24 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻