【发布时间】:2019-12-20 15:13:38
【问题描述】:
我正在开发一个小型社交网络,但我正在努力优化设计中的屏蔽部分。我有 3 个表阻塞、提要和用户。它工作正常,但是当我添加阻止查询时,查询从 16 毫秒或更少到超过 50 毫秒或更高,这对于简单的事情来说似乎很多。事实上,如果没有阻塞我的 hedisql sql,查询时间有时会报告为 0ms,因为我猜它低于一定的时间。
屏蔽的想法是,如果用户屏蔽了其他人,他们将无法看到他们的提要帖子,被屏蔽的人也无法看到屏蔽者。
我正在努力优化的部分是: LEFT JOIN 阻塞 ON blocking.blockerId = feed.userId AND blocking.blockedId = '3' OR blocking.blockerId = '3' AND blocking.blockedId = feed.userId 其中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;
而且它似乎运行得更好,谁能让我更深入地理解为什么?
【问题讨论】:
-
我也更改了查询:SELECT users.displayName, feed.id, feed.userId, feed.message FROM feed FORCE INDEX (PRIMARY) INNER JOIN users ON feed.userId = users.id LEFT JOIN阻塞 ON blocking.blockerId = feed.userId AND blocking.blockedId = '3' OR blocking.blockerId = '3' AND blocking.blockedId = feed.userId WHERE blocking.blockerId 为 NULL AND blocking.blockedId 为 NULL ORDER BY feed.id DESC 限制 20; ```而且它似乎运行得更好,谁能给我更深入的理解为什么?
-
请考虑更改名称 blockerId 和/或blockedId - 它们的相似性使得阅读查询变得非常困难。
-
不使用
FORCE INDEX时EXPLAIN会说什么?
标签: mysql performance query-optimization