如何优化MySQL查询以进行更新?

如何优化MySQL查询以进行更新?,mysql,optimization,Mysql,Optimization,我有一张有30万条记录的桌子。在这个表中有duplicae行,我想更新列“flag” 桌子 我使用此查询更新“标志”列: 对于这30万条记录,此查询的运行速度非常慢(超过600秒) 如何优化此查询 我的桌子的结构 CREATE TABLE IF NOT EXISTS `inv` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pn` varchar(10) NOT NULL COMMENT 'Part Number', `qty` int(5) NO

我有一张有30万条记录的桌子。在这个表中有duplicae行,我想更新列“flag”

桌子

我使用此查询更新“标志”列:

对于这30万条记录,此查询的运行速度非常慢(超过600秒)

如何优化此查询

我的桌子的结构

CREATE TABLE IF NOT EXISTS `inv` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pn` varchar(10) NOT NULL COMMENT 'Part Number',
  `qty` int(5) NOT NULL,
  `qty_old` int(5) NOT NULL,
  `flag_qty` tinyint(1) NOT NULL,
  `name` varchar(60) NOT NULL,
  `vid` int(11) NOT NULL ,
  `flag_d` tinyint(1) NOT NULL ,
  `flag_u` tinyint(1) NOT NULL ,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `pn` (`pn`),
  KEY `name` (`name`),
  KEY `vid` (`vid`),
  KEY `pn_2` (`pn`),
  KEY `flag_qty` (`flag_qty`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;

如果“name”重复,我想更新flag_qty

让MySQL向您解释查询。然后,您将看到什么索引可以改善情况。
解释
将向您展示哪里速度慢,下面是一些想法,如何改善性能:

  • 添加索引
  • 使用InnoDB外键
  • 将查询拆分为2个,并在您使用的lagnuage中分别处理它们
  • 在MySQL过程中写同样的想法(不确定这是否会很快)

    • 我会使用临时表。1.)将所有相关记录选择到临时表中,在id上设置索引。2.)使用以下方法更新表

      UPDATE table i, tmp_i
      SET i.flag = '1'
      WHERE i.id = tmp_i.id
      
      您可以尝试(假设是VB.net,但可以用任何语言实现)

      获取ID列表(逗号分隔)后,使用

      UPDATE i  
      SET i.flag = '1' 
      WHERE i.number in ( .... )
      

      它也可能很慢,但是第一个-
      选择将不会锁定数据库和复制等。
      更新将更快。

      如果您还没有关于
      编号的索引,您应该添加一个-

      CREATE INDEX table_number ON table (number);
      
      更新试试这个-

      UPDATE inv t1
      INNER JOIN inv t2
          ON t1.name = t2.name
          AND t1.id <> t2.id
      SET t1.flag_qty = 1;
      
      更新库存t1
      内部连接inv t2
      在t1.name=t2.name上
      和t1.id t2.id
      设置t1.flag_数量=1;
      
      通过直接将此数据选择到另一个表中,而不是首先执行此标志更新,您可以仅使用重复项创建表

      INSERT INTO duplicate_invs
      SELECT DISTINCT inv1.*
      FROM inv AS inv1
      INNER JOIN inv AS inv2
          ON inv1.name = inv2.name
          AND inv1.id < inv2.id
      
      插入到重复的库存中
      选择DISTINCT inv1*
      从inv变为inv1
      内部连接inv作为inv2
      在inv1.name=inv2.name上
      和inv1.id

      如果您可以解释从
      inv
      表中删除行的逻辑,那么整个过程可能只需一步即可完成。

      表的结构是什么?此表上是否有可用的主键?设置此标志的目的是什么?是否基于此标志进行进一步处理?此标志的用途是如果表中有重复行,则此标志为1。之后,我想创建一个包含重复行的表,并从主表中删除这些行。其他所有列的数据是否也重复,或者它们是否有不同的值?我问这些问题是因为我怀疑有更好的解决方案来解决你正在尝试做的事情?这是一次性重复数据消除过程还是经常发生?你怎么会得到复制品呢?如果不希望复制,为什么
      number
      不是主键(或者至少有唯一键)?其他列的数据不同。数字匹配,但另一列(“更多列…”)中的信息不重复。出于这个原因,我想更新字段标志。在这种情况下,请发布
      SHOW index FROM table_name
      的输出。我在一次测试中对3M行运行了您的查询,它在我的笔记本电脑上以1秒多一点的时间返回。添加完整的表结构(来自
      SHOW CREATE table\u name
      的输出)可能会有所帮助。我添加了表的sql结构。
      CREATE INDEX table_number ON table (number);
      
      UPDATE inv t1
      INNER JOIN inv t2
          ON t1.name = t2.name
          AND t1.id <> t2.id
      SET t1.flag_qty = 1;
      
      INSERT INTO duplicate_invs
      SELECT DISTINCT inv1.*
      FROM inv AS inv1
      INNER JOIN inv AS inv2
          ON inv1.name = inv2.name
          AND inv1.id < inv2.id