我是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管理员只显示前两个存档表。在具有相同模式和较少数据的数据库上,脚本可以正常工作。
有没有人知道如何最好地解决这个问题?
答案 0 :(得分:1)
将脚本复制到文件中并将其保存到磁盘。
然后运行mysql -u -p&lt; yoursavescriptname
这将从脚本中读取命令并依次执行它们。
此命令行本身可以放在Windows上的.bat文件中,也可以放在* nix上的可执行.sh文件中。
你也可以放置几个mysql等等。同一个.bat文件中的文件名行。
如果您想在特定时间运行此操作,则可以从cron条目引用.sh文件。但是,如果这样做,在某处的.sh文件中添加一个env,并将输出重定向到一个文件,因为cron运行的环境与登录用户不同。
答案 1 :(得分:0)
如果处方日期字段未编入索引,则需要很长时间并在运行时锁定表格。所以尝试添加一个索引。
答案 2 :(得分:0)
答案 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,因此我的语法可能不正确。
希望这有帮助。