前言
想的再多,不如行动起来,大家好,我是啊Q,让我们徜徉在知识的海洋里吧。
一起“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第20天, 点击查看活动详情 。
刚学习编程的你是否也写过这个语句 select * from ...
没错,我也干过,那么今天我们就说说 select * 查询有哪些隐患和问题在里面呢?
分析:
假设你有这样一个场景:加入你现在有一个需求:需要展示阅读量前100的图书名。
我们的sql可以这样写
- SQL1: select * from book order by read_count desc limit 100 ;
- SQL2: select book_name from book order by read_count desc limit 100 ;
接下来我们就以上面的两个sql进行分析。分析一下select * 有哪些问题。
查询性能问题
- 查询表中的所有列时,数据库引擎需要扫描整个表的所有行,并且需要读取每一列的数据。这会使查询的处理时间变长。如果只查询表中的特定列,引擎只需要扫描所需的列,并读取对应的数据,从而可以更快地处理查询请求。如果表中列很多时,开销将会更大。加入上述表我们有200个字段,可实际上我们只需要一个字段的值。这种情况下空消耗之大可想而知。
- 特别的,当我们的表中存储的有大字段时,比如:text ,blob等。这查询将会造成更多的磁盘IO损耗,导致查询性能下降。
- 无法使用“覆盖索引”。 假如我们现在在 book_name和read_count上建立了索引 (
CREATE INDEX idx_book_readcount_bookname ON book (read_count, book_name)
),那么我们就可以直接通过索引查询查询出我们想要的结果。如果是select * 的话,即使是在这两个字断上建立了索引,也需要回表查询,大大降低了查询速度。
内存占用问题
在上诉情况下,使用select * 无论是在数据库服务器上还是在应用服务器上。SELECT * 查询返回的数据集包含表中的所有列,这可能会导致内存占用过高 ,从而会耗尽服务器的内存 。可能导致服务器崩溃或者宕机,业务服务器(JVM)OOM 或者 STW 。
维护问题
SELECT *查询可能会隐式地引入不必要的列。例如,当使用INNER JOIN语句连接两个表时,如果两个表中都包含相同的列名,则查询可能会返回两个列,这可能会对查询结果造成意外的影响。因此,最好使用显式的列名来查询表中的数据,这样可以避免这些维护问题。
数据安全问题
数据安全日益重要,SELECT *查询可能会泄露敏感信息。例如,如果表中包含密码、信用卡号码或其他敏感数据,则查询可能会返回这些数据,这可能会导致安全漏洞。为了避免这种情况,应该避免使用SELECT *查询,并且只查询需要的列。
可读性问题
SELECT *查询可能会降低代码的可读性。如果查询返回许多列,则代码可能会变得复杂。这可能会导致其他开发人员难以理解这些代码和数据的含义及其是否必要,这无疑增加了维护的难度。当然随着ORM框架日趋完善,这个问题如今已经不是很明显。