区分数据集并将大量行更新/插入到大型MySQL表中的最快方法?

如何解决区分数据集并将大量行更新/插入到大型MySQL表中的最快方法?

| 模式 我有一个带有一个大表的MysqL数据库(说500万行)。该表具有几个用于实际数据的字段,一个可选的注释字段以及用于记录何时首次添加该行以及何时删除该数据的字段。为了简化为一个“数据”列,它看起来像这样:
+----+------+---------+---------+----------+
| id | data | comment | created | deleted  |
+----+------+---------+---------+----------+
| 1  | val1 | NULL    | 1       | 2        |
| 2  | val2 | nice    | 1       | NULL     |
| 3  | val3 | NULL    | 2       | NULL     |
| 4  | val4 | NULL    | 2       | 3        |
| 5  | val5 | NULL    | 3       | NULL     |
由于有了
created
deleted
字段,这种模式使我们能够查看数据的任何过去版本。
SET @version=1;
SELECT data,comment FROM MyTable
WHERE created <= @version AND 
      (deleted IS NULL OR deleted > @version);

+------+---------+
| data | comment |
+------+---------+
| val1 | NULL    |
| val2 | nice    |
可以更简单地获取当前版本的数据:
SELECT data,comment FROM MyTable WHERE deleted IS NULL;

+------+---------+
| data | comment |
+------+---------+
| val2 | nice    |
| val3 | NULL    |
| val5 | NULL    |
DDL:
CREATE TABLE `MyTable` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,`data` varchar(32) NOT NULL,`comment` varchar(32) DEFAULT NULL,`created` int(11) NOT NULL,`deleted` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `data` (`data`,`comment`)
) ENGINE=InnoDB;
更新中 一组新的数据和注释会定期到达。五百万行表示,这可能会很大。我需要更新ѭ6,以便将新数据集存储在其中。这表示: \“删除\”旧行。注意\“吓人的报价\”-我们实际上并未从
MyTable
删除行。我们必须将
deleted
字段设置为新版本
N
。必须对
MyTable
中所有在先前版本
N-1
中但不在新集合中的行进行此操作。 插入新行。必须将ѭ6set中新版本中ѭ11not版本以外的所有行添加为新行,其中
created
字段设置为新版本
N
deleted
设置为NULL。 新集中的某些行可能与版本11的版本6中的行匹配,在这种情况下,无需执行任何操作。 我目前的解决方案 鉴于我们必须“区分”两组数据来计算出删除,我们不能只读取新数据并进行适当的插入。我想不出一种方法,不用先将所有新数据转储到临时表中就可以执行差异操作。所以我的策略是这样的:
-- temp table uses MyISAM for speed.
CREATE TEMPORARY TABLE tempupdate (
    `data` char(32) NOT NULL,`comment` char(32) DEFAULT NULL,PRIMARY KEY (`data`),KEY (`data`,`comment`)
) ENGINE=MyISAM;

-- Bulk insert thousands of rows
INSERT INTO tempupdate VALUES
    (\'some new\',NULL),(\'other\',\'comment\'),...

-- Start transaction for the update
BEGIN;
SET @newVersion = 5; -- Worked out out-of-band

-- Do the \"deletions\". The join selects all non-deleted rows in MyTable for
-- which the matching row in tempupdate does not exist (tempupdate.data is NULL)
UPDATE MyTable
    LEFT JOIN tempupdate
    ON MyTable.data = tempupdate.data AND
       MyTable.comment <=> tempupdate.comment
    SET MyTable.deleted = @newVersion
    WHERE tempupdate.data IS NULL AND
          MyTable.deleted IS NULL;

-- Delete all rows from the tempupdate table that match rows in the current
-- version (deleted is null) to leave just new rows.
DELETE tempupdate.*
    FROM MyTable RIGHT JOIN tempupdate
    ON MyTable.data = tempupdate.data AND
       MyTable.comment <=> tempupdate.comment
    WHERE MyTable.id IS NOT NULL AND
          MyTable.deleted IS NULL;

-- All rows left in tempupdate are new so add them.    
INSERT INTO MyTable (data,comment,created)
    SELECT disTINCT tempupdate.data,tempupdate.comment,@newVersion
    FROM tempupdate;

COMMIT;

DROP TEMPORARY TABLE IF EXISTS tempupdate;
问题(最后) 我需要找到最快的方法来执行此更新操作。我无法更改ѭ6的架构,因此任何解决方案都必须使用该约束。您能想到一种执行更新操作的更快方法,还是建议加快现有方法的速度? 我有一个Python脚本,用于测试不同更新策略的时间并检查其在多个版本中的正确性。它相当长,但是我可以编辑一下这个问题,如果人们认为它会有用。     

解决方法

        加快速度之一是用于装载-LOAD DATA INFILE。     ,        就我所经历的审计日志而言,使用两个表会更好,例如:
yourtable (id,col1,col2,version) -- pkey on id
yourtable_logs (id,version) -- pkey on (id,version)
然后在yourtable上添加一个更新触发器,该触发器将先前版本插入yourtable_logs中。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?