正在搜索数据库 table 以确定列表中不可见的文件名

Searching DB table to determine unseen file names from list

我正在处理磁盘中的平面文件,需要确保我不会处理同一个文件两次。每个已处理文件的文件名都存储在 postgresql 数据库中,在下一次迭代中,我需要确定磁盘上看不见的文件并处理它们,即。我需要确定磁盘上的文件名和数据库中的文件名的设置差异。

目前我的方法是从磁盘上的文件名创建一个 CTE,并将其加入 table 的可见文件名。磁盘上的文件列表很大且不断变化,处理速度变慢。

这是当前查询:

WITH input(filename) AS (VALUES ${filenames.joinToString { "(?)" }})
SELECT input.filename FROM input 
LEFT JOIN my_table pm ON input.filename ILIKE pm.filename
WHERE pm.filename IS NULL

${filenames.joinToString { "(?)" }} 扩展为类似于 (?), (?), (?),具体取决于文件名参数的数量。

我可以做些什么来加快这个过程?

我必须做的一件事是在文件名列上添加一个索引。什么样的指标才是正确的选择?

由于您使用的是 ILIKE,我不会在 pm.filename 上放置索引,而是在 LOWER(pm.filename) 上放置索引。这应该允许您删除 ILIKE 以支持性能更高的 LIKE。这也意味着您可以只使用简单的 B-tree index,因为它与 LIKE 配合使用效果很好。如果使用通配符,LIKE 很有用,但如果不使用,则只需使用普通的 =-equality。

最后,查询优化器很可能已经对查询做了很多工作,但我建议您查看此查询的 EXPLAIN (ANALYSE) 输出。我有一些改进建议,但不知道它们是否会有所帮助,或者它们都会归结为同一个查询计划。这完全取决于您!


这会获取第一个查询的第一个列表的结果,并从第二个查询的结果中删除所有匹配项。缺点是返回的文件名是小写的。

SELECT LOWER(filename)
FROM (VALUES ${filenames.joinToString { "(?)" }}) AS input(filename)
EXCEPT ALL (SELECT LOWER(filename) FROM my_table pm)

这个查询没有这个缺点,它只是 returns 所有在 my_table 中没有匹配的文件名。

SELECT filename
FROM (VALUES ${filenames.joinToString { "(?)" }}) AS input(filename)
WHERE NOT EXISTS (
  SELECT
  FROM my_table pm
  WHERE LOWER(pm.filename) = LOWER(input.filename)
)

最后一个查询可能等同于这个查询,但为了完整性我会添加它。

SELECT filename
FROM (VALUES ${filenames.joinToString { "(?)" }}) AS input(filename)
WHERE LOWER(filename) NOT IN (
  SELECT LOWER(pm.filename)
  FROM my_table pm
)