我正在使用 mysql 数据库,现在我必须确保列中的值应该是1
,而它可能1
已经是。因此,考虑以下两个陈述:
UPDATE category SET is_leaf=1 WHERE id=9
或者
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0
id
是主键,区别是当is_leaf已经是1的时候,再更新还是不更新,哪个效率更高?
我知道这并不重要,但我想找出更好地理解mysql。
我正在使用 mysql 数据库,现在我必须确保列中的值应该是1
,而它可能1
已经是。因此,考虑以下两个陈述:
UPDATE category SET is_leaf=1 WHERE id=9
或者
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0
id
是主键,区别是当is_leaf已经是1的时候,再更新还是不更新,哪个效率更高?
我知道这并不重要,但我想找出更好地理解mysql。
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0
效率更高。因为那样它只会更新相关数据。否则即使is_leaf=1
记录也要去更新。
假设表上有1000条记录,更新一条记录需要1s。如果您尝试更新所有记录,则需要 1000 秒。但假设在这种情况下 is_leaf=0
记录数为 150,那么如果您使用第二条语句,则只需 150 秒而不是 1000 秒。
编辑 :
带有搜索参数的查询 (SARG)
WHERE 子句可帮助您限制查询返回的行数。但是,指定 WHERE 条件的方式会影响查询的性能。如果写入 WHERE 条件以使其使用将索引列作为输入的函数,则忽略索引并扫描整个表。这会导致性能下降。例如,以下结果会导致表扫描,因为在函数中使用了列 OrderDate:
SELECT CustomerID, EmployeeID FROM Orders
WHERE DATEDIFF(m, OrderDate, GetDate())>3
如果函数被重写如下所示,那么查询会使用索引来寻找所需的值,这会提高性能:
SELECT CustomerID, EmployeeID FROM Orders
WHERE OrderDate < DATEADD(m, -3, GetDate())
据说第二个查询中的过滤条件使用可搜索参数或 SARG,因为查询优化器可以在执行期间使用索引查找操作。
有关这方面的更多信息,您最好阅读提高查询性能
并阅读本文以加快搜索和过滤器
包含的查询AND is_leaf=0
有时会更有效。
根据主键定位行时,它不会有太大的不同。(索引的可用性 on (id,is_leaf)
可能会产生很小的差异。)但是一旦 MySQL 确定没有要更新的行,它就可以采用更短的代码路径。
但是,如果没有该谓词,MySQL 将不得不定位行,获取行锁(在 InnoDB 的情况下),并触发任何“BEFORE UPDATE FOR EACH ROW”触发器。然后 MySQL 必须检查是否有任何列值实际被更改(请注意,触发器的执行可能会将一个或多个列设置为不同的值)。如果 MySQL 检测到行没有更改,它可以跳过任何“ON UPDATE”时间戳列的设置,触发任何“AFTER UPDATE FOR EACH ROW”触发器,并将受影响的行数设置为零。(在事务的上下文中,不清楚 MySQL 是否可以在确定行没有被更改时释放行锁,或者行锁是否会继续保持直到提交或回滚。)
因此,这两个语句之间的一大区别是,即使行没有实际更改,MySQL 也会触发“FOR EACH ROW”触发器;但它不会为 WHERE 子句排除的行触发任何“FOR EACH ROW”触发器。
在简单的情况下,没有任何触发器,我不希望在性能上有任何可测量的差异。
我个人的偏好是包含额外的谓词。这确保不会请求或持有(InnoDB)意向行锁,并且不会触发 FOR EACH ROW 触发器。
除了行锁定和触发器执行之外,只要这两个语句完全相同,它们就不是真的。至少在一般情况下不会,因为有可能is_leaf
包含 NULL 或 0 或 1 以外的值。
鉴于此声明:
UPDATE category SET is_leaf=1 WHERE id=9
对于当它不等于 1 时设置为 1 的等效语句is_leaf
,我们实际上需要检查 NULL 和任何不同于 1 的值,例如:
UPDATE category SET is_leaf=1 WHERE id=9 AND NOT (is_leaf <=> 1)
考虑一下当is_leaf
为 NULL 或 2 时会发生什么,例如,使用以下语句:
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0