Может быть, вы должны объединить два метода нарочно. Почему ???
Давайте использовать эту таблицу (MySQL-диалект)
CREATE TABLE mydata
(
id int not null auto_increment
firstname varchar(16) not null,
lastname varchar(16) not null,
zipcode char(5) not null,
...
deleted tinyint not null default 0
KEY (deleted,id),
KEY (deleted,lastname,firstname,id),
KEY (deleted,zipcode,id),
KEY (lastname,firstname),
KEY (zipcode),
PRIMARY KEY (id)
);
Обратите внимание, что, за исключением PRIMARY KEY, каждому индексу, который вы создаете, должен предшествовать deleted
флаг и заканчиваться на id
.
Давайте создадим надгробный стол
CREATE TABLE mytomb SELECT id FROM mydata WHERE 1=2;
ALTER TABLE mytomb ADD PRIMARY KEY (id);
Если у вашей таблицы уже есть deleted
флаг, вы можете заполнить таблицу с надписью
INSERT INTO mytomb SELECT id FROM mydata WHERE deleted = 1;
Хорошо, теперь данные и надгробная плита подготовлены. Как вы выполняете удаление?
Допустим, вы удаляете каждого человека из почтового индекса 07305. Вы бы запустили следующее:
INSERT IGNORE INTO mytomb SELECT id FROM mydata WHERE deleted=0 AND zipcode='07305';
UPDATE mydata SET deleted=1 WHERE deleted=0 AND zipcode='07305';
Хорошо, это выглядит как много накладных расходов в любом случае.
Теперь, вы хотите увидеть все удаленные данные? Вот два разных способа:
SELECT * FROM mydata WHERE deleted=1;
SELECT B.* FROM mytomb A INNER JOIN mydata B USING (id);
Если число идентификаторов в mytomb превышает 5% от количества строк в mydata, это полное сканирование таблицы. В противном случае выполняется сканирование индекса с поиском для каждой строки. Обратите внимание на любые ориентиры в этом отношении. Поиск объяснения планов.
Теперь, вы хотите увидеть каждого человека в почтовый индекс 07304? Вот два разных способа:
SELECT * FROM mydata WHERE deleted=1 AND zipcode='07304';
SELECT A.* FROM mydata A LEFT JOIN mytomb B USING (id) WHERE B.id IS NULL AND A.zipcode='07304'
Как насчет массовых удалений? Вот два разных способа:
DELETE FROM mydata WHERE deleted=1;
DELETE B.* FROM mytomb A INNER JOIN mydata B USING (id); DELETE FROM mytomb;
ВЫВОД
Теперь я не говорю, чтобы сохранить оба метода. Выполнение этого с течением времени показывает, какой метод является более быстрым с точки зрения общей работоспособности. Вы должны решить, какие тесты лучше всего подходят для запросов реальных данных, запросов к удаленным данным и массовых удалений.