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 的 属性。
如果某些数据从增量值更改,它会更新或插入。
谢谢!
我正在使用 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 的 属性。 如果某些数据从增量值更改,它会更新或插入。 谢谢!