Mysql 使用选择子查询中的值高效地更新查询
我试图提出一个查询,使用同一个表中的其他记录来更新MySQL表中的记录,但在本地测试和生产测试之间,结果不一。我不太了解子查询,所以我想把这个问题带到这里。在MySQL InnoDB 5.6.23的本地开发中,对大约180k条记录的数据集进行查询需要25到30秒。在具有MySQL InnoDB 5.5.32和254k记录数据集的临时服务器上,查询似乎会暂停数小时,直到停止,占用了100%的CPU核心 这就是我提出的问题:Mysql 使用选择子查询中的值高效地更新查询,mysql,database,performance,optimization,query-optimization,Mysql,Database,Performance,Optimization,Query Optimization,我试图提出一个查询,使用同一个表中的其他记录来更新MySQL表中的记录,但在本地测试和生产测试之间,结果不一。我不太了解子查询,所以我想把这个问题带到这里。在MySQL InnoDB 5.6.23的本地开发中,对大约180k条记录的数据集进行查询需要25到30秒。在具有MySQL InnoDB 5.5.32和254k记录数据集的临时服务器上,查询似乎会暂停数小时,直到停止,占用了100%的CPU核心 这就是我提出的问题: UPDATE `product_lang` AS `pl1` SE
UPDATE
`product_lang` AS `pl1`
SET
pl1.`name` = (
SELECT pl2.`name` FROM (SELECT `name`, `id_product`, `id_lang` FROM `product_lang`) AS `pl2`
WHERE pl1.`id_product` = pl2.`id_product`
AND pl2.`id_lang` = 1
)
WHERE
pl1.`id_lang` != 1
目标是将id_lang
不是1的产品记录中name
的值替换为记录值的name
的值,默认值id_lang
为1
我知道子查询效率很低,但我真的不知道如何解决这个问题,将其留在SQL land中而不是使用应用程序层来完成繁重的工作,这将是一个巨大的优势。确保有一个指定列id\uProduct和id\uLang的索引。确保有一个指定列id\uProduct和id\uLang的索引。确保有一个指定列id\u的索引product和id_lang。确保有一个指定id_lang和id_lang列的索引。如果您这样编写查询:
UPDATE product_lang pl1
SET pl1.name = (SELECT pl2.`name`
FROM (SELECT `name`, `id_product`, `id_lang`
FROM `product_lang`
) `pl2`
WHERE pl1.`id_product` = pl2.`id_product` AND pl2.`id_lang` = 1
)
WHERE pl1.`id_lang` <> 1
此查询所需的索引是
product\u lang(id\u lang,id\u product)
和product\u lang(id\u product)
。但是,这似乎是一个奇怪的更新
,因为它会将所有名称设置为语言1中的名称。如果您这样编写查询:
UPDATE product_lang pl1
SET pl1.name = (SELECT pl2.`name`
FROM (SELECT `name`, `id_product`, `id_lang`
FROM `product_lang`
) `pl2`
WHERE pl1.`id_product` = pl2.`id_product` AND pl2.`id_lang` = 1
)
WHERE pl1.`id_lang` <> 1
此查询所需的索引是
product\u lang(id\u lang,id\u product)
和product\u lang(id\u product)
。但是,这似乎是一个奇怪的更新
,因为它会将所有名称设置为语言1中的名称。如果您这样编写查询:
UPDATE product_lang pl1
SET pl1.name = (SELECT pl2.`name`
FROM (SELECT `name`, `id_product`, `id_lang`
FROM `product_lang`
) `pl2`
WHERE pl1.`id_product` = pl2.`id_product` AND pl2.`id_lang` = 1
)
WHERE pl1.`id_lang` <> 1
此查询所需的索引是
product\u lang(id\u lang,id\u product)
和product\u lang(id\u product)
。但是,这似乎是一个奇怪的更新
,因为它会将所有名称设置为语言1中的名称。如果您这样编写查询:
UPDATE product_lang pl1
SET pl1.name = (SELECT pl2.`name`
FROM (SELECT `name`, `id_product`, `id_lang`
FROM `product_lang`
) `pl2`
WHERE pl1.`id_product` = pl2.`id_product` AND pl2.`id_lang` = 1
)
WHERE pl1.`id_lang` <> 1
此查询所需的索引是product\u lang(id\u lang,id\u product)
和product\u lang(id\u product)
。但是,这似乎是一个奇怪的更新
,因为它将把所有名称都设置为语言1中的名称。更新pl1
设置pl1.name=pl2.name
来自产品_lang pl1
,product_lang
pl2
其中pl1.id\u product
=pl2.id\u product
和pl2.id\u lang
=1
和pl1.id\u lang
1
所需的合成索引将是id_product和id_lang,用于更新pl1
UPDATE product_lang AS pl1
JOIN product_lang AS pl2
ON pl1.`id_product` =
pl2.`id_product`
SET pl1.name = pl2.name
WHERE pl2.`id_lang` = 1
AND pl1.`id_lang` != 1;
设置pl1.name=pl2.name
来自产品_lang pl1
,product_lang
pl2
其中pl1.id\u product
=pl2.id\u product
和pl2.id\u lang
=1
和pl1.id\u lang
1
所需的合成索引将是id_product和id_lang,用于更新pl1
UPDATE product_lang AS pl1
JOIN product_lang AS pl2
ON pl1.`id_product` =
pl2.`id_product`
SET pl1.name = pl2.name
WHERE pl2.`id_lang` = 1
AND pl1.`id_lang` != 1;
设置pl1.name=pl2.name
来自产品_lang pl1
,product_lang
pl2
其中pl1.id\u product
=pl2.id\u product
和pl2.id\u lang
=1
和pl1.id\u lang
1
所需的合成索引将是id_product和id_lang,用于更新pl1
UPDATE product_lang AS pl1
JOIN product_lang AS pl2
ON pl1.`id_product` =
pl2.`id_product`
SET pl1.name = pl2.name
WHERE pl2.`id_lang` = 1
AND pl1.`id_lang` != 1;
设置pl1.name=pl2.name
来自产品_lang pl1
,product_lang
pl2
其中pl1.id\u product
=pl2.id\u product
和pl2.id\u lang
=1
和pl1.id\u lang
1
所需的合成索引将是的id_product和id_lang
UPDATE product_lang AS pl1
JOIN product_lang AS pl2
ON pl1.`id_product` =
pl2.`id_product`
SET pl1.name = pl2.name
WHERE pl2.`id_lang` = 1
AND pl1.`id_lang` != 1;
并且有索引(id\u lang,id\u product)
并且有索引(id\u lang,id\u product)
并且有索引(id\u lang,id\u product)
并具有
索引(id\u lang,id\u product)
查询需要将每个产品的所有语言重置为默认语言。这就是为什么它很奇怪!;)查询需要为每个产品将所有语言重置为默认语言。这就是为什么它很奇怪!;)查询需要为每个产品将所有语言重置为默认语言。这就是为什么它很奇怪!;)查询需要为每个产品将所有语言重置为默认语言。这就是为什么它很奇怪!;)