Обновление таблицы с длинными шариками происходит слишком медленно - PullRequest
1 голос
/ 07 февраля 2020

У меня есть таблица, заполненная данными (около 20 000 записей). Я пытаюсь обновить его данными из другой таблицы, но у меня есть тайм-аут (30 секунд). Сначала я попробовал наивное решение:

UPDATE TableWhithBlobs a
JOIN AnotherTable b on a.AnotherTableId = b.Id
SET a.SomeText= b.Description;

Этот сценарий работает намного дольше, чем 30 секунд, поэтому я попытался уменьшить объединение:

UPDATE TableWhithBlobs a
SET a.SomeText = (select b.Description from AnotherTable b where a.AnotherTableId = b.Id);

, но этот по-прежнему очень медленный , Есть ли случаи, как это могло быть быстро?

Редактировать:
Небольшое объяснение того, что я делаю. Ранее у меня было две таблицы, которые в моем скрипте называются TableWhithBlobs и AnotherTable. В таблице TableWhithBlobs была сохранена ссылка на таблицу AnotherTable, но эта ссылка не была реальным внешним ключом, это был просто guid из таблицы AnotherTable. И есть ограничение уникального ключа для этой ссылки в TableWhithBlobs для этого guid. Я решил исправить это, удалить старое поле из таблицы TableWhithBlobs и добавить к нему обычный внешний ключ (используя первичный идентификатор из AnotherTable). Сценарий из вопроса просто добавляет правильные данные в это новое поле. После этого я удаляю старую ссылку guid и добавляю новое ограничение внешнего ключа. Все отлично работает при небольшом количестве данных в TableWhithBlobs, но в базе данных QA с 20000 строками это очень медленно.

Обновление

ПОКАЗАТЬ CREATE TABLE TableWhithBlobs;

CREATE TABLE `TableWhithBlobs` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`AnotherTableId` char(36) CHARACTER SET ascii NOT NULL,
`ChunkNumber` bigint(20) NOT NULL,
`Content` longblob NOT NULL,
`SomeText` bigint(20) NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `AnotherTableId` (`AnotherTableId`,`ChunkNumber`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

ПОКАЗАТЬ СОЗДАТЬ СТОЛ AnotherTable;

CREATE TABLE `AnotherTable` (
`Description` bigint(20) NOT NULL AUTO_INCREMENT,
`Id` char(36) CHARACTER SET ascii NOT NULL,
`Length` bigint(20) NOT NULL,
`ContentDigest` char(68) CHARACTER SET ascii NOT NULL,
`ContentAndMetadataDigest` char(68) CHARACTER SET ascii NOT NULL,
`Status` smallint(6) NOT NULL,
`ChunkStartNumber` bigint(20) NOT NULL DEFAULT '0',
`IsTestData` bit(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`Description`),
UNIQUE KEY `Id` (`Id`),
UNIQUE KEY `ContentAndMetadataDigest` (`ContentAndMetadataDigest`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

PS. Имена столбцов могут выглядеть странно, потому что я хочу скрыть имена реальных производственных схем.

innodb_buffer_pool_size - 134217728, ОЗУ - 4 ГБ

Результат

explain UPDATE TableWhithBlobs a JOIN AnotherTable b on a.AnotherTableId = 
b.Id SET a.SomeText= b.Description;

Update explanation

Версия: mysql Вер. 14.14 Распространение 5.7.21-20, для debian- linux -gnu (x86_64) с использованием 6.3

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Некоторые мысли, ни одна из которых не выскакивает как « ответ »:

  • Увеличение innodb_buffer_pool_size до 1500M, при условии, что это не приводит к обмену.
  • Отойдите назад и посмотрите на «почему» BIGINT нужно копировать так часто. И нужно ли обновлять «все» строки.
  • Поместите LONGBLOB в другую таблицу параллельно с текущей. Это добавит JOIN для случаев, когда вам нужно получить большой двоичный объект, но может не допустить его для текущего запроса. (Я бы не ожидал, что большой двоичный объект будет «в пути», но, очевидно, это так.)
  • Что находится в этом объекте? В некоторых ситуациях лучше иметь блоб в файле. Ярким примером является изображение для веб-сайта - к нему можно получить доступ через http * <img...>.
  • увеличить время ожидания - но это просто "подметает проблему под коврик" и, вероятно, приводит к 30+ Вторая задержка в других вещах, которые его ждут. Я не распознаю 30 секунд как время ожидания. Просмотрите SHOW VARIABLES LIKE '%out'; Попробуйте увеличить значение, равное 30.
  • Есть ли обновление по частям - но будет ли это иметь другие последствия? (В любом случае, Луук должен перенести эту опцию вперед.)
0 голосов
/ 15 февраля 2020

Как насчет небольших обновлений?

UPDATE TableWhithBlobs a
JOIN AnotherTable b on a.AnotherTableId = b.Id
SET a.SomeText= b.Description
WHERE a.SomeText <> b.Description;

или даже:

UPDATE TableWhithBlobs a
JOIN AnotherTable b on a.AnotherTableId = b.Id
SET a.SomeText= b.Description
WHERE a.SomeText <> b.Description
LIMIT 100;

Ваша проблема с тайм-аутом должна быть решена ?, но я не знаю, сколько раз вам нужно было запускать это, наконец, получить 0 rows affected ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...