如何在 postgres 中有效地(使用索引)查找未引用的行?
How to find unreferenced rows efficiently (with an index) in postgres?
如何在 postgresql 中有效地找到没有指向它们的外键的巨大 table 行?
假设我们有一个 table 的橙子和橙子分析结果。橙色主键不受我们控制,也没有任何特定顺序。橙子具有与专用程序进行的分析相关的列。
Table oranges
(PK超过orange_id,btree超过created_at):
orange_id | raw_orange_data | created_at
1 | '{ "foo": 5}' | '2021-08-09 15:00:00'
4092141 | '{ "foo": 42}' | '2021-08-09 16:00:00'
42 | '{ "foo": 13}' | '2021-08-09 11:00:00'
上述其他程序存在多个版本,我们希望保留结果以供比较。我们应该如何安排外键才能select下一个需要高效处理的橘子?
Table orange_analysis
(PK over orange_id, analysis_version):
orange_id | analysis_version| analysis_result
1 | 1 | 9000
1 | 2 | 9001
4092141 | 1 | 50
4092141 | 2 | 60
我们目前正在考虑
SELECT *
FROM oranges
LEFT JOIN orange_analysis ON oranges.id = orange_analysis.orange_id
WHERE (oranges_analysis.orange_id IS NULL AND oranges_analysis.analysis_version = 1)
ORDER BY oranges.created_at DESC
LIMIT 500
或 NOT EXISTS
查询,但我担心他们无法使用索引。
有没有办法组织我们的 table 以确保此类查询 运行 快速?没有 postgres 走过 oranges
table 可以完成吗?如果我们没有多个版本,我会使用可为空的 FK 到 orange_analysis
,但不幸的是,我们必须维护多个分析版本。
我想出的唯一一件事是让 analysis_result
可以为空,为所有分析变体的所有橙子创建它为空,在其上放置一个索引,并将 analysis_result
列设置为一旦分析取得进展,它各自的价值。
如果您正在寻找缺少特定版本的橙子,那么您可以使用:
SELECT o.*
FROM oranges o LEFT JOIN
orange_analysis oa
ON o.id = oa.orange_id AND oa.analysis_version = 1
WHERE oa.orange_id IS NULL
ORDER BY o.created_at DESC
LIMIT 500;
不过,为了性能,我可能会建议 NOT EXISTS
使用特定索引:
SELECT o.*
FROM oranges o
WHERE NOT EXISTS (SELECT 1
FROM orange_analysis oa
WHERE o.id = oa.orange_id AND oa.analysis_version = 1
)
ORDER BY o.created_at DESC
LIMIT 500;
您需要的索引是 oranges(created_at desc, id)
和 orange_analysis(orange_id, analysis_version)
。这些也适用于 LEFT JOIN
版本,但我不确定它们是否会避免对 ORDER BY
.
进行排序
我认为普通集合操作通常是最有效的方法:
SELECT id FROM oranges
EXCEPT
SELECT orange_id FROM orange_analysis
WHERE analysis_version = 1;
这将仅输出第一个查询中没有出现在第二个查询结果中的那些行(设置差异)。
如何在 postgresql 中有效地找到没有指向它们的外键的巨大 table 行?
假设我们有一个 table 的橙子和橙子分析结果。橙色主键不受我们控制,也没有任何特定顺序。橙子具有与专用程序进行的分析相关的列。
Table oranges
(PK超过orange_id,btree超过created_at):
orange_id | raw_orange_data | created_at
1 | '{ "foo": 5}' | '2021-08-09 15:00:00'
4092141 | '{ "foo": 42}' | '2021-08-09 16:00:00'
42 | '{ "foo": 13}' | '2021-08-09 11:00:00'
上述其他程序存在多个版本,我们希望保留结果以供比较。我们应该如何安排外键才能select下一个需要高效处理的橘子?
Table orange_analysis
(PK over orange_id, analysis_version):
orange_id | analysis_version| analysis_result
1 | 1 | 9000
1 | 2 | 9001
4092141 | 1 | 50
4092141 | 2 | 60
我们目前正在考虑
SELECT *
FROM oranges
LEFT JOIN orange_analysis ON oranges.id = orange_analysis.orange_id
WHERE (oranges_analysis.orange_id IS NULL AND oranges_analysis.analysis_version = 1)
ORDER BY oranges.created_at DESC
LIMIT 500
或 NOT EXISTS
查询,但我担心他们无法使用索引。
有没有办法组织我们的 table 以确保此类查询 运行 快速?没有 postgres 走过 oranges
table 可以完成吗?如果我们没有多个版本,我会使用可为空的 FK 到 orange_analysis
,但不幸的是,我们必须维护多个分析版本。
我想出的唯一一件事是让 analysis_result
可以为空,为所有分析变体的所有橙子创建它为空,在其上放置一个索引,并将 analysis_result
列设置为一旦分析取得进展,它各自的价值。
如果您正在寻找缺少特定版本的橙子,那么您可以使用:
SELECT o.*
FROM oranges o LEFT JOIN
orange_analysis oa
ON o.id = oa.orange_id AND oa.analysis_version = 1
WHERE oa.orange_id IS NULL
ORDER BY o.created_at DESC
LIMIT 500;
不过,为了性能,我可能会建议 NOT EXISTS
使用特定索引:
SELECT o.*
FROM oranges o
WHERE NOT EXISTS (SELECT 1
FROM orange_analysis oa
WHERE o.id = oa.orange_id AND oa.analysis_version = 1
)
ORDER BY o.created_at DESC
LIMIT 500;
您需要的索引是 oranges(created_at desc, id)
和 orange_analysis(orange_id, analysis_version)
。这些也适用于 LEFT JOIN
版本,但我不确定它们是否会避免对 ORDER BY
.
我认为普通集合操作通常是最有效的方法:
SELECT id FROM oranges
EXCEPT
SELECT orange_id FROM orange_analysis
WHERE analysis_version = 1;
这将仅输出第一个查询中没有出现在第二个查询结果中的那些行(设置差异)。