我有一个POSTS
表,结构是这样的:
CREATE TABLE IF NOT EXISTS `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_turkish_ci DEFAULT NULL,
`content` longtext COLLATE utf8_turkish_ci,
`excerpt` longtext COLLATE utf8_turkish_ci,
`link` longtext COLLATE utf8_turkish_ci,
`original_link` longtext COLLATE utf8_turkish_ci,
`mime_type` longtext COLLATE utf8_turkish_ci,
`language_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`site_id` int(11) DEFAULT NULL,
`type` varchar(255) COLLATE utf8_turkish_ci DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`modified_at` datetime DEFAULT NULL,
`is_deleted` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `type` (`type`),
KEY `created_at` (`created_at`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci AUTO_INCREMENT=52487 ;
一个USERS表,结构如下:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) COLLATE utf8_turkish_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci AUTO_INCREMENT=9422 ;
我正在使用此查询来获取按照下降时间排序的最新“页面,文件或帖子”帖子,并按用户分组以显示用户的所有最新帖子:
SELECT p.*, u.*
FROM posts p
LEFT JOIN users u ON p.user_id = u.id
WHERE p.type IN ('post', 'page', 'file')
GROUP BY p.user_id
ORDER BY p.created_at DESC
LIMIT 30
但它太慢了,甚至限制在30个记录中。
现在,我怎样才能加快这个查询?要索引哪些列或任何其他想法?感谢。
答案 0 :(得分:2)
要做的第一件事是在posts.user_id
(或者posts.user_id + posts.type
)上添加索引。以及posts.created_at
<强>更新强>
我只是注意你的查询从两个表中获取所有字段,而posts表有6个长文本列。所以我相信你的性能很差,因为mysql必须创建一个相当大的临时表或临时文件来获取所有行以满足你的group by
+ order by
子句。
我认为以下查询应该有所帮助。
SELECT u.*, p1.* FROM
users u
INNER JOIN
(
SELECT p.user_id, p.created_at, p.id FROM posts p
WHERE p.type IN ('post', 'page', 'file') GROUP by p.user_id
ORDER BY p.created_at DESC LIMIT 30
)xxx ON xxx.user_id = u.id
INNER JOIN posts p1 ON (p1.id = xxx.id)
答案 1 :(得分:0)
就索引而言,我建议在posts.type(WHERE),posts.created_at(ORDER)上创建一个。这应该有助于加快排序。
答案 2 :(得分:0)
你可以试试这个:
SELECT p。,u。
FROM(SELECT * FROM帖子WHERE p.type IN(&#39; post&#39;,&#39; page&#39;,&#39; file&#39;))p
LEFT JOIN用户u on p.user_id = u.id
GROUP BY p.user_id ORDER BY p.created_at DESC
限制30
MySQL首先处理内部查询,并使用其结果进程处理具有较少记录的outter查询。
答案 3 :(得分:0)
尝试@ Gabriel的答案,但在内部查询中使用LIMIT。
SELECT p。,u。 FROM(SELECT * FROM posts WHERE type IN('post','page','file')ORDER BY created_at DESC LIMIT 30)p LEFT JOIN用户u on p.user_id = u.id ORDER BY p.created_at;