Mysql 使用选择子查询中的值高效地更新查询

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

我试图提出一个查询,使用同一个表中的其他记录来更新MySQL表中的记录,但在本地测试和生产测试之间,结果不一。我不太了解子查询,所以我想把这个问题带到这里。在MySQL InnoDB 5.6.23的本地开发中,对大约180k条记录的数据集进行查询需要25到30秒。在具有MySQL InnoDB 5.5.32和254k记录数据集的临时服务器上,查询似乎会暂停数小时,直到停止,占用了100%的CPU核心

这就是我提出的问题:

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)

查询需要将每个产品的所有语言重置为默认语言。这就是为什么它很奇怪!;)查询需要为每个产品将所有语言重置为默认语言。这就是为什么它很奇怪!;)查询需要为每个产品将所有语言重置为默认语言。这就是为什么它很奇怪!;)查询需要为每个产品将所有语言重置为默认语言。这就是为什么它很奇怪!;)