正在搜索数据库 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
)
我正在处理磁盘中的平面文件,需要确保我不会处理同一个文件两次。每个已处理文件的文件名都存储在 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
)