数据库端的昂贵查询
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.
我认为这就是第二次查询比第一次查询更昂贵的原因。
让我们考虑一下这两个表:
| 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.
我认为这就是第二次查询比第一次查询更昂贵的原因。