sql - 具有许多表的 PostgreSQL 最佳 SELECT 查询

标签 sql postgresql join subquery query-optimization

我使用的是 PostgreSQL 数据库,有 4 个表可供使用:registry、invoice、invoice_position、user_involved

表注册表列:

id
reg_name

表格发票:

id
reg_id(FK to registry, can be many invoices in one registry)
invoice_name

表invoice_position:

id
invoice_id(FK to invoice, can be many positions in invoice)
position_name

表 user_involved:

id
Inv_position_id(FK to invoice_position, it's a one to one relationship)
user_name

我需要创建一个 SELECT 查询,如果 registry 表中出现不止一次 user_involved(这仅与 user_involved 相关,由 FK 的 invoice_position ->发票->注册)。需要注意的几件事是,这些表每个包含超过 +/- 1.000.000 行(注册表表除外),此时我无法在注册表和 user_involved 之间添加直接关系。问题是如何编写最佳 SELECT,或者在这种状态下是否有可能,因为嵌套多个 SELECT 将花费很长时间。

编辑: 到目前为止,这是我尝试过的:

SELECT rg.id, COUNT(ui.id) FROM registry rg
  LEFT JOIN invoice inv ON inv.reg_id = rg.id
  LEFT JOIN invoice_position ip ON ip.invoice_id = inv.id
  LEFT JOIN user_involved ui ON ui.inv_position_id = ip.id
WHERE ip.id = $id GROUP BY rg.id,ui.id HAVING COUNT (ui.id) > 1;

此查询将在一个 while 循环内,其中带有给定不同发票位置 ID 的变量“id”。

最佳答案

我会先做:

EXPLAIN 
SELECT rg.id, COUNT(ui.id)
FROM invoice_position ip, invoice inv, registry rg, user_involved ui
WHERE ip.id = $id
  AND ip.invoice_id = inv.id
  AND inv.reg_id = rg.id
  AND ui.inv_position_id = ip.id
GROUP BY rg.id
HAVING COUNT(ui.id) > 1;

看看你得到了什么。不使用 LEFT OUTER JOIN 的原因是它们限制了优化器可以选择的计划(或者至少他们在我上次检查时做了)并且这个查询似乎没有需要他们。

除此之外,您还可以考虑一次获取多个 invoice_position 行并在数据库外部进行匹配。这样您就可以稍微分摊执行查询的成本,但代价是调用代码会更复杂一些。

例如:

SELECT ip.id, rg.id, COUNT(ui.id)
FROM invoice_position ip, invoice inv, registry rg, user_involved ui
WHERE ip.id IN $id_list
  AND ip.invoice_id = inv.id
  AND inv.reg_id = rg.id
  AND ui.inv_position_id = ip.id
GROUP BY ip.id, rg.id
HAVING COUNT(ui.id) > 1;

关于sql - 具有许多表的 PostgreSQL 最佳 SELECT 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53593777/

相关文章:

.net - 使用 .NET 批量插入到 Oracle

ruby-on-rails - 仅在生产中发生错误时如何调试 Rails 应用程序?

postgresql - 如何检查 PostgreSQL 9.3 中右侧的无限范围是否为 NULL - 确保使用 GIST 索引

MySQL:从交叉连接行返回总记录数?

php mysql forum app...如何制作粘性线程?

sql - 从 View 或表中更快地获取数据?

c# - 数据库中的数组插入

sql - 最简单的标准 C 语言 SQL 实现,可用于基于 Linux 的 ARM 终端

sql - 在 Postgres 中选择每个用户的每 N 行

mysql - SQL,未使用的 LEFT JOIN 变慢,优化器不工作?