У меня есть приложение, которое я пишу на Java с простым SQL, поэтому здесь нет пользовательских MySQL или SQL Server - оно может работать на любом из них.Одна операция сохранения данных должна извлечь данные из БД, сравнить их с тем, что было отправлено, а затем вставить, обновить или удалить соответствующим образом.
Я значительно улучшил производительность операции, пакетируя вызовы JDBC.
Итак, мои ВСТАВКИ - я просто вызываю метод Statement.addBatch()
для всего набора данных, который нужно вставить, и драйвер JDBC создает
INSERT INTO data (parentId, seriesDate, valueDate, value)
VALUES (a,b,c,d),(a,b,e,f),(a,b,g,h)... etc
DELETEs - Я просто удаляю весь лот с помощью
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) ...
, но здесь проблема не в этом, моя главная проблема в том, что ОБНОВЛЕНИЯ действительно медленные - в два раза медленнеекак INSERT
я получаю 1000 отдельных операторов:
UPDATE data SET value = 4
WHERE parentId = 1 AND seriesDate = '' AND valueDate = '';
В SQL Server ОБНОВЛЕНИЯ так же быстро, как и INSERT , но в MySQL я вижу, что он работает в 10 раз медленнее.
Я надеюсь, что забыл какой-то взаимно совместимый подход или пропустил какую-то конфигурацию соединения JDBC, которую мне нужно настроить, может бытьв сочетании с количеством элементов, которые я помещаю в каждую партию.
[ОБНОВЛЕНИЕ 2018-05-17] Вот запрошенный DDL - и, к сожалению, я не могу изменить это (пока) поэтому любые предложения, связанные с изменениями схемы, не помогут, по крайней мере, в этом году: (
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 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
с помощью триггера (и опять же, я не могу отказаться от этой функции).