如何在mysql中进行优化和良好的更新语句?

时间:2015-04-30 14:18:38

标签: php mysql

我想编写一个语句,例如将is_new更新为0,条件为mail.user_id=$user.id等。

update mails set `is_new=0` WHERE `mails.user_id=$user.id`

我应该添加另一个条件来防止更新已经is_new等于零的记录吗?像这样

update mails set is_new=0 WHERE mails.user_id=$user.id and is_new!=0

哪个声明最好?你觉得它还需要第二个条件吗?

3 个答案:

答案 0 :(得分:1)

作为一个非常一般的原则,我将我的UPDATE查询结构化为" touch"实际需要触摸的记录。在我看来,出于性能原因这一点较少,出于可读性原因更多:后一种形式的查询更准确地说明了您尝试做的事情 - 即,您只想为那些记录设置is_new=0其中is_new还不是0.所以仅仅因为这个原因,我说应该有额外的条件。

更一般地说,有一个着名的计算机科学引用,"过早优化是所有邪恶的根源"。在使用MySQL查询时,我并不总是同意这个引用,但它提出了一个重要的观点:如果您对是否优化某些内容感到困惑,那么您实际上并没有尝试了两种格式和/或进行了测量,以确定优化产生了多大的差异,让您浪费时间。如果您在不知道它会产生什么差异的情况下进行优化,你确定的唯一结果就是你使你的工作变得更加复杂。

因此,不要出于性能原因进行优化,直到您知道(或有充分理由相信)优化会产生影响。但始终为了可读性和标准化原因而优化,因为您 知道人们将来必须阅读您的代码。至少这是我的规则。

答案 1 :(得分:1)

问题在于,当您在更新中设置值时,它实际上会覆盖旧值,这比检查是否应该覆盖该值需要更长的时间。所以,你有以下几种情况:

案例1:updateis_new0

user_id
  • 如果is_new匹配且0不是0,则会正确更新为user_id
  • 如果is_new匹配并且0已经update,那么它会0set,但这需要更长的时间,因为它是写操作

案例2:is_new 00,如果尚未user_id

  • 如果is_new匹配并且0不是0,那么它会检查它是0并因此正确地将其更新为user_id
  • 如果is_new匹配并且0已经0,那么它将检查它是否为update并将保留记录

假设您必须有x x条记录,但是,y条记录中只有0is_new is_new 。检查0 a is_new是否花费0时间并将b更新为is_new需要0次平均记录。在这种情况下:

如果您没有过滤掉update已经x * b的记录,那么: 您将is_new所有记录,这需要0时间。

如果您过滤掉is_new已经x * a的记录,那么: 您将检查y以获取记录,这需要y * b,然后您将更新x * a + y * b < x * b 记录,这需要SELECT s.* FROM student AS s INNER JOIN student_room AS sr ON s.roll_no = sr.roll_no WHERE sr.room_no NOT IN (6, 7) ;

直觉上,我认为写作花了很多时间,那就是:

LEFT JOIN

然而,肯定的是对它进行基准测试并查看一些测量结果,因为地球上没有人会告诉你你的mysql如何执行你的查询。

编辑:

基于评论,显然,文档指出如果字段更新为其当前值,那么MySQL将注意到该问题并且不会执行更新。

  

如果将列设置为当前的值,MySQL会注意到这一点   并且不会更新它。

Source

这并没有改变这样一个事实:如果需要进行优化,就应该进行实验,因为如果证明引用错误,那么文档就不是第一次存在缺陷。此外,这些想法对其他情况也应该有用,因为引用只接触带有=运算符的条件,如果应该检查其他条件,引用的MySQL功能将不适用。

答案 2 :(得分:1)

根据我的经验和我的观点,答案很清楚 - 不要添加is_new != 0。有几个原因,我会尝试列出它们:

  • SQL是关于解释您想要做什么的。添加条件也将告诉如何执行此操作。 MySQL已经过优化,足以避免工作超出预期。

  • 添加条件不会使您的查询更具可读性。删除它。它明确指出您要将is_new更新为基于user_id的值

  • 添加条件会导致潜在损害性能。注意 potential 这个词 - 我不是说它会,但它可能会。如果你无法优化某些东西是如何工作的,为什么你可能会让它变慢?只是不要。在你的情况下,我们可能正在谈论糟糕的表现值,但仍然。

  • 添加条件将使MySQL做得更多。不多,但仍然 - 它会做更多。你真的不需要它。

  • MySQL在写入任何新内容之前检查该行是否确实已更改。如果is_new0并且您想再次将其设置为0 - MySQL会注意到它并且它将跳过更新该行(写入操作比检查操作昂贵得多,所以MySQL将执行该检查。

手动引用:

  

如果将列设置为当前的值,MySQL会注意到这一点   并且不会更新它。

相关的源代码,如果需要:here