运行大量sql命令来存档和删除数据的最佳方法是什么

时间:2011-08-31 12:57:36

标签: mysql scripting

我是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 个答案:

答案 0 :(得分:1)

将脚本复制到文件中并将其保存到磁盘。

然后运行mysql -u -p&lt; yoursavescriptname

这将从脚本中读取命令并依次执行它们。

此命令行本身可以放在Windows上的.bat文件中,也可以放在* nix上的可执行.sh文件中。

你也可以放置几个mysql等等。同一个.bat文件中的文件名行。

如果您想在特定时间运行此操作,则可以从cron条目引用.sh文件。但是,如果这样做,在某处的.sh文件中添加一个env,并将输出重定向到一个文件,因为cron运行的环境与登录用户不同。

答案 1 :(得分:0)

如果处方日期字段未编入索引,则需要很长时间并在运行时锁定表格。所以尝试添加一个索引。

答案 2 :(得分:0)

尝试command line mysql tool

编辑:添加示例

mysql -uusername -ppassword yourshema < your.sql

答案 3 :(得分:0)

我建议您尝试一次删除固定数量的行。我还没有使用过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,因此我的语法可能不正确。

希望这有帮助。