查找(sqlite3)表中是否_not_列出给定字符串的有效方法

时间:2018-03-16 04:29:30

标签: sql sqlite

我有一个Db表,其中列出了已存档到LTO的媒体文件(其中有430万个)。正在进行的归档过程是手动的,由不同的人在停机时执行。我们需要一种有效的方法来确定文件夹中哪些文件存档,以便我们可以根据需要完成作业,或者如果文件夹全部存档,则可以自信地删除该文件夹。

(为了论证,我们假设所有文件名都是唯一的,我们确实需要处理重复,但这不是这个问题。)

我应该只是启动Perl / Python / Ruby并通过它们与Db交谈。但是我需要花很长时间才能恢复速度,并且我有一种唠叨的感觉,认为它会有点过分。

我可以想到两种更简单的方法,但每种方法都有缺点,我想知道是否有更好的方法?

方法1:是简单地对每个目录结构进行bash-recurse,调用sqlite3 per-file并在查询返回时输出文件名并清空结果

这可能效率低于

方法2:通过目录结构递归并生成一个sql文件,该文件将:

  • 创建一个包含所有磁盘文件的表(让我们称之为“工作表”)
  • 将其与存档表进行比较 - 选择工作表中的所有文件,但不选择存档表中的所有文件
  • 销毁工作台,或退出而不保存

虽然2看起来似乎比1更有效,但似乎首先构建比较表可能会产生一些开销,我有点想象备份表是一个单一的只读的东西,人们参考并且不要写进去。

纯SQL中有没有办法输出一个not-founds列表(没有它们存在于另一个表中)?

2 个答案:

答案 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

SQL

CL在他/她的回答中有详细的方法2