Mysql 如何使用GROUP BY和ORDER BY优化查询
我有一个POSTS表,结构如下:Mysql 如何使用GROUP BY和ORDER BY优化查询,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,我有一个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, `
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 ;
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 ;
还有一个用户表,结构如下:
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 ;
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条记录以内
现在,我如何加快查询速度?要索引哪些列或其他想法?谢谢。首先要做的是在posts.user\u id或posts.user\u id+posts.type上添加索引。还有一个关于posts的索引 更新 我刚刚注意到,您的查询从两个表中获取所有字段,posts表有6个长文本列。所以我认为您的性能很差,因为mysql必须创建一个相当大的临时表或临时文件来获取所有行,以满足GROUPBY+ORDERBY子句的要求。 我认为下面的查询应该会有所帮助
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)
就索引而言,我建议在posts.type WHERE,posts.created_上创建索引。这将有助于加快排序速度。您可以尝试以下方法: 选择p,u。 从中选择*从p.所在的帖子中键入“帖子”、“页面”、“文件”p 在p.user\u id=u.id上左加入用户u 按p.user\U id分组按p.created\U在DESC创建的订单 限制30
MySQL首先处理内部查询,然后用其结果处理记录较少的外部查询。尝试@Gabriel的答案,但在内部查询中有限制 选择p,u。 从SELECT*FROM post,其中键入“post”、“page”、“file”顺序,由DESC LIMIT 30p创建 在p.user\u id=u.id上左加入用户u
由p.U.在创建的订单 这也是我的要求,但OP更新了CREATE表,以显示用户id已被索引:/Yes我为查询中提到的每一列创建了索引,但没有任何更改:它工作起来很有魅力。现在查询只持续了3秒钟,我知道它仍然很遥远,然后bestUsers表有9000多个用户,posts表有50000多个帖子。查询仍然需要7秒钟。没有收获。