如何提高mySQL与SQL Server中大量UPDATE的速度?

时间:2018-05-16 22:14:42

标签: mysql sql sql-server jdbc

我有一个应用程序,我用Java编写简单的SQL,因此这里没有自定义MySQL或SQL Server - 它可能必须运行。一个数据持久化操作必须从数据库中获取数据,将其与已提交的数据进行比较,然后相应地插入,更新或删除。

通过批处理JDBC调用,我已经大大提高了操作的性能。

所以我的 INSERT - 我只是调用Statement.addBatch()方法来插入整个数据集,并且JDBC驱动程序创建

INSERT INTO data (parentId, seriesDate, valueDate, value) 
    VALUES (a,b,c,d),(a,b,e,f),(a,b,g,h)... etc

DELETE - 我只是用

删除了整个批次
DELETE FROM data WHERE parentId = a AND seriesDate = b;

我可以重新插入它们。 (通过撰写一个很长的

来采取另一种方法可能会更好
DELETE FROM data WHERE (parentId = 1 AND seriesDate = b) 
    OR (parentId = 2 AND seriesDate = c) 
    OR (parentId = 3 AND seriesDate = d)  ...

但这不是问题,我的主要问题是 UPDATEs 非常慢 - 比 INSERT

慢两倍

我收到1000条单独的陈述:

UPDATE data SET value = 4 
    WHERE parentId = 1 AND seriesDate = '' AND valueDate = '';

在SQL Server中, UPDATE INSERT 一样快,但在MySQL中,我发现它运行速度慢了10倍。

我希望我已经忘记了一些相互兼容的方法,或者错过了我需要调整的一些JDBC连接配置,可能与我在每批中放入的项目数量相关。

[更新2018-05-17] 以下是所请求的DDL - 遗憾的是我无法更改此内容,因此任何涉及架构更改的建议都会赢得&#39 ; t帮助,至少不是今年:(

CREATE TABLE data (
  parentId INT UNSIGNED NOT NULL,
  seriesDate DATE NOT NULL,
  valueDate DATE NOT NULL,
  value FLOAT NOT NULL,
  versionstamp INT UNSIGNED NOT NULL DEFAULT 1,
  createdDate DATETIME DEFAULT CURRENT_TIMESTAMP,
  last_modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  CONSTRAINT pk_data PRIMARY KEY (parentId, seriesDate, valueDate),
  CONSTRAINT fk_data_forecastid FOREIGN KEY (parentId)
    REFERENCES forecast (id)
) MAX_ROWS 222111000;

CREATE TRIGGER trg_data_update BEFORE UPDATE ON data
  FOR EACH ROW SET NEW.versionstamp = OLD.versionstamp + 1;

CREATE INDEX ix_data_seriesdate ON `data` (seriesDate);

INSERT

INSERT INTO `data` (`parentId`, `valueDate`, `value`, `seriesDate`)
    VALUES (52031,'2010-04-20',1.12344,'2013-01-10')

EXPLAIN PLAN:
id: 1
select_type: INSERT
table: data
partitions:
type: ALL
possible_keys: PRIMARY,ix_data_seriesdate

更新

UPDATE `data` SET `value` = -2367.0
    WHERE `parentId` = 52005 AND `seriesDate` = '2018-04-20' AND `valueDate` = '2000-02-11'

EXPLAIN PLAN:
id: 1
select_type: UPDATE
table: data
partitions: 
type: range
possible_keys: PRIMARY,ix_data_seriesdate
key: PRIMARY
key_len: 10
ref: const,const,const
rows: 1
filtered: 100
Extra: Using where

DELETE

DELETE FROM `data` WHERE `parentId` = 52030 AND `seriesDate` = '2018-04-20'

EXPLAIN PLAN:
id: 1
select_type: DELETE
table: data
partitions: 
type: range
possible_keys: PRIMARY,ix_data_seriesdate
key: PRIMARY
key_len: 7
ref: const,const
rows: 1
filtered: 100
Extra: Using where

FYI 2字段会自动更新 - last_modified子句ON UPDATE和触发器versionstamp(同样,我无法撤销该功能)。

1 个答案:

答案 0 :(得分:2)

我发现改进UPDATE语句的方式:

  • 使用辅助表(可以“批量”更新)
  • 检查不必要的触发器
  • 改进索引(对于WHERE子句)
  • OLAP或OLTP中间人临时表(它们允许批量更新)

E.G。

CREATE TABLE #TempData ( 
  parentId INT UNSIGNED NOT NULL,
  seriesDate DATE NOT NULL,
  valueDate DATE NOT NULL,
  value FLOAT NOT NULL
);

INSERT INTO #TempData ( parentId, seriesDate, valueDate, value ) VALUES ( .... ), ( .... ), ( .... );

UPDATE
  data
SET
  value = #TempData.value
FROM
  #TempData
WHERE
  data.parentId = #TempData.parentId AND
  data.seriesDate = #TempData.seriesDate AND
  data.valueDate = #TempData.valueDate;