SELECT * 会导致查询效率低的原因
前言
因为 SELECT *
查询语句会查询所有的列和行数据,包括不需要的和重复的列,因此它会占用更多的系统资源,导致查询效率低下。而且,由于传输的数据量大,也会增加网络传输的负担,降低系统性能。
如果需要查询所有的列数据,可以使用 LIMIT
关键字限制查询的行数,避免传输过多的数据。在实际开发中建议指定列名,避免使用 SELECT *
。
一、适合SELECT * 的使用场景
SELECT *
是 SQL 语句中的一种,用于查询数据表中所有的列和行。它的使用场景有以下几种:
- 初学者的练习:当学习 SQL 语言的初学者没有掌握如何选择特定的列时,可以用
SELECT *
来查看完整的数据表结构,这有助于更好地理解数据表的组成。 - 快捷查询:当需要查询数据表中所有的数据时,
SELECT *
可以快捷地查找到所有的数据,省去了手动输入列名的麻烦。 - 在某些情况下,使用
SELECT *
可以使 SQL 语句更加简洁明了,让代码更易于维护和修改。
但SELECT *
也有一些潜在的风险,比如 SELECT *
可能会导致查询效率低下、数据冗余和安全问题等。
二、SELECT * 会导致查询效率低的原因
2.1、数据库引擎的查询流程
数据库引擎的查询流程通常包含以下几个步骤:
- 解析 SQL 语句:数据库引擎先将 SQL 语句解析成内部的执行计划,包括了查询哪些数据表、使用哪些索引、如何连接多个数据表等信息。
- 优化查询计划:数据库引擎对内部的执行计划进行优化,根据查询的复杂度、数据量和系统资源等因素,选择最优的执行计划。
- 执行查询计划:数据库引擎根据执行计划,通过 I/O 操作读取数据表的数据,进行数据过滤、排序、分组等操作,最终返回结果集。
- 缓存查询结果:如果查询结果集比较大或者查询频率较高,数据库引擎会将查询结果缓存在内存中,以加速后续的查询操作。
以MySQL为例,执行一条select
语句时,会经过:
- 连接器:主要作用是建立连接、管理连接及校验用户信息。
- 查询缓冲:查询缓冲是以
key-value
的方式存储,key
就是查询语句,value
就是查询语句的查询结果集;如果命中直接返回。注意,MySQL 8.0已经删除了查询缓冲。 - 分析器:词法句法分析生成语法树。
- 优化器:指定执行计划,选择查询成本最小的计划。
- 执行器:根据执行计划,从存储引擎获取数据,并返回客户端。
2.2、SELECT * 的实际执行过程
当使用 SELECT *
查询语句时,数据库引擎会将所有的列都查询出来,包括不需要的和重复的列,然后将这些数据传输到客户端。这个过程会涉及以下几个步骤:
- 执行解析 SQL 语句:当数据库引擎接收到
SELECT *
查询语句时,会首先解析该语句,确定需要查询哪些数据表,以及如何连接这些数据表,然后将解析结果保存到内部的执行计划中。 - 执行查询计划:根据执行计划,数据库引擎会扫描相应的数据表,读取所有的列和行数据,然后将这些数据传输到客户端。
- 数据传输到客户端:一旦查询完成,数据库引擎将查询结果集发送到客户端,包括所有的列和行数据。
由于 SELECT *
查询语句会查询所有的列和行数据,包括不需要的和重复的列,因此它会占用更多的系统资源,导致查询效率低下。而且,由于传输的数据量大,也会增加网络传输的负担,降低系统性能。
2.3、使用 SELECT * 查询语句带来的不良影响
- 查询效率低下:由于
SELECT *
查询语句会查询所有列和行数据,包括不需要的和重复的列,因此会占用更多的系统资源,导致查询效率低下。 - 数据冗余:使用
SELECT *
查询语句可能会查询出不必要的重复数据,增加数据库的存储空间,降低数据库的性能。 - 网络传输负担增加:由于
SELECT *
查询语句会传输所有的列和行数据,因此会增加网络传输的负担,降低系统性能。 - 安全问题:如果数据表中包含敏感信息,使用
SELECT *
查询语句可能会泄露敏感信息,引发安全问题。
所以,建议选择具体的列进行查询。如果需要查询所有的列数据,可以使用 LIMIT
关键字限制查询的行数,避免传输过多的数据。
三、优化查询效率的方法
-
SELECT 显式指定字段名。
SELECT
显式指定字段名的优势:- 减少不必要的数据传输 。
- 减少内存消耗。
- 提高查询效率
SELECT
显式指定字段名的注意事项: 掌握数据表结构、避免指定过多的字段 、避免频繁修改查询语句。
-
使用索引。
-
减少子查询。
-
避免使用 OR 操作符。
四、总结
SELECT *
的不良影响:
- 查询效率低下;
- 数据冗余;
- 网络传输负担增加;
- 安全问题。
显式指定字段名的优势:
- 查询效率更高;
- 减少数据冗余;
- 网络传输负担减少;
- 更好的代码可读性;
- 提高安全性。
优化查询效率的方法:
- 显式指定需要查询的字段名;
- 使用
LIMIT
关键字限制查询的行数; - 优化索引,提高查询效率;
- 避免在
WHERE
子句中使用函数或表达式,以免影响查询效率; - 避免使用子查询,以免引起性能问题;
- 合理使用
JOIN
,避免查询结果集过大。