首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用large in()子句优化MySQL查询

使用large in()子句优化MySQL查询
EN

Stack Overflow用户
提问于 2015-11-25 22:11:48
回答 2查看 618关注 0票数 0

这里有一个简单的要求,即从Friend表中查询六度关系的量。

Friend的结构如下所示:

代码语言:javascript
复制
+----------+---------+------+-----+---------+----------------+
| Field    | Type    | Null | Key | Default | Extra          |
+----------+---------+------+-----+---------+----------------+
| id       | int(11) | NO   | PRI | NULL    | auto_increment |
| userId   | int(11) | NO   | MUL | NULL    |                |
| friendId | int(11) | NO   |     | NULL    |                |
+----------+---------+------+-----+---------+----------------+

假设我想知道userId:1的六度关系量,我写下了六个查询,如下所示

SELECT friendId FROM Friend WHERE userId = 1来获得一个学位的朋友。

然后执行

SELECT friendId FROM Friend WHERE userId in (/*above query result*/)

五次。

问题并不像看起来那么简单,因为我的朋友表中有数百万条记录。

尽管用户在一个度关系中只有两个朋友,但他/她的六度关系量很有可能是1大于六位数。

in子句中的项数是指数级的。

然后,六个查询花费超过一分钟的时间来获得结果。

如何优化这种情况?

EN

回答 2

Stack Overflow用户

发布于 2015-11-25 22:19:04

您可以使用subqueries,看看MySQL优化器是否足够聪明,能够将它们重写为连接(通常是这样)。

但实际上RDBMS并不适合这项任务。最好研究一下基于图形的数据库。请参见this question示例。

票数 0
EN

Stack Overflow用户

发布于 2015-11-25 22:25:25

创建一个临时表来保存中间结果,并使用JOIN而不是IN:

代码语言:javascript
复制
DROP TEMPORARY TABLE IF EXISTS tmp_friends;
CREATE TEMPORARY TABLE `tmp_friends` (
    `id` INT UNSIGNED NOT NULL,
    PRIMARY KEY (`id`)
);

INSERT INTO tmp_friends VALUES(<id of the given user>);

#run this 6 times
INSERT IGNORE INTO tmp_friends
SELECT f.userId
FROM tmp_friends t
JOIN Friend f ON f.friendId = t.id

SELECT f.*
FROM tmp_friends t
JOIN Friend f ON f.userId = t.id
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33918706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档