Мне нужно обновить множество записей в одной таблице (от 300 до 500 тысяч) и удалить несколько миллионов в другой таблице. Поскольку это занимает некоторое время, я использую LIMIT, чтобы сделать это в блоке, чтобы показать пользователю индикатор выполнения.
Мой первый небольшой вопрос: почему я могу использовать следующий оператор в SQLiteSpy, а не когда я использую ADO.NET-провайдер System.Data.SQLite?
UPDATE Table1
SET Status1 = newValue1, Status2 = value2
WHERE Key1 = key1Value
AND Status1 = value1
LIMIT 1000
Я должен использовать следующее утверждение, чтобы оно заработало:
UPDATE Table1
SET Status1 = newValue1, Status2 = value2
WHERE Key1 = key1Value
AND Key2 in (
SELECT Key2
FROM Table
WHERE Key1 = key1Value
AND Status1 = value1
LIMIT 1000)
Я использую последнюю версию SQLiteSpy (которая использует SQLite 3.7.2) и System.Data.SQlite.
Мой другой вопрос более сложный.
Я использую 2 таблицы:
CREATE TABLE Table1 (
Key1 INTEGER NOT NULL,
Key2 INTEGER NOT NULL,
...
Some fixed varchar data fields
...
Status1 CHAR(1) NOT NULL,
Status2 VARCHAR NULL,
Status3 CHAR(1) NOT NULL,
UpdateDate DATETIME NOT NULL,
CONSTRAINT PK_Table1 PRIMARY KEY (Key1 ASC, Key2 ASC))
и
CREATE TABLE Table2 (
Key1 INTEGER NOT NULL,
Key2 INTEGER NOT NULL,
Key3 INTEGER NOT NULL,
...
Some fixed varchar data fields
...
CONSTRAINT PK_Table2 PRIMARY KEY (Key1 ASC, Key2 ASC, Key3 ASC))
с таблицей1 с двумя индексами:
CREATE INDEX IDX_Tabel1_Status1 ON Table1 (Key1 ASC, Status1 ASC, Key2 ASC)
CREATE INDEX IDX_Tabel1_Status2 ON Table1 (Key1 ASC, Status2 ASC, Key2 ASC)
Как вы уже догадались, Key1 и Key2 в обеих таблицах понравились.
То, что я хочу сделать, это удалить в таблице 2 все записи для записей, которые имеют определенный статус в таблице 1, сбросить 3 поля состояния до их первоначального значения и обновить дату в таблице 1. Поскольку число задействованных записей может быть большим (таблица 1 содержит до 500 тыс. Записей, а таблица 2 - от 20 до 40 млн.), И большую часть времени она занимает от 50% до 100% таблицы 1, я выполняю операции удаления и обновления в «маленьких» блоки (где-то между 1000 и 10000 записей в таблице 1). Поэтому я повторяю 2 следующих утверждения, пока все соответствующие записи не будут удалены / обновлены (одно удаление и обновление для каждой транзакции):
DELETE FROM Table2
WHERE Key1 = @Key1
AND Key2 in (
SELECT Key2
FROM Table
WHERE Key1 = @Key1
AND Status1 = @Status1
LIMIT 1000)
UPDATE Table1
SET Status1 = @NewStatus1, Status2 = @Status2, Status3 = @Status3, UpdateDate = @Date
WHERE Key1 = @Key1
AND Key2 in (
SELECT Key2
FROM Table
WHERE Key1 = @Key1
AND Status1 = @Status1
LIMIT 1000)
Удаление выполняется довольно быстро, но обновления занимают много времени (от 2 до 3 секунд на 1000 записей). Я думаю, это потому, что оба индекса должны быть обновлены. Поэтому мне интересно, улучшит ли это производительность, удалив оба индекса перед удалением / обновлением и воссоздав их потом. Но тогда подвыборы станут медленнее. В какой момент (процент от общего числа задействованных записей или абсолютное количество записей) мне следует рассмотреть возможность удаления индексов?
Спасибо,
Марк