两个 MySQL 表的最佳连接

Optimal join in two MySQL tables

我有一个 table (T1) 约。 500000 条非重复记录:

ID1    Relation  ID2
4      Rel4      13
5      Rel5       4
13     Rel13     16
16     Rel16     5

我有属性 table T1_Prop:

ID    Entity    
4     Ent4     
5     Ent5
13    Ent13   
16    Ent16  

我想以如下有效方式加入这两个 table(基于 id : 4):

 Entity   Relation   Entity
 Ent4      Rel4      Ent13  
 Ent5      Rel5      EntEnt4

我设计了这个 select 语句,包括 JOIN,效果很好。但是,我不确定这是否是最好的方法:

select 
  a.entity, 
  r.relation, 
  b.entity 
from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 AND (r.ID1=4 OR r.ID2=4) 
INNER JOIN T1_Prop as b ON b.ID=r.ID2;

这是 SQL 的一个很好的用法。它是为这种查询而构建的。

T1 上,您需要两个覆盖索引来加快速度。他们是:

(ID1, ID2, relation)

(ID2, ID1, relation)

这两个索引是用来处理OR子句的。这是我看到的唯一潜在的性能问题,那只是因为 OR 操作有时会欺骗查询规划器进行过多的 table 扫描。

尝试重构您的查询,使您选择的 ID 值更加明显。

select   a.entity, r.relation, b.entity 
  from T1 as r 
 INNER JOIN T1_Prop as a ON a.ID=r.ID1  
 INNER JOIN T1_Prop as b ON b.ID=r.ID2
 WHERE (r.ID1=4 OR r.ID2=4) 

然后,如果您遇到性能问题,请在创建覆盖索引后,再次将其重构为

select   a.entity, r.relation, b.entity 
  from T1 as r 
 INNER JOIN T1_Prop as a ON a.ID=r.ID1  
 INNER JOIN T1_Prop as b ON b.ID=r.ID2
 WHERE r.ID1=4 
UNION
select   a.entity, r.relation, b.entity 
  from T1 as r 
 INNER JOIN T1_Prop as a ON a.ID=r.ID1  
 INNER JOIN T1_Prop as b ON b.ID=r.ID2
 WHERE r.ID2=4 

除了第一个 ON 子句外,您的查询看起来很好。条件 (r.ID1=4 OR r.ID2=4) 不是 T1_Prop 中的记录加入 T1 记录的规则。这是一个条件,T1 记录要考虑并因此属于 WHERE 子句。

select 
  a.entity AS entity1, 
  r.relation, 
  b.entity AS entity2
FROM t1 AS r 
INNER JOIN t1_prop AS a ON a.id = r.id1
INNER JOIN t1_prop AS b ON b.id = r.id2
WHERE r.id1 = 4 OR r.id2 = 4;

这不会改变执行计划; DBMS 将同样执行此操作。但它更具可读性,因为它显示了实际意图:获取其中一个 ID 为 4 的关系并将实体连接到这些关系。

另一个表达这种意图的选项是:

select 
  a.entity AS entity1, 
  r.relation, 
  b.entity AS entity2
FROM (SELECT * FROM t1 WHERE r.id1 = 4 OR r.id2 = 4) AS r 
INNER JOIN t1_prop AS a ON a.id = r.id1
INNER JOIN t1_prop AS b ON b.id = r.id2;

有些人认为 FROM 中的子查询可读性较差,但是,其他人则不这么认为。当查询变得更加复杂并且说您甚至处理来自不同表的聚合时,这通常是构建干净查询的方法。

以上查询实际上都没有比另一个更好或更差。