1

我有一个相当复杂的操作,我试图只使用一个 SQL 查询来执行,但我不确定这是否比将其分解为 n 个查询更优化。基本上,我有一个名为“Users”的表,其中包含用户 ID 及其相关联的 fb_ids(id 是 pk,fb_id 可以为空)。

+-----------------+
| id | .. | fb_id |
|====|====|=======|
| 0  | .. | 12345 |
| 1  | .. | 31415 |
| .. | .. |  ..   |
+-----------------+

我还有另一个名为“Friends”的表,它代表两个用户之间的朋友关系。这使用他们的 id(不是他们的 fb_id),应该是双向关系。

+----------------+
| id | friend_id |
|====|===========|
| 0  |     1     |
| 1  |     0     |
| .. |    ..     |
+----------------+
// user 0 and user 1 are friends

所以问题来了: 我们得到了一个特定用户的 id(“my_id”)和一个该用户的 Facebook 好友数组(一个 fb_id 数组,称为 fb_array)。我们希望更新 Friends 表,以便它尊重 Facebook 友谊作为我们用户之间的有效友谊。需要注意的是,并非他们所有的 Facebook 朋友都会在我们的数据库中拥有帐户,因此应该忽略这些朋友。每次用户登录时都会调用此查询,以便在他们在 Facebook 上添加任何新朋友时更新我们的数据。这是我写的查询:

INSERT INTO Friends (id, friend_id)
SELECT "my_id", id FROM Users WHERE id IN
  (SELECT id FROM Users WHERE fb_id IN fb_array)
AND id NOT IN
  (SELECT friend_id FROM Friends WHERE id = "my_id")

第一个 IN 子句的重点是获取所有用户的子集,这些用户也是你的 Facebook 朋友,这是我担心的主要部分。因为 fb_ids 是作为一个数组给出的,所以我必须将所有 id 解析为一个用逗号分隔的巨大字符串,该字符串构成“fb_array”。我担心为那个 IN 子句设置这么大的字符串的效率(用户可能在 Facebook 上有成百上千的朋友)。你能想出更好的方法来编写这样的查询吗?

还值得注意的是,此查询不保持朋友关系的双重性质,但这不是我担心的(为此扩展它是微不足道的)。

4

2 回答 2

1

如果我没记错的话,如果您UNIQUE对组合有限制,您的查询可以简化(id, friend_id)为:

INSERT IGNORE INTO Friends 
  (id, friend_id)
SELECT "my_id", id 
FROM Users 
WHERE fb_id IN fb_array ;

您应该有索引User (fb_id, id)并测试效率。如果数组中的项目数太大(超过几千个),您可能必须拆分数组并多次运行查询。包含您的数据和设置的配置文件。

于 2013-01-04T01:07:20.153 回答
1

取决于以下列是否可以为空(值可以是NULL):

  • 用户.id
  • FRIENDS.friend_id

可空:

SELECT DISTINCT
       "my_id", u.id 
  FROM Users u
 WHERE u.fb_id IN fb_array
   AND u.id NOT IN (SELECT f.friend_id 
                      FROM FRIENDS f
                     WHERE f.id = "my_id")

不可为空:

   SELECT "my_id", u.id 
     FROM Users u
LEFT JOIN FRIENDS f ON f.friend_id = u.id
                   AND f.id = "my_id"
    WHERE u.fb_id IN fb_array
      AND f.fried_id IS NULL

欲了解更多信息:

谈到数组中的值的数量

上面提到的两篇文章中运行的测试包含 100 万行,具有 10,000 个不同的值。

于 2013-01-04T01:12:57.397 回答