数据库端的昂贵查询

Expensive query on database side

让我们考虑一下这两个表:

|     Person    |
----------------
|  ID  | Name   | 
_________________
|  1   |  alice |
|  2   |  bob   |  
|  ... |  ...   |  
| 99   |  zach  |  


| PersonFriend  |
----------------
|  ID  |FriendID| 
_________________
|  1   |  2     |
|  2   |  1     |  
|  2   |  99    |
| ...  |  ...   |  
| 99   |  1     |  

这是两个用于模拟朋友和朋友的朋友的表。 现在第一个查询是:
1) 鲍勃的朋友是谁?
使用 SQL 的查询是:

SELECT p1.Person
FROM Person p1 JOIN PersonFriend  ON PersonFriend.FriendID = p1.ID 
     JOIN Person p2  ON PersonFriend.PersonID = p2.ID 
WHERE p2.Person = 'bob'

现在考虑反之亦然:
2) 谁是鲍勃的朋友?
SQL 中的查询是:

SELECT p1.Person 
FROM Person p1 JOIN PersonFriend  ON PersonFriend.PersonID = p1.ID 
     JOIN Person p2  ON PersonFriend.FriendID = p2.ID 
WHERE p2.Person = 'bob' 

好吧,这两个查询都很简单,但我不明白为什么第二个在数据库方面比第一个更昂贵。有人可以帮助我吗?

我记得在 Neo4j 图数据库一书中看到这个例子,认为这是一个高度做作的例子。在提到的示例中,性能不会受到影响。

正如他们在本书后面解释的那样,只有像朋友的朋友这样的更复杂的查询在计算上是昂贵的。

示例 2-3。爱丽丝的朋友的朋友

SELECT p1.Person AS PERSON, p2.Person AS FRIEND_OF_FRIEND
FROM PersonFriend pf1 JOIN Person p1
ON pf1.PersonID = p1.ID
JOIN PersonFriend pf2
ON pf2.PersonID = pf1.FriendID
JOIN Person p2
ON pf2.FriendID = p2.ID
WHERE p1.Person = 'Alice' AND pf2.FriendID <> p1.ID

我试着自己回复。 让我们考虑两个查询的查询树:

1) Bob 的朋友是谁?

   PROJ p1.Person
          |
          |
     J   O   I   N 
 p1.ID=PersonFriend.FriendID 
     /            \
    /              \
   /                \
Person p1    ###### J   O   I   N ######
              p2.ID=PersonFriend.PersonID 
                      /         \
                     /           \ 
                    /             \ 
                SEL(Persona p2)   PersonFriend
           p2.Person="bob"

2) 谁是鲍勃的朋友?

     PROJ p1.Person
              |
              |
         J   O   I   N 
     p1.ID=PersonFriend.PersonID 
         /            \
        /              \
       /                \
    Person p1    ###### J   O   I   N ######
                  p2.ID=PersonFriend.FriendID  
                          /         \
                         /           \ 
                        /             \ 
                    SEL(Persona p2)   PersonFriend
               p2.Person="bob"

PersonFriend table 的key是compound: ,记录按ID排序。 如您所见,用哈希标记的两个连接具有不同的参数。第一个不需要遍历PersonFriendtable的所有记录,因为记录是按照ID排序的。第二次join,需要遍历PersonFriend的所有记录table.
我认为这就是第二次查询比第一次查询更昂贵的原因。