MySQL和InnoDB - 在非唯一索引上使用WHERE UPDATE - 如何遇到行?

时间:2014-08-02 20:17:57

标签: mysql innodb

当在非唯一索引列上执行UPDATE和WHERE时,表行的上下文中的规则是如何遇到的?

我有一个测试表,其中col列为非唯一索引:

id  |  col
----------
1   |  1
----------
2   |  2
----------
3   |  2
----------
22  |  3


UPDATE tab SET col=1 WHERE col=1;
// OR
UPDATE tab SET col=3 WHERE col=3;
// OR
UPDATE tab SET col=2 WHERE col=2;     
// These updates encounter ONLY rows where col=1, col=3 or col=2

相同的表和相同的更新,但在表格中还有一个记录,其中col = 2:

id  |  col
----------
1   |  1
----------
2   |  2
----------
3   |  2
----------
4   |  2
----------
22  |  3


UPDATE tab SET col=1 WHERE col=1;
// OR
UPDATE tab SET col=3 WHERE col=3;
// Both updates encounter ONLY rows where col=1 or col=3.

UPDATE tab SET col=2 WHERE col=2;     
// This update encounters ALL the rows in the table even those where col IS NOT 2.
// WHY ?

2 个答案:

答案 0 :(得分:0)

那里有一篇精彩的文章。我相信这会回答你的疑问。

http://www.mysqlperformanceblog.com/2012/11/23/full-table-scan-vs-full-index-scan-performance/

答案 1 :(得分:0)

简而言之,处理UPDATE时遇到的每一行都是行锁定的。这意味着UPDATE的锁定影响取决于如何处理查询以读取要更新的行。如果您的UPDATE查询不使用索引或错误索引,则可能会锁定许多或所有行。 (请注意,锁定行的订单还取决于所使用的索引。)在您的情况下,由于您的表格非常小​​,而且您实际上正在改变您的行的分布索引,它选择对相关查询使用全表扫描。

您可以测试大多数UPDATE个查询的效果和行为,方法是将它们转换为SELECT并在其上使用EXPLAIN SELECT(在较新的版本中,您甚至可以EXPLAIN UPDATE

简而言之:在测试性能或锁定行为之前,您应该拥有具有实际数据分布的表,而不是具有少量测试行的非常小的表。