【问题标题】:Is there a difference between Select * and Select [list each col] [duplicate]Select * 和 Select [列出每个列] [重复] 之间有区别吗
【发布时间】:2010-09-17 13:25:25
【问题描述】:

我使用的是 MS SQL Server 2005。对于 SQL 引擎来说,两者之间是否有区别

SELECT * FROM MyTable;

SELECT ColA, ColB, ColC FROM MyTable;

当 ColA、ColB 和 ColC 代表表中的每一列时?

如果它们是相同的,有什么理由你应该使用第二个吗?我有一个使用 LINQ 的项目,我不确定它生成的标准 SELECT * 是否是一种不好的做法,或者我是否应该始终使用 .Select() 来指定我想要的列。

编辑:更改“当 ColA、ColB 和 ColC 都是表的列时?”到“当 ColA、ColB 和 ColC 代表表中的每一列时?”为了清楚起见。

【问题讨论】:

标签: sql database linq linq-to-sql


【解决方案1】:

一般来说,最好是明确的,所以Select col1, col2 from Table 更好。原因是在某些时候,可能会向该表添加一个额外的列,这会导致从查询中带回不需要的数据。

不过,这并不是一个硬性规定。

【讨论】:

  • 在很多情况下,它还会导致依赖代码中断。在具有不使用 INSERT 语句的列列表的懒惰开发人员的环境中尤其如此。
  • 在某些情况下,显式意味着您可能必须更改使用该表的每一个代码,因为您确实希望新列几乎无处不在。虽然您通常仍需要更改视图代码,但在这些情况下,只需使用 * 仍会将工作量减少一半。这完全取决于你在做什么,以及你对未来的计划是什么。
  • 从开发人员的角度来看,它并不是那么好,因为如果您必须更改或删除列名,则会造成恐慌,因为您必须在任何地方进行更改。但是@swilliams 先生,它有什么性能优势吗?
【解决方案2】:

1) 第二个更明确地说明了返回哪些列。那么第二个的价值就是你明确知道哪些列回来了。

2) 当列数多于显式使用的列数时,这可能会导致返回的数据更少。

3) 如果您通过添加新列来更改表,则第一个查询会更改,而第二个不会。如果您有类似“for all columns returned do ...”之类的代码,那么如果您使用第一个而不是第二个,结果会发生变化。

【讨论】:

    【解决方案3】:

    我会让很多人对我不满意,但特别是如果我稍后要添加列,我通常喜欢使用 SELECT * FROM 表。由于这个原因,我被称为惰性,因为如果我对我的表进行任何修改,我不想追踪所有使用该表的存储过程,而只是在我的应用程序的数据访问层类中更改它.在某些情况下我会指定列,但在我试图从数据库中获取完整的“对象”的情况下,我宁愿只使用“*”。而且,是的,我知道人们会因此而讨厌我,但它让我在向我的应用程序中添加字段时更快、更少错误。

    【讨论】:

    • 我认为你不必过于防御。这是对风格上主观问题的有效回答。 :)
    • “更快”在开发方面,当然。但是,您可能在几乎每一个 SELECT 语句上都浪费了 I/O。
    • 我和你在一起,我还没有遇到可以追溯到“select *”与“select column1, column2...”的性能问题。我确信它会发生,但我宁愿在它发生时处理该异常,而不是在我不需要 99% 的时间时针对它进行防御性编码。
    • 我也和你在一起。在某些情况下,星号显然确实使代码的维护成本更低(尤其是如果您有一个不错的 IDE 和/或良好的编码约定),这通常比与性能相关的问题重要得多。
    【解决方案4】:

    问题的两个方面是:显式列规范在添加新列时提供更好的性能,但 * 规范在添加新列时不需要维护。

    使用哪一个取决于您希望添加到表中的列类型以及查询的目的。

    如果您将表用作对象的后备存储(这在 LINQ-to-SQL 情况下很可能),您可能希望添加到该表的任何新列都包含在您的对象中,反之亦然反之亦然。您正在并行维护它们。因此,对于这种情况,SELECT 子句中的 * 规范是正确的。每次更改时,显式规范都会为您提供额外的维护,如果您没有正确更新字段列表,则会出现错误。

    如果查询要返回大量记录,出于性能原因,您最好使用明确的规范。

    如果两者都成立,请考虑使用两个不同的查询。

    【讨论】:

      【解决方案5】:

      您应该指定一个明确的列列表。 SELECT * 将带回比您创建更多 IO 和网络流量所需的更多列,但更重要的是,即使存在非聚集覆盖索引(在 SQL Server 上),它也可能需要额外的查找。

      【讨论】:

      • 是的!这是显式覆盖索引的最佳理由。
      • 接受的答案似乎满足了更多人对 * 和 col1、col2、col3 之间区别的[错误]概念。
      【解决方案6】:

      不使用第一个语句(select *)的一些原因是:

      1. 如果您稍后在该表中添加一些大字段(BLOB 列会非常不好),您可能会在应用程序中遇到性能问题
      2. 如果查询是包含两个或多个表的 JOIN 查询,则某些字段可能具有同名。最好确保您的字段名称不同。
      3. 从编程美学的角度来看,第二条语句的查询的目的更加清晰

      【讨论】:

      • 我不反对你的回答。但是当在结果集上请求适当的 getter 时,大多数数据库使用单独的调用来加载 Large Object(BLOB) 类型。因此,只有当您确实希望读取这些列时,性能才会受到影响。
      【解决方案7】:

      当您单独选择每个字段时,更清楚实际选择了哪些字段。

      【讨论】:

        【解决方案8】:

        SELECT * 在大多数地方都是不好的做法。

        • 如果有人向该表添加 2gb BLOB 列怎么办?
        • 究竟是什么人在该表中添加了任何列?

        这是一个等待发生的错误。

        【讨论】:

        • "SELECT *" 不会返回 2 个演出,所以这无关紧要。添加的列会影响依赖代码,以及真正重要的可读性和明确性。
        • 我基本同意,除了错误部分。我发现我已经避免了错误,只需获取整行并且只有一个地方(数据访问层类)来处理该数据。我通常在那里处理可能出现的问题。带有 SQL 链接的数据模型类是调整内容的好地方。
        • @P DBA:我说过它会返回 2 个演出吗?我只是在问代码是否会处理表中的更改,如第二个项目符号所示。 @SB您可能会围绕对架构的更改进行编码,大多数开发人员不会,并且事情会中断。为什么要让自己接受这样的机会?
        【解决方案9】:

        几件事:

        • 很多人在这里发帖建议不要使用 *,并给出了这些答案的几个充分理由。到目前为止,在其他 10 个回复中,只有一个不建议列出列。
        • 在向 StackOverflow 等帮助网站发帖时,人们通常会对该规则进行例外处理,因为他们通常不知道您的表中有哪些列或对您的查询很重要。出于这个原因,您会在这里和网络上的其他地方看到很多使用 * 语法的代码,尽管发帖人倾向于在自己的代码中避免使用它。

        【讨论】:

          【解决方案10】:

          它有利于向前兼容。

          当你使用

          SELECT * FROM myTable
          

          在“myTable”中有 3 列。您会得到与

          相同的结果
          SELECT Column1, Column2, Column3 FROM myTable
          

          但是如果你以后添加新列,你会得到不同的结果。

          当然,如果您更改现有列的名称,在第一种情况下您会得到结果,在第二种情况下您会收到错误(我认为这是应用程序的正确行为)。

          【讨论】:

          • 我不确定在未来发生变化时中断是向前兼容性的定义。
          • 我认为 TcKs 的案例是,打破比假装工作(但不工作)更好。
          • 我同意,如果您重命名列并按列名访问结果,应用程序应该会中断。如果您仍然按列名而不是索引访问结果,则使用 * 并不能更好地保护自己免受重命名。
          • @Greg D 是的,这正是我的意思。
          【解决方案11】:

          如果您的代码依赖于按特定顺序排列的某些列,则需要列出这些列。如果不是,那么使用“*”或在 select 语句中写出列名并没有什么不同。

          例如,如果您将列插入到表中。

          拿这张桌子: ColA ColB ColC

          您可能有疑问:

          SELECT *
          FROM myTable
          

          那么代码可能是:

          rs = executeSql("SELECT * FROM myTable")
          while (rs.read())
              Print "Col A" + rs[0]
              Print "Col B" + rs[1]
              Print "Col C" + rs[2]
          

          如果您在 ColB 和 ColC 之间添加一列,查询将不会返回您要查找的内容。

          【讨论】:

            【解决方案12】:

            对于 LinqToSql,如果您打算稍后修改这些记录,则应将整条记录拉入内存。

            【讨论】:

              【解决方案13】:

              这取决于您所说的“差异”是什么意思。有明显的语法差异,但真正的差异是性能之一。

              当您说SELECT * FROM MyTable 时,您是在告诉 SQL 查询引擎返回一个包含该表中所有列的数据集,而 SELECT ColA, ColB, ColC FROM MyTable 告诉查询引擎返回一个数据从表中设置 ColA、ColB 和 ColC。

              假设您有一个包含 100 列的表,定义为 CHAR[10]。 SELECT * 将返回 100 列 * 10 字节的数据,而 SELECT ColA, ColB, ColC 将返回 3 列 * 10 字节的数据。这是通过网络传回的数据量的巨大差异。

              指定列列表还可以让您更清楚您感兴趣的列。缺点是如果您从表中添加/删除列,您需要确保列列表也被更新,但我认为这是与性能提升相比,代价很小。

              【讨论】:

              • 在这种情况下,性能没有差异。我相信您在问题的第一部分错过了这条关键信息:“当 ColA、ColB 和 ColC 都是表的列时?”由于他想要所有列,因此没有性能差异。其他问题?是的。
              • @Pittsburgh DBA:我看到了,但读起来不同......因为 ColA、ColB 和 ColC 都是表中的列,而不是表中的完整列集。无论哪种方式,我的回复中的信息仍然是相关的(但在这个特定的情况下,它是一个洗牌。)
              【解决方案14】:
              SELECT * FROM MyTable
              

              select * 取决于架构中的列顺序,因此如果您通过集合的索引 # 引用结果集,您将看到错误的列。

              SELECT Col1,Col2,Col3 FROM MyTable
              

              此查询将为您提供一个随时间保持不变的集合,但您多久更改一次列顺序?

              【讨论】:

                【解决方案15】:

                快速查看查询执行计划表明查询是相同的。

                一般的经验法则是,您希望将查询限制为仅需要返回的字段。

                【讨论】:

                  【解决方案16】:

                  选择每一列比只选择 * 更好,因为如果您添加或删除新行,您必须查看代码并查看您对检索到的数据做了什么。
                  此外,它还可以帮助您更好地理解您的代码,并允许您使用别名作为列名(如果您正在执行与共享名称的列的表连接)

                  【讨论】:

                    【解决方案17】:

                    一个关于为什么你从不(恕我直言)应该使用 SELECT * 的例子。这与 MSSQL 无关,而与 MySQL 有关。 5.0.12 之前的版本以非标准方式从某些类型的连接返回列。当然,如果您的查询定义了您想要的列和顺序,那么您没有问题。想象一下,如果他们不这样做会很有趣。

                    (一个可能的例外:您的查询仅从一个表中选择并且您在选择的编程语言中通过名称而不是位置来识别列。)

                    【讨论】:

                      【解决方案18】:

                      使用“SELECT *”优化程序员的打字。而已。这是唯一的优势。

                      【讨论】:

                        猜你喜欢
                        • 2015-09-10
                        • 2016-12-23
                        • 1970-01-01
                        • 2012-03-16
                        • 2017-12-19
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多