我正在尝试从我的数据库中获取朋友列表并且我的查询正在运行但是需要花费大量时间来加载结果(有时大约10秒)。
这是:
SELECT F.status, U.username, U.email, UI.country, UI.birthday, P.thumb_url
FROM user U, relation F, user_info UI, photo P
WHERE
CASE
WHEN F.leader = 'USER_ID'
THEN F.subscriber = U.id
WHEN F.subscriber= 'USER_ID'
THEN F.leader= U.id
END
AND
U.id = UI.user_id
AND
UI.main_photo = P.id
AND
F.status='1';
我的“关系”表格如下:
CREATE TABLE IF NOT EXISTS `relation` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`leader` int(11) NOT NULL,
`subscriber` int(11) NOT NULL,
`time` timestamp NOT NULL DEFAULT,
`status` int(11) NOT NULL DEFAULT '0',
`seen` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
所以我的问题是:为了改善我的查询,你有一些好的建议吗?
谢谢!
答案 0 :(得分:3)
根据经验,如果您在SQL中使用CASE(或任何其他if / then逻辑),那么您可能做错了。 SQL是一种声明性语言,这意味着你会问它问题。如果你告诉它如何回答这个问题,它可能会以糟糕的(或缓慢的)结束。关键是将约束用户ID放在WHERE子句中,并将其保持在连接之外。这改变了它告诉数据库如何完成其工作,以及询问数据库。数据库将负责其余的工作。
使用JOIN语法可以更清楚地了解连接是什么以及什么是约束。当您希望将多个表中的行拼接在一起时,可以使用SQL joins。数据库知道如何优化它们。
第二位是use EXPLAIN告诉你MySQL是如何执行查询的,它的速度很慢。这通常表示您需要索引的位置或需要重写查询的哪个部分。
我将假设Relationship.leader
和Relationship.subscriber
都是User.id
上的外键,并描述谁关注该用户以及他们关注的是谁,并且您希望向每个人展示与给定USER_ID
相关的用户。不需要CASE,你可以检查是否匹配(检查那个)。
SELECT F.status, U.username, U.email, UI.country, UI.birthday, P.thumb_url
FROM user U
JOIN user_info UI
ON U.id = UI.user_id
JOIN photo P
ON UI.main_photo = P.id
JOIN relation F
ON F.leader = U.id OR F.subscriber = U.id
WHERE F.status='1'
AND U.id = ?
更新:现在了解它应该是用户的朋友列表,更改U.id = ?
以检查用户是否处于关系中。
SELECT F.status, U.username, U.email, UI.country, UI.birthday, P.thumb_url
FROM user U
JOIN user_info UI
ON U.id = UI.user_id
JOIN photo P
ON UI.main_photo = P.id
JOIN relation F
ON F.leader = U.id OR F.subscriber = U.id
WHERE F.status='1'
AND F.leader = ? OR F.subscriber = ?
我们想要一个关系列表,但我们使用Users作为主表。这有点尴尬。 @fraxool's query which is FROM relation更有意义,但它可以使用一些关于约束在哪里的清理。 JOIN ON仅关于网格化表格。在哪里限制整体返回的内容。将这些原则应用于@ fraxool的新查询,我们得到......
SELECT username, email, ui.gender, ui.country, ui.birthday, p.thumb_url
FROM relation R
JOIN user U
ON U.id = R.leader OR U.id = R.subscriber
JOIN user_info UI
ON U.id = UI.user_id
JOIN photo P
ON UI.main_photo = P.id
WHERE R.status = 1
AND (R.leader = ? OR R.subscriber = ?)
除非您可以成为自己的朋友,否则U.id != ?
的附加约束是不必要的。这是应该在relation.leader和relation.subscriber的列约束中处理的东西。
答案 1 :(得分:0)
感谢您的回答。
所以我找到了一个使用JOIN语法而不是大小写的好解决方案。我在这里发布,因为它可以帮助你们中的一些。
SELECT username, email, ui.gender, ui.country, ui.birthday, p.thumb_url
FROM relation
RIGHT JOIN user ON
(user.`id` = relation.`leader`
OR
user.`id` = relation.`subscriber`)
AND
user.`id` != '?'
AND
relation.`status` = '1'
JOIN user_info ui, photo p
WHERE
(relation.`leader` = '?'
OR
relation.`subscriber` = '?')
AND user.`id` = ui.`user_id`
AND ui.`main_photo` = p.`id`;
此查询只需要大约100毫秒来加载结果,而我发布的第一个查询大约需要5秒......