代码之家  ›  专栏  ›  技术社区  ›  Colin

更新数据库记录中单个字段时的最佳实践

  •  2
  • Colin  · 技术社区  · 15 年前

    我使用.NET创建了一个数据访问层。在我更新数据库记录的任何地方,我都使用SQL

    更新客户集firstname=:firstname,lastname=:lastname,address1=:address1,address2=:address2,…等

    这意味着记录中的每个字段都会被更新,即使只有一个字段可能被更改。一位同事对此提出了异议,他说,只有当某个字段发生变化时,我们才应该更新该字段,并以带宽为例——假设我们有160个字段,然后我们传递160个字段的数据。我想如果我检查一个值是否发生了更改,并纯粹基于实际更改的值生成SQL,我可以节省Web服务器和数据库服务器之间的带宽。

    在Web服务器和客户机之间,我现在需要传递新的和旧的值,因此可能会增加那里的带宽(但无论如何,ASP.NET已经这样做了,我不确定是否可以关闭该位,因此这可能不是问题)。

    那么什么是最佳实践呢?我应该担心更新数据库记录中的所有字段吗?如何只更新已更改的字段?

    编辑在10月29日补充道:有人知道NHibernate的作用吗?也许这是一个花费时间学习如何做到这一点的论点。

    7 回复  |  直到 15 年前
        1
  •  6
  •   keithwarren7    15 年前

    过早的优化是万恶之源。

    有理由这样做吗,你真的有带宽问题吗?

    根据我的经验,跟踪变更可能需要很多工作(即需要维护很多代码),这取决于它是如何实现的。有一些优雅的方式,但我认为你做的很好,除非有证据支持改变。

    如果您计划实现某种定制的变更跟踪形式,我肯定不会与数据库“聊天”。当您第一次从数据库中提取对象时,在本地复制它,并与之进行比较。

        2
  •  4
  •   kevinw    15 年前

    也许除了带宽之外,您还需要考虑多用户争用。根据应用程序的设计方式,更新所有字段方法可能会导致问题。

    如果有两个用户同时加载记录编号1。用户A将姓氏从“smith”更改为“smythe”,然后保存。然后用户B将地址1从“The Street”更改为“Any Street”,并保存。

    在您的方法下,第二次保存还将把姓氏重新恢复为“smith”(因为这就是用户b加载它时的情况)。

    在这之后,您还需要在保存时进行其他检查(可能是某种时间戳),以确保数据库中的值是您认为的值。

        3
  •  2
  •   Greg Beech    15 年前

    假设您在Web服务器和数据库服务器之间有千兆网络连接,那么您必须在100兆数据区域中更新somwhere 每秒 甚至接近成为一个问题。每天大约8兆字节。我猜你没有更新这么多的数据,所以这可能不是问题。

        4
  •  1
  •   James Cronen    15 年前

    网络带宽在所有级别上都在不断提高。除非你在某个地方遇到了瓶颈,不要担心。即便如此,我的预感是,与在其他地方发现性能改进相比,获得的收益足够小,以至于您将花费更多的时间和精力(以及风险)来优化您的更新。

        5
  •  1
  •   MartW    15 年前

    好吧,您要么按照您所做的方式来做(每次都有效,并通过每个字段),要么花时间为每个字段生成定制的SQL,然后为每个字段传递一条SQL语句,或者在运行中生成大量只包含更新字段的SQL(如果您犯了错误,则存在注入SQL的风险)。通过在参数化存储过程中进行更新,并且只在字段值之间传递,而不是在名称之间传递,您可能会获得更好的带宽节约。

    除非带宽真的是个问题,否则我认为你没有问题。无论如何,SP路由是更好的选择。

        6
  •  1
  •   alphazero    15 年前

    其中一个字段不是表的pk吗?你真的在更新pk吗?外国钥匙呢?你也在更新吗?

    问题不在于带宽。至少隔离记录的非关系元素,并且只更新该集合(不包括pk和外键)。

        7
  •  1
  •   madman1969    15 年前

    我发现自己也处于同样的境地。我编写了自己的轻量级ORM/DAL,以接口到一个非优化设计的数据库,即具有200多个字段的表。

    我发现确实有一个开销与试图更新一行的所有字段相关,而不仅仅是那些已更改的字段。

    在我的例子中,我可以通过使用ORM属性的智能“setters”来解决这个问题,如果试图修改某个特定字段,ORM属性将记录这些属性。这意味着当我将对象提交回数据库时,我可以发出一条SQL更新语句,该语句只引用那些标记为已修改的字段。

    N.B. 对于select语句,最佳实践要求显式引用要返回的字段,而不是使用“select*from”。有人说这是因为性能/带宽的原因,所以反向更新是有意义的。