为啥我们不应该在生产服务器上的 mysql 查询中使用 Select *?
Posted
技术标签:
【中文标题】为啥我们不应该在生产服务器上的 mysql 查询中使用 Select *?【英文标题】:Why shouldn't we use Select * in a mysql query on a production server?为什么我们不应该在生产服务器上的 mysql 查询中使用 Select *? 【发布时间】:2012-04-22 12:49:29 【问题描述】:基于这个问题Selecting NOT NULL columns from a table其中一位发帖人说
您不应该在生产中使用 SELECT *。
我的问题:我们真的不应该在生产服务器上的 mysql 查询中使用 Select * 吗?如果是,我们为什么不使用全选?
【问题讨论】:
【参考方案1】:请记住,您的数据库服务器不一定与查询数据库的程序位于同一台机器上。数据库服务器可能位于带宽有限的网络上;它甚至可以跨越半个地球。
如果您确实需要每一列,那么请务必使用SELECT * FROM table
。
但是,如果您只需要某些列,那么使用 SELECT * FROM table
请求所有列只会浪费一半的列。
其他可能的原因,最好指定您想要的确切列:
数据库结构可能会改变。例如,如果您的程序假定某些列名,那么如果列名更改,它可能会失败。如果违反您对列名的假设,显式命名您要检索的列将使程序立即失败。正如@Konerak 提到的,命名您想要的列还可以确保结果中列的 order 相同,即使表架构发生变化(即在两列之间插入一列其他人。)如果您依赖 FirstName
作为结果的 [2]
nd 元素,这一点很重要。
(注意:处理这个问题的一种更健壮和自记录的方法是要求您的数据库结果作为键值对列表,如 php 关联数组、Perl 哈希或 Python dict
。那这样您就不需要使用数字来索引结果(name = result[2]
) - 您可以使用列名:name = result["FirstName"]
。)
【讨论】:
【参考方案2】:使用SELECT *
效率非常低,尤其是对于具有大量列的表。您应该只选择您需要的列。
除此之外,使用列名使查询更易于阅读和维护。
【讨论】:
嗯,使用SELECT *
或SELECT a,b,c
当一个表有三列时具有相同的性能。它只是不太面向未来,更容易出错。
您能否详细说明为什么 SELECT *
效率低下的原因?我列出了一些原因,但我可能遗漏了一些。【参考方案3】:
大多数人确实建议不要在生产中使用 SELECT *
,因为它往往会破坏事情。不过也有一些例外。
SELECT *
获取所有列 - 而大多数时候你不
都需要。这会导致 SQL 服务器发送的列多于
需要,这是一种浪费,并且会使系统变慢。
使用SELECT *
,以后添加列时,旧查询也会
选择这个新列,而通常它不需要它。命名
这些列明确阻止了这种情况。
大多数编写SELECT *
查询的人也倾向于抓取行
并使用列顺序来获取列 - 这会破坏你的代码
在现有色谱柱之间注入色谱柱。
显式命名列还可以保证它们始终按相同的顺序排列,而SELECT *
在修改表列顺序时可能表现不同。
但也有例外,例如这样的陈述:
INSERT INTO table_history
SELECT * FROM table
这样的查询从表中获取行,并将它们插入到 table_history 中。如果您希望此查询在新行添加到表和 table_history 时继续工作,SELECT *
是要走的路。
【讨论】:
我认为任何依赖于列顺序的代码都很难维护。最好按名称 (result["FirstName"]
) 询问列而不是数字 (result[2]
)。
所以一般来说,您会建议将数据作为关联数组而不是数字数组获取?
离场!但是,如果您真的想按顺序获取列,则显式命名它们至少可以保证顺序。
是的,以关联数组的形式获取结果使代码更加健壮且更易于阅读 - result['FirstName']
显而易见,而 result[2]
则更难阅读。可能会有轻微的速度损失,但除非您正在编写 Facebook,否则您不必担心这一点。请记住,“程序首先是为人类阅读而编写的,只是偶尔为计算机执行。”以上是关于为啥我们不应该在生产服务器上的 mysql 查询中使用 Select *?的主要内容,如果未能解决你的问题,请参考以下文章
为啥不应该在 Liferay 的生产环境中使用 HSQLDB?