Каков наилучший способ запустить ряд команд SQL для архивирования и удаления данных - PullRequest
0 голосов
/ 31 августа 2011

Я новичок в mysql, так что прости меня, если решение моей проблемы очевидно. У меня есть база данных mysql, в которой есть несколько таблиц, которые мне нужно заархивировать. Ряд таблиц имеет более 1000000 строк. У меня есть 11 таблиц, которые я архивирую и затем удаляю из.

Фрагмент из моего кода будет:

set @archive_before_date='2010-10-01'

create table if not exists archive_prescription as 
select * from prescription where prescriptiondate < @archive_before_date;

delete from prescription where prescriptiondate < @archive_before_date;

В настоящее время я использую браузер mysql и запускаю скрипт на вкладке скрипта. Когда я запускаю скрипт, браузер запросов MySQL показывает в диспетчере задач, что он не отвечает, а администратор MySQL показывает только первые две архивные таблицы. В базе данных с той же схемой и меньшим количеством данных скрипт работает отлично.

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

Ответы [ 4 ]

1 голос
/ 31 августа 2011

Скопируйте скрипт в файл и сохраните его на диск.

Затем запустите mysql -u -p

Это прочитает команды из скрипта и выполнит их по очереди.

Эту командную строку можно поместить в файл .bat в Windows или в исполняемый файл .sh в * nix.

Также вы можете поместить несколько строк mysql и т. Д. В один и тот же файл .bat.

Если вы хотите запустить это в определенное время, вы можете обратиться к файлу .sh из записи cron. однако, если вы сделаете это, добавьте куда-нибудь env в файл .sh и перенаправьте вывод в файл, когда cron запускается в другой среде вошедшему в систему пользователю.

0 голосов
/ 31 августа 2011

Я бы порекомендовал вам попытаться удалить фиксированное количество строк одновременно. Я еще не использовал mysql, но вот пример из MS SQL.

DECLARE @DELETE_COUNT INT, @ARCHVIE_DATE DATETIME

SET @ARCHIVE_DATE = '2010-10-01'
SET @DELETE_COUNT = 1000

WHILE (@DELETE_COUNT <> 0)
BEGIN

DELETE TOP (@DELETE_COUNT)
OUTPUT DELETED.*
INTO MyArchiveTable
FROM MyTable a
WHERE a.PrescriptionDate < @ARCHIVE_DATE

SET @DELETE_COUNT = @@ROWCOUNT

END

Преимущество заключается в удалении и архивировании данных в одном операторе. Если MySQL не имеет ничего подобного, ваш план вполне разумен. Вам необходимо сохранить первые 1000 строк, а затем удалить их. Пожалуйста, убедитесь, что у вас есть заказ на ... в случае, если кто-то изменяет кластерный индекс на вас и, очевидно, индекс на PrescriptionDate . Если возможно, вы можете создать кластерный индекс для PrescriptionDate. Или Вы можете добавить дату рецепта в существующий кластерный индекс в качестве первого столбца.

DECLARE @DELETE_COUNT INT, @ARCHVIE_DATE DATETIME

SET @ARCHIVE_DATE = '2010-10-01'
SET @DELETE_COUNT = 1000

WHILE (@DELETE_COUNT <> 0)
BEGIN

BEGIN TRANSACTION

INSERT INTO MyArchiveTable
SELECT TOP(@DELETE_COUNT) * FROM MyTable a WHERE a.PrescriptionDate < @ARCHIVE_DATE
ORDER BY a.PrescriptionDate

DELETE FROM MyTable a INNER JOIN
(SELECT TOP(@DELETE_COUNT) * FROM MyTable
WHERE PrescriptionDate < @ARCHIVE_DATE ORDER BY PrescriptionDate) b ON a.Id = b.Id

SET @DELETE_COUNT = @@ROWCOUNT

COMMIT TRANSACTION    
END

Это также имеет дополнительное преимущество - не откатывать весь процесс удаления в случае тупика. Если в MySQL есть операторы try / catch, вы можете использовать их для перехвата ошибок взаимоблокировки, а затем их игнорировать. Цикл while должен повторяться снова и снова до тех пор, пока он не будет успешным.

Обратите внимание, что я никогда не использовал MySQL, поэтому мой синтаксис может быть неправильным.

Надеюсь, это поможет.

0 голосов
/ 31 августа 2011

Попробуйте инструмент mysql командной строки

РЕДАКТИРОВАТЬ: добавить пример

mysql -uusername -ppassword yourshema < your.sql
0 голосов
/ 31 августа 2011

Если поле prescriptiondate не проиндексировано, потребуется много времени и заблокировать таблицу во время работы. Поэтому попробуйте добавить индекс.

...