WHERE和HAVING有何不同?MySQL索引如何优化?
摘要:WHERE关键字 WHERE的作用 where是在数据分组之前进行过滤 执行流程 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 示例 SELECT * FROM employee
WHERE关键字
WHERE的作用
where是在数据分组之前进行过滤
执行流程
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
示例
SELECT *
FROM employee
WHERE salary > 5000;
含义:先从表中筛选出 salary > 5000 的记录,再返回结果。
HAVING 关键字
HAVING 的作用
HAVING 是在分组之后对聚合结果进行过滤。
示例:
SELECT dept, COUNT(*)
FROM employee
GROUP BY dept
HAVING COUNT(*) > 2;
执行逻辑:先按 dept 分组,计算每组 COUNT(*),再过滤 COUNT(*) > 2
WHERE 和 HAVING 的区别
WHERE 和 HAVING 都是 SQL 中的过滤条件,但它们的作用阶段不同。
区别
WHERE
HAVING
作用阶段
分组前过滤
分组后过滤
是否可以使用聚合函数
不可以
可以
是否必须配合 GROUP BY
不需要
一般需要
为什么 HAVING 需要和 GROUP BY 使用
因为 HAVING 的作用是过滤聚合结果,而聚合结果只有在分组之后才会产生。
常见的聚合函数:
count(*) sum() max() min() AVG()
这些聚合函数必须在分组后才有意义。
执行流程:
1 FROM 找到表
2 WHERE 过滤行数据
3 GROUP BY 分组
4 聚合函数计算
5 HAVING 过滤分组结果
6 SELECT
7 ORDER BY
因此 WHERE 过滤原始数据,HAVING 过滤聚合后的数据
什么时候用 WHERE,什么时候用 HAVING
原则:能用 WHERE 就不要用 HAVING。
原因:WHERE 在分组前过滤,数据量更少,效率更高。
举例:
SELECT dept, COUNT(*)
FROM employee
WHERE salary > 5000
GROUP BY dept
HAVING COUNT(*) > 2;
执行逻辑:
WHERE 先过滤工资 > 5000 的员工
GROUP BY 再分组
HAVING 再过滤部门人数
这样效率更高。
MySQL 的索引
索引是 MySQL 中提升查询效率的核心工具,可以把它理解成书籍的目录—— 没有目录时找内容要逐页翻(全表扫描),有目录时能直接定位到目标页码(快速查询)。
索引的核心作用
加速查询:这是最核心的作用,避免全表扫描,直接定位符合条件的数据。
优化排序/分组:对需要 ORDER BY/GROUP BY 的字段建索引,可避免临时表排序,提升效率。
唯一约束:如主键索引、唯一索引,能保证字段值的唯一性(比如用户手机号不能重复)。
注意:索引会降低插入/更新/删除的效率(因为修改数据时要同步维护索引),所以不是索引越多越好,按需创建即可。
索引的分类
功能分类:主键索引、唯一索引、全文索引、普通索引
数据结构分类:b+树索引、哈希索引
存储位置分类:聚簇索引、非聚簇索引
索引类型
特点
适用场景
主键索引(PRIMARY KEY)
唯一、非空,一张表只能有 1 个主键索引
表的唯一标识(如用户 ID)
唯一索引(UNIQUE)
唯一,但允许 NULL(多个 NULL 不冲突),一张表可创建多个
唯一标识字段(如手机号、邮箱)
普通索引(INDEX)
无唯一性约束,最常用
普通查询字段(如商品名称、分类)
组合索引(复合索引)
基于多个字段的索引,遵循最左前缀原则
多字段联合查询(如 WHERE 分类=1 AND 价格<100)
全文索引(FULLTEXT)
针对文本内容的模糊匹配优化(如文章内容搜索),仅支持 MyISAM/InnoDB(5.6+),适用于 CHAR、VARCHAR 和 TEXT 等字段。
长文本模糊查询(如 MATCH(content) AGAINST('关键词'))
主键索引=唯一索引+非空。每个表只能有一个主键索引,但可以有多个唯一索引。
普通索引仅用于加速查询,不限制字段值的唯一性;适用于高频写入的字段、范围查询的字段。
唯一索引强制字段值的唯一性,插入或更新时会触发唯一性检查;适用于业务唯一性约束的字段、防止数据重复插入的字段。
