【发布时间】:2019-03-09 22:33:04
【问题描述】:
如果一个表在多个列中被另一个表引用,那么从两个表中获取数据的最快方法是什么?
考虑一个包含公司名称的表格和一个包含合同的表格。每个合约都可以有一个client、一个intermediary和一个contractor——在每个组合中。每个值可能是null,同一家公司可能在每个合同行中出现一次、两次或三次。
表定义为:
CREATE TABLE company (id integer,name text);
CREATE TABLE contract (id integer, client integer, intermediary integer, contractor integer);
我用下面的测试数据创建了一个 SQL 小提琴: https://www.db-fiddle.com/f/irCodeZjeEPWvhmRwMcHqT/0
测试数据:
INSERT INTO company (id,name) VAlUES (1,'Company 1');
INSERT INTO company (id,name) VAlUES (2,'Company 2');
INSERT INTO company (id,name) VAlUES (3,'Company 3');
INSERT INTO company (id,name) VAlUES (4,'Company 4');
INSERT INTO company (id,name) VAlUES (5,'Company 5');
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (1,NULL,NULL,NULL);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (2,NULL,2,3);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (3,1,NULL,NULL);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (4,NULL,2,NULL);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (5,1,2,3);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (6,4,NULL,5);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (7,1,NULL,1);
INSERT INTO contract (id,client,intermediary,contractor) VAlUES (7,3,3,3);
现在,使用 PostgreSQL 9.6,需要一个查询来返回合同 ID 和每个相关公司的名称。使用子查询很容易:
SELECT
id,
(SELECT name FROM company WHERE id = client) AS "clientName",
(SELECT name FROM company WHERE id = intermediary) AS "intermediaryName",
(SELECT name FROM company WHERE id = contractor) AS "contractorName"
FROM contract;
但是,在现实世界中,由于查询复杂得多,我们在这里遇到了性能问题。现在的问题是:有没有办法改进它? JOIN 会比子查询快吗?如果是:那将如何运作?
当然,你可以做类似的事情
SELECT * FROM contract LEFT JOIN company ON company.id = ANY(ARRAY[client,contractor,intermediary]);,
但在这种情况下,哪个公司在合同中扮演哪个角色的信息会丢失。
(编辑:在现实世界中,有索引、外键约束和其他东西。为了简洁起见,我把所有这些都放在一边了。)
【问题讨论】:
-
我目前的一般评论是“更好”/“最好”等:除非你定义它,否则工程中没有“更好”/“最好”之类的东西。同样不幸的是,所有合理的实际定义都需要大量的经验,以及与对细节的混乱敏感度相互作用的大量因素。进行简单的设计。当您通过测量证明您可以想到的设计和所有替代方案都存在问题时(无论当时意味着什么),然后提出一个非常具体的问题。这也应该定义“更好”/“最好”。 meta.stackexchange.com/q/204461
标签: sql postgresql performance join subquery