我正在一个小型社交网络上工作,但是我正在努力优化设计的阻碍部分。我有3个表阻止,供稿和用户。它工作正常,但是当我添加阻止查询时,查询时间从16ms或更短到超过50ms或更高,对于简单的事情来说似乎很多。实际上,在我的hedisql sql中没有阻塞的情况下,有时查询时间报告为0ms,因为我猜它低于一定的时间。
屏蔽的想法是,如果用户屏蔽了其他人,则他们将无法看到自己的供稿,而被屏蔽的人将无法看到屏蔽器。
我正在努力优化的部分是: 左联接阻塞ON阻塞.blockerId = feed.userId AND阻塞.blockedId ='3'或阻塞.blockerId ='3'AND阻塞.blockedId = feed.userId WHERE Blocking.blockerId为NULL和Blocking.blockedId为NULL
有没有一种方法可以在不更改数据的情况下改进此查询,或者它会达到预期的效果?
查询我正在尝试优化:
SELECT users.displayName, feed.id, feed.userId, feed.message
FROM feed
INNER JOIN users ON feed.userId = users.id
LEFT JOIN blocking ON blocking.blockerId = feed.userId AND blocking.blockedId = '3' OR blocking.blockerId = '3' AND blocking.blockedId = feed.userId
WHERE blocking.blockerId IS NULL AND blocking.blockedId IS NULL
ORDER BY feed.id DESC
LIMIT 20;
屏蔽表和密钥:
CREATE TABLE IF NOT EXISTS `blocking` (
`blockerId` int(11) NOT NULL,
`blockedId` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`blockedId`,`blockerId`) USING BTREE,
KEY `userId` (`blockerId`,`blockedId`) USING BTREE,
CONSTRAINT `blockedId` FOREIGN KEY (`blockedId`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `blockerId` FOREIGN KEY (`blockerId`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
)
进纸表:
CREATE TABLE IF NOT EXISTS `feed` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userId` int(11) NOT NULL,
`message` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `userId` (`userId`),
KEY `timestamp` (`timestamp`),
CONSTRAINT `userIdCas` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
)
用户表:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL,
`displayName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`createdAt` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
)
我正在调整的更新查询似乎运行得更快:
FROM feed
FORCE INDEX (PRIMARY)
INNER JOIN users ON feed.userId = users.id
LEFT JOIN blocking ON blocking.blockerId = feed.userId AND blocking.blockedId = '3' OR blocking.blockerId = '3' AND blocking.blockedId = feed.userId
WHERE blocking.blockerId IS NULL AND blocking.blockedId IS NULL
ORDER BY feed.id DESC
LIMIT 20;
任何人都可以解释为什么它运行得更好以及为什么MySQL可能不使用索引开头吗?
(来自注释)我将查询更改为
SELECT users.displayName, feed.id, feed.userId, feed.message
FROM feed FORCE INDEX (PRIMARY)
INNER JOIN users ON feed.userId = users.id
LEFT JOIN blocking ON blocking.blockerId = feed.userId
AND blocking.blockedId = '3'
OR blocking.blockerId = '3'
AND blocking.blockedId = feed.userId
WHERE blocking.blockerId IS NULL
AND blocking.blockedId IS NULL
ORDER BY feed.id DESC
LIMIT 20;
运行起来似乎更好,谁能让我对原因有更深入的了解?
答案 0 :(得分:1)
您应该在OR条件附近使用(),否则您将获得令人讨厌的结果
SELECT users.displayName
, feed.id
, feed.userId
, feed.message
FROM feed
INNER JOIN users ON feed.userId = users.id
LEFT JOIN blocking ON blocking.blockerId = feed.userId
AND ( blocking.blockedId = '3' OR blocking.blockerId = '3' )
AND blocking.blockedId = feed.userId
WHERE blocking.blockerId IS NULL AND blocking.blockedId IS NULL
ORDER BY feed.id DESC
LIMIT 20;
为获得更好的性能,您可以尝试在表上添加复合索引
table blocking columns ( blockerId, blockedId )
以及表上的复合索引
table feed columns (userId, message, id )