我正在尝试从我的数据库中获取好友列表,我的查询正在运行,但需要花费大量时间来加载结果(有时大约需要 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;
所以我的问题是:您有什么好的建议可以改进我的查询吗?
谢谢!
最佳答案
根据经验,如果您在 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 = ?
更新:现在了解它应该是用户的 friend 列表,更改 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 = ?
我们想要一个关系列表,但我们使用用户作为主表。这有点尴尬。 @fraxool's query which is FROM relation更有意义,但它可以使用一些关于什么约束去哪里的清理。 JOIN ON 仅关于网格化表。 WHERE 用于限制整体返回的内容。将这些原则应用于@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 != ?
的附加约束是不必要的,除非你可以成为自己的 friend 。这应该在 relation.leader 和 relation.subscriber 的列约束中处理。
关于mysql - 如何加速我的 "friends list"MySQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28531834/