使用大型in()子句优化MySQL查询

时间:2015-11-25 14:11:48

标签: mysql

有一个简单的要求是从You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'events.sched_expired < '2015-11-25' THEN '0' ' at line 4 表中查询六度关系的数量。

UPDATE events SET events.scheduled = ( CASE sched_exp_type WHEN 'counter' and events.sched_counter <= '0' THEN '0' WHEN 'date' events.sched_expired < '2015-11-25' THEN '0' ELSE (events.scheduled) END ) 的结构是这样的:

 $c_date = date("Y-m-d");
echo $c_date."<br/>";
$update_sched_column = "UPDATE events SET  events.scheduled = (
CASE sched_exp_type
WHEN 'counter' and events.sched_counter <= '0' THEN '0'
WHEN 'date' events.sched_expired < '$c_date' THEN '0'
ELSE (events.scheduled)
END
)";

假设我想知道Friend的六度关系金额,并且我写下了这样的六个查询 Friend获得一个学位的朋友。

然后执行
+----------+---------+------+-----+---------+----------------+ | 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 | | +----------+---------+------+-----+---------+----------------+
五次。

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

用户userId:1的六度关系数量很可能超过六位数,尽管他/她只有两个朋友处于一度关系。

IN子句中的项目数量是指数级的。

然后六个查询花了一分多钟才得到结果。

如何优化这种情况?

2 个答案:

答案 0 :(得分:0)

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

但实际上RDBMS不适合这项任务。更好地了解基于图形的数据库。例如,请参阅this question

答案 1 :(得分:0)

创建临时表以保存中间结果,并创建JOIN而不是IN:

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