为什么SELECT *是不好的做法?如果您添加了想要的新列,这难道不意味着需要更改的代码更少吗?

我知道SELECT COUNT(*)在某些db上是一个性能问题,但是如果您真的想要每个列呢?


当前回答

在设计方案之前理解您的需求(如果可能的话)。

了解数据, 1)索引 2)所使用的存储类型; 3)供应商引擎或功能;即……缓存,内存功能 4)数据类型 5)桌子大小 6)查询频率 7)如果资源是共享的,相关的工作量 8)测试

A)要求会有所不同。如果硬件不能支持预期的工作负载,则应该重新评估如何在工作负载中提供需求。关于向表中添加的列。如果数据库支持视图,您可以使用特定的命名列创建特定数据的索引(?)视图(vs.选择'*')。定期检查您的数据和模式,以确保您永远不会遇到“输入垃圾”->“输出垃圾”综合征。

假设没有其他解;你可以考虑以下几点。一个问题总是有多种解决方案。

1)索引:select *将执行一个表罐。根据各种因素,这可能涉及到磁盘寻道和/或与其他查询的争用。如果表是多用途的,请确保所有查询都是高性能的,并在您的目标时间以下执行。如果有大量数据,而您的网络或其他资源没有调优;你需要考虑到这一点。数据库是一个共享环境。

2)存储类型。Ie:如果你使用SSD,磁盘或内存。I/O时间和系统/cpu上的负载会有所不同。

3) DBA是否可以调优数据库/表以获得更高的性能?假设出于某种原因,团队已经决定选择“*”是问题的最佳解决方案;可以将DB或表加载到内存中。(或者其他方法…也许反应被设计成有2-3秒的延迟?——而广告的作用是为公司赚取收入……)

4)从基线开始。了解您的数据类型,以及如何显示结果。更小的数据类型、字段数量会减少结果集中返回的数据量。这将为其他系统需求留下可用资源。系统资源通常是有限制的;“总是”工作低于这些限制,以确保稳定性和可预测的行为。

5)表/数据的大小。选择“*”在小表中很常见。它们通常适合内存,并且响应时间很快。再次……回顾您的需求。特征蠕变计划;总是为当前和未来可能的需求做计划。

6)查询/查询频率。了解系统上的其他工作负载。如果这个查询每秒发出一次,并且表很小。结果集可以设计为保留在缓存/内存中。然而,如果查询是一个频繁的批处理过程,有千兆字节/兆兆字节的数据……最好分配额外的资源以确保其他工作负载不受影响。

7) Related workloads. Understand how the resources are used. Is the network/system/database/table/application dedicated, or shared? Who are the stakeholders? Is this for production, development, or QA? Is this a temporary "quick fix". Have you tested the scenario? You'll be surprised how many problems can exist on current hardware today. (Yes, performance is fast...but the design/performance is still degraded.) Does the system need to performance 10K queries per second vs. 5-10 queries per second. Is the database server dedicated, or do other applications, monitoring execute on the shared resource. Some applications/languages; O/S's will consume 100% of the memory causing various symptoms/problems.

8)测试:测试你的理论,尽可能多地理解。你选择的“*”问题可能是一个大问题,或者它可能是你甚至不需要担心的事情。

其他回答

引用自这篇文章。

永远不要用“SELECT *”,

我发现使用“SELECT *”的原因只有一个。

如有特殊要求和创建动态环境时添加或删除列,由应用程序代码自动处理。在这种特殊情况下,您不需要更改应用程序和数据库代码,这将自动影响生产环境。在这种情况下,您可以使用“SELECT *”。

在很多情况下,SELECT *会在应用程序的运行时导致错误,而不是在设计时。它隐藏了应用程序中列更改或坏引用的信息。

即使您现在希望选择每一列,也可能不希望在某人添加一个或多个新列之后选择每一列。如果您使用SELECT *来编写查询,那么在某些时候,您可能会冒这样的风险,即有人可能会添加一列文本,从而使您的查询运行得更慢,即使您实际上并不需要该列。

如果您添加了想要的新列,这难道不意味着需要更改的代码更少吗?

如果您确实想要使用新列,那么无论如何您都必须对代码进行大量其他更改。你只保存,new_column -只有几个字符的输入。

使用列名进行选择提高了数据库引擎从索引访问数据的可能性,而不是查询表数据。

当数据库模式发生变化时,SELECT *使您的系统暴露在意想不到的性能和功能变化中,因为您要将任何新列添加到表中,即使您的代码还没有准备好使用或显示这些新数据。

如果您将字段添加到表中,它们将自动包含在使用select *的所有查询中。这看起来很方便,但它会使您的应用程序变慢,因为您获取的数据比您需要的要多,并且它实际上会在某些时候使您的应用程序崩溃。

在结果的每一行中可以获取多少数据是有限制的。如果向表中添加字段导致结果超过了限制,则在尝试运行查询时将收到错误消息。

这是一种很难发现的错误。您在一个地方做了更改,而在另一个实际上根本不使用新数据的地方它就会崩溃。它甚至可能是一个不太常用的查询,以至于在有人使用它之前需要一段时间,这使得将错误与更改联系起来更加困难。

如果指定希望在结果中显示哪些字段,就不会出现这种开销溢出。