在 JOIN 值上完成时 MySQL 慢 ORDER BY?
Posted
技术标签:
【中文标题】在 JOIN 值上完成时 MySQL 慢 ORDER BY?【英文标题】:MySQL Slow ORDER BY when done on JOIN value? 【发布时间】:2016-06-06 00:49:12 【问题描述】:我有这个问题:
SELECT
c.*,
cv.views
FROM
content AS c
JOIN
content_views AS cv ON cv.content = c.record_num
WHERE
c.enabled = 1
ORDER BY
cv.views
很简单,但是真的很慢...有没有办法让它更快?
这是我的解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE c ref enabled_2,enabled enabled 4 const 23947 Using temporary; Using filesort
1 SIMPLE cv eq_ref PRIMARY PRIMARY 4 c.record_num 1
编辑 2016-02-24
请注意,我通常使用 LIMIT,因此 EXPLAIN 中返回的记录数并不完全准确,但是为了简单起见,并且由于 LIMIT 或没有它,性能不会改变,我有删除它。
根据 cmets 的要求,这是我的 SHOW CREATE TABLE 的结果。如您所见,我的一个表是 MyISAM 而另一个是 InnoDB。
CREATE TABLE `content` (
`title` varchar(255) NOT NULL DEFAULT '',
`filename` varchar(255) NOT NULL DEFAULT '',
`filename_2` varchar(255) NOT NULL,
`filename_3` varchar(255) NOT NULL,
`orig_filename` varchar(255) NOT NULL,
`trailer_filename` varchar(255) NOT NULL,
`thumbnail` varchar(255) NOT NULL DEFAULT '',
`embed` text NOT NULL,
`description` text NOT NULL,
`paysite` int(11) NOT NULL DEFAULT '0',
`keywords` varchar(255) NOT NULL,
`model` varchar(255) NOT NULL DEFAULT '',
`scheduled_date` date NOT NULL DEFAULT '0000-00-00',
`date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`encoded_date` datetime NOT NULL,
`rating` int(5) NOT NULL DEFAULT '0',
`length` int(11) NOT NULL DEFAULT '0',
`submitter` int(11) NOT NULL DEFAULT '0',
`ip` varchar(15) NOT NULL,
`approved` int(11) NOT NULL DEFAULT '0',
`hotlinked` varchar(1024) NOT NULL,
`plug_url` varchar(255) NOT NULL,
`enabled` int(11) NOT NULL DEFAULT '0',
`main_thumb` int(11) NOT NULL DEFAULT '3',
`xml` varchar(32) NOT NULL,
`photos` int(11) NOT NULL DEFAULT '0',
`mobile` varchar(255) NOT NULL,
`modeltmp` varchar(255) NOT NULL,
`movie_width` int(11) NOT NULL,
`movie_height` int(11) NOT NULL,
`token` varchar(255) DEFAULT NULL,
`source_thumb_url` varchar(255) NOT NULL,
`related` varchar(1024) NOT NULL,
`force_related` varchar(255) NOT NULL,
`record_num` int(11) NOT NULL AUTO_INCREMENT,
`webvtt_src` text NOT NULL,
`category_thumb` int(11) NOT NULL,
`related_date` date NOT NULL,
`publish_ready` tinyint(1) NOT NULL,
PRIMARY KEY (`record_num`),
KEY `encoded_date` (`encoded_date`,`photos`,`enabled`),
KEY `filename` (`filename`),
KEY `scheduled_date` (`scheduled_date`),
KEY `enabled_2` (`enabled`,`length`,`photos`),
KEY `enabled` (`enabled`,`encoded_date`,`photos`),
KEY `rating` (`rating`,`enabled`,`photos`),
KEY `token` (`token`),
KEY `submitter` (`submitter`),
FULLTEXT KEY `keywords` (`keywords`,`title`),
FULLTEXT KEY `title` (`title`),
FULLTEXT KEY `description` (`description`),
FULLTEXT KEY `keywords_2` (`keywords`)
) ENGINE=MyISAM AUTO_INCREMENT=124207 DEFAULT CHARSET=latin1
CREATE TABLE `content_views` (
`views` int(11) NOT NULL,
`content` int(11) NOT NULL,
PRIMARY KEY (`content`),
KEY `views` (`views`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
【问题讨论】:
解释中没有什么可怕的,关于表格的信息? 请提供SHOW CREATE TABLE
。
您打算如何处理结果集中的 23,947 行?确定不把它们扔到网页上?
为了简单起见,我删除了 LIMIT,但无论有没有它,性能都是一样的。我已经在我的主帖中发布了 CREATE TABLE
【参考方案1】:
对于这个查询:
SELECT c.*, cv.views
FROM content c JOIN
content_views cv
ON cv.content = c.record_num
WHERE c.enabled = 1
ORDER BY cv.views;
最好的索引可能是content(enabled, record_num)
和content_views(content, views)
。我猜即使有了这些索引,性能也会和你现在的差不多。
【讨论】:
(content, views)
如果是content=const ORDER BY views
会更好。他所拥有的没有views
在一个 的地方订购。然而,它是有用的,因为它是“覆盖”的。也就是说,它不会阻止“文件排序”,但也不需要接触数据。另一方面,这可能是只有 2 列的 InnoDB。如果是这样,那么(content, views)
将与表冗余!
而(enabled, record_num)
也无济于事,因为它会想在c.*
存在时获取所有的信息。令人惊讶的是,他在“旗帜”上的索引甚至被使用了。
@RickJames。 . .复合索引是引擎在从数据页获取其余列之前使用该索引进行连接。
我认为 Handler 做了这一步。以上是关于在 JOIN 值上完成时 MySQL 慢 ORDER BY?的主要内容,如果未能解决你的问题,请参考以下文章
MySQL Left Join 运行速度非常慢,拆分为 2 个查询要快得多