我有一个Db表,其中列出了已存档到LTO的媒体文件(其中有430万个)。正在进行的归档过程是手动的,由不同的人在停机时执行。我们需要一种有效的方法来确定文件夹中哪些文件不存档,以便我们可以根据需要完成作业,或者如果文件夹全部存档,则可以自信地删除该文件夹。
(为了论证,我们假设所有文件名都是唯一的,我们确实需要处理重复,但这不是这个问题。)
我应该只是启动Perl / Python / Ruby并通过它们与Db交谈。但是我需要花很长时间才能恢复速度,并且我有一种唠叨的感觉,认为它会有点过分。
我可以想到两种更简单的方法,但每种方法都有缺点,我想知道是否有更好的方法?
方法1:是简单地对每个目录结构进行bash-recurse,调用sqlite3 per-file并在查询返回时输出文件名并清空结果
这可能效率低于
方法2:通过目录结构递归并生成一个sql文件,该文件将:
虽然2看起来似乎比1更有效,但似乎首先构建比较表可能会产生一些开销,我有点想象备份表是一个单一的只读的东西,人们参考并且不要写进去。
纯SQL中有没有办法输出一个not-founds列表(没有它们存在于另一个表中)?
答案 0 :(得分:1)
查找不在其他表中的值很简单:
SELECT *
FROM SomeTable
WHERE File NOT IN (SELECT File
FROM OtherTable);
要创建另一个表,您可以编写一系列INSERT语句,或者只使用纯文本文件中shell的.import
命令。
不会保存temporary table。
答案 1 :(得分:0)
Sooo,我想我必须回答我自己的问题。
tl; dr - 使用脚本语言(我希望避免的事情)
在我的系统上尝试使用其他两种方法(详情如下),在检查33文件目录结构时,会产生以下数字,而不是430万条记录Db:
Ruby脚本:0.27s
Bash每个文件运行一次sqilte3("方法1"):0.73s
SQL制作临时表并使用" NOT IN" (方法2):8s
令我惊讶的是,all-sql比bash慢一个数量级。这是真的,使用macOS(10.12)命令行sqlite3和GUI" DB浏览器for SQLite"
这是我的Ruby脚本的关键。 Ruby当然不是最快的语言,你可能做得比这更好(但是如果你真的需要速度,可能是C的时候了)
localcode.net
(注意接下来的两个不是答案,但如果有人想检查我的方法,我会包括它们)
这是一个粗略的Bash recurse-through-files,它将打印 备份的文件列表(不是我想要的,但让我了解速度):
require "sqlite3"
db = SQLite3::Database.open 'path/to/mydb.db'
# This will skip Posix hidden files, which is fine by me
Dir.glob("search_path/**/*") do |f|
file = File.stat(f)
next unless file.file?
short_name = File.basename(f)
qouted_short_name = short_name.gsub("'", "''")
size = File.size(f)
sql_cmd = "select * from 'Backup_Table' where filename='#{qouted_short_name}' and sizeinbytesincrsrc=#{size}"
count = db.execute(sql_cmd).length
if count == 0
puts "UNARCHIVED: #{f}"
end
end
CL在他/她的回答中有详细的方法2