关于重复密钥更新 - 优先级
ON DUPLICATE KEY UPDATE - precedence
做INSERT INTO {tableA} SELECT a,b,c FROM {tableB} ON DUPLICATE KEY UPDATE x=y
时
重复键的计算优先级是什么?我假设 MySQL 首先检查表 B 中的元组是否与表 A 中的 unique/primary 键冲突。如果 SELECT 不包含主键,或者如果不存在其他重复键,则评估每个后续的 UNIQUE INDEX "group" 并执行相同的检查。但是,如果您的 tableB 具有多组唯一的多列索引,会发生什么情况?他们是否按照 SHOW INDEXES FROM tableB
所述从上到下进行评估?
这是我的 SHOW INDEXES FROM <table>
:
Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation
daily_metrics,0,PRIMARY,1,id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,1,line_item_id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,2,creative_id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,3,year,A
daily_metrics,0,unique_lineItem_creative_y_m_d,4,month,A
...
假设有额外的一组唯一索引类似于 unique_lineItem_creative_y_m_d
文档似乎没有说明这种行为。
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
我还假设使用第一个匹配的唯一索引,如果存在匹配,则不会尝试匹配后续可以匹配的唯一索引。换句话说,使用第一个匹配的唯一索引,而不考虑尝试在所有索引中找到最佳匹配。
如果 tableB
中存在任何主键或唯一键,那是无关紧要的。 INSERT...ON DUPLICATE KEY UPDATE
唯一重要的是要插入的 table 的主键或唯一键 - 在您的示例中为 tableA
。
如果您插入到 tableA
的值已在 tableA
的任何主键或唯一键中找到,则会触发 IODKU 的 UPDATE
部分。
这是关于插入的值,而不是源的约束 table。
您也可以在不使用任何来源 table 的情况下触发 UPDATE
-- 只需插入带有一组常量的 VALUES()
子句即可。
你是对的:一旦 MySQL 在任何 UNIQUE
索引中检测到重复项,它就会放弃 INSERT
并进行更新。
MySQL 评估唯一索引的顺序不会改变结果。对于某个唯一索引,没有 更好 匹配之类的东西。因为它们是唯一索引,所以显示为重复的列值的任何组合都足以完全指定要更新的行。
MySQL 的查询规划器希望选择评估成本最低的索引。但是,从形式上讲,它用于此目的的索引是不可预测的。这种不可预测性是SQL等声明性语言的属性。 MySQL 可以以任何可行的方式完成它的工作,而且它不必告诉你。程序员可能很难掌握,因为我们已经习惯了 过程 语言。
做INSERT INTO {tableA} SELECT a,b,c FROM {tableB} ON DUPLICATE KEY UPDATE x=y
重复键的计算优先级是什么?我假设 MySQL 首先检查表 B 中的元组是否与表 A 中的 unique/primary 键冲突。如果 SELECT 不包含主键,或者如果不存在其他重复键,则评估每个后续的 UNIQUE INDEX "group" 并执行相同的检查。但是,如果您的 tableB 具有多组唯一的多列索引,会发生什么情况?他们是否按照 SHOW INDEXES FROM tableB
所述从上到下进行评估?
这是我的 SHOW INDEXES FROM <table>
:
Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation
daily_metrics,0,PRIMARY,1,id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,1,line_item_id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,2,creative_id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,3,year,A
daily_metrics,0,unique_lineItem_creative_y_m_d,4,month,A
...
假设有额外的一组唯一索引类似于 unique_lineItem_creative_y_m_d
文档似乎没有说明这种行为。 https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
我还假设使用第一个匹配的唯一索引,如果存在匹配,则不会尝试匹配后续可以匹配的唯一索引。换句话说,使用第一个匹配的唯一索引,而不考虑尝试在所有索引中找到最佳匹配。
如果 tableB
中存在任何主键或唯一键,那是无关紧要的。 INSERT...ON DUPLICATE KEY UPDATE
唯一重要的是要插入的 table 的主键或唯一键 - 在您的示例中为 tableA
。
如果您插入到 tableA
的值已在 tableA
的任何主键或唯一键中找到,则会触发 IODKU 的 UPDATE
部分。
这是关于插入的值,而不是源的约束 table。
您也可以在不使用任何来源 table 的情况下触发 UPDATE
-- 只需插入带有一组常量的 VALUES()
子句即可。
你是对的:一旦 MySQL 在任何 UNIQUE
索引中检测到重复项,它就会放弃 INSERT
并进行更新。
MySQL 评估唯一索引的顺序不会改变结果。对于某个唯一索引,没有 更好 匹配之类的东西。因为它们是唯一索引,所以显示为重复的列值的任何组合都足以完全指定要更新的行。
MySQL 的查询规划器希望选择评估成本最低的索引。但是,从形式上讲,它用于此目的的索引是不可预测的。这种不可预测性是SQL等声明性语言的属性。 MySQL 可以以任何可行的方式完成它的工作,而且它不必告诉你。程序员可能很难掌握,因为我们已经习惯了 过程 语言。