MySQL 由于索引太大,加入更新失败

MySQL Join Update Fails Due To Too Large Indexes

我正在使用 Python 在 MySQL 5.7.26 中填充一些 table。但是,Python 是无关的。当 运行 手动查询数据库时也会出现此问题。

我正在向一些临时的 table 添加数据,比如 tmp_source,并且由于缺少 MERGE 语句,然后我在 INNER JOIN UPDATE目的地 table destination 后跟 LEFT JOIN INSERT。查询看起来像这样:

UPDATE destination D
INNER JOIN tmp_source S
      ON D.col1 = S.col1
      AND D.col2 = S.col2
SET D.col3 = S.col3,
    D.col4 = S.col4;

INSERT INTO destination
SELECT * FROM tmp_source S
LEFT JOIN destination D
      ON D.col1 = S.col1
      AND D.col2 = S.col2
WHERE D.col1 IS NULL;

目的是更新现有行并插入缺失行,如 MERGE。但是,虽然插入工作正常,但由于以下原因更新有时会失败:

1071, 'Specified key was too long; max key length is 1024 bytes'

不允许我在结构上修改 destination table。它有一些制作不当的索引(例如 VARCHAR(256) 用于实际上永远不会超过 50 个字符的列),我知道这会带来问题。

我尝试创建 tmp_source 有和没有索引 - 没有骰子。

有什么方法可以在不改变 destination table 的情况下解决这个问题?我有一个 “它很愚蠢,但它有效,所以它并不愚蠢” 生成静态更新的想法,只是 运行 那些,例如:

UPDATE desination
SET col3 = val3,
    col4 = val4
WHERE col1 = val1
  AND col2 = val2

我的想法是我没有处理大量的数据。我可以捕获这个特定的异常,并且只在发生这种情况的 table 时执行此操作。有问题的 tables 通常少于 200 行。在这种情况下,速度并不是真正重要的。

但感觉就像这样的解决方法(可能是因为它是)。有人有更好的主意吗?

所以...令我震惊的是,我基本上忘记了书中最古老的技巧之一:DELETE-INSERT。

显然可以在 destination 上执行 DELETE,然后执行 INSERT。如果我想在删除之前保留某些值,我什至可以更新 tmp_source table。

所以它会像:

UPDATE tmp_source D
INNER JOIN destination S
      ON D.col1 = S.col1
      AND D.col2 = S.col2
SET D.col5 = S.col5,
    D.col6 = S.col6;

DELETE D
FROM destination D
INNER JOIN tmp_source S
      ON D.col1 = S.col1
      AND D.col2 = S.col2;

INSERT INTO destination
SELECT * FROM tmp_source S
LEFT JOIN destination D
      ON D.col1 = S.col1
      AND D.col2 = S.col2
WHERE D.col1 IS NULL;

您是否尝试过使用替换查询? Replace 服务于 update 和 Insert 的 属性。 如果某些数据从增量值更改,它会更新或插入。 谢谢!