При отправке запроса DELETE, innoDB удаляет данные из базы данных один за другим или сначала создает список данных, которые нужно удалить? - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть таблица базы данных с ~ 140 000 строк, и сейчас я делаю запрос, который выглядит как

DELETE FROM database WHERE type="delete"

Но это занимает много времени.Я испытываю желание остановить запрос и посмотреть, не уменьшился ли размер базы данных, но я не уверен, что она находится в процессе создания списка данных, которые нужно удалить до того, как данные действительно будут удалены.Как innoDB фактически удаляет данные из базы данных при получении запроса DELETE?

Вот запрос CREATE (для таблицы images):

CREATE TABLE IF NOT EXISTS `images` (
  `imageID` int(11) NOT NULL AUTO_INCREMENT,
  `runID_fk` int(11) DEFAULT NULL,
  `sequenceID_fk` int(11) DEFAULT NULL,
  `cameraID_fk` int(11) DEFAULT NULL,
  `data` longblob,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `name` text,
  `type` text,
  `pcadata` longblob,
  PRIMARY KEY (`imageID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018
  • INDEX уже упоминалось.
  • TEXT столбцы (из которых 4) могут храниться в другом месте, что требует дополнительного обращения к диску.(уже упоминалось).
  • InnoDB создает список вещей, которые нужно отменить в случае сбоя;это, возможно, самая большая стоимость.
  • Лучше всего удалять кусками не более 1000 строк.Пройдите через PRIMARY KEY, чтобы найти фрагменты.
  • Существуют и другие методы, если это повторяющаяся задача.
  • Если удаляется более, скажем, половина таблицы, то: Создайте новую таблицу;INSERT SELECT для копирования хранителей;RENAME TABLE поменять местами;DROP.

Подробнее о последних трех предложениях см. this .

0 голосов
/ 16 декабря 2018

На основании вашего оператора CREATE у вас нет индекса для столбца type.Итак, ваша проблема связана с медленным предложением WHERE.По сути, ваш запрос вынуждает сервер баз данных просматривать каждую строку, чтобы определить, является ли значение в столбце type "delete".Это медленно, независимо от того, сколько у вас строк.Индекс сделает это намного быстрее, потому что сервер может просто запросить список всех соответствующих строк, а затем работать только с этими строками.

В качестве очень широкого практического правила, если вы собираетесь использовать столбецв предложении WHERE он должен быть проиндексирован.(Конечно, есть исключения, но это не одно из них в зависимости от того, что вы опубликовали.)

Чтобы узнать, что делает сервер базы данных, запустив запрос EXPLAIN, как в

EXPLAIN DELETE FROM database WHERE type="delete"

Исходя из вашего комментария, ваш EXPLAIN возвращает что-то вроде этого:

id   select_type   table    partitions   type   possible_keys   key     key_len   ref    rows     filtered  Extra
1    SIMPLE        images                ALL    null            null    null      null   145669             Using where

Что 145,699, которые вы видите, не являются (как вы написали в комментарии) "размер строк ".Это количество строк, на которое сервер должен посмотреть, чтобы выполнить ваш запрос.Как видите, у него нет индексов, которые он может использовать.Таким образом, вместо просмотра только тех строк, которые вы хотите удалить, нужно взглянуть на 145 669 строк.

Кроме того, поскольку ваш столбец type является столбцом TEXT, это будет еще медленнее.Вы должны серьезно рассмотреть возможность добавления TINYINT, CHAR (не TEXT) или другого столбца для хранения статуса строки, если вы собираетесь пометить строки для удаления таким способом.

На болееобщее примечание, вы действительно должны пересмотреть некоторые из этих типов столбцов.Я серьезно сомневаюсь, что вам нужно 2^16 - 1 байт для столбца с именем name, например.

...