SELECT fcat.id,fcat.title,fcat.description,
count(DISTINCT ftopic.id) as number_topics,
count(DISTINCT fpost.id) as number_posts FROM fcat
LEFT JOIN ftopic ON fcat.id=ftopic.cat_id
LEFT JOIN fpost ON ftopic.id=fpost.topic_id
GROUP BY fcat.id
ORDER BY fcat.ord
LIMIT 100;
ftopic_cat_id索引,fpost.topic_id,fcat.ord
说明:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE fcat ALL PRIMARY NULL NULL NULL 11 Using temporary; Using filesort
1 SIMPLE ftopic ref PRIMARY,cat_id_2 cat_id_2 4 bloki.fcat.id 72
1 SIMPLE fpost ref topic_id_2 topic_id_2 4 bloki.ftopic.id 245
fcat - 11行, ftopic - 1106行, fpost - 363000行
查询需要4,2秒
TABLES:
CREATE TABLE IF NOT EXISTS `fcat` (
`id` int(11) NOT NULL auto_increment,
`title` varchar(250) collate utf8_unicode_ci NOT NULL,
`description` varchar(250) collate utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`visible` tinyint(4) NOT NULL default '1',
`ord` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `ord` (`ord`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=12 ;
CREATE TABLE IF NOT EXISTS `ftopic` (
`id` int(11) NOT NULL auto_increment,
`cat_id` int(11) NOT NULL,
`title` varchar(100) collate utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`updated` timestamp NOT NULL default CURRENT_TIMESTAMP,
`lastname` varchar(200) collate utf8_unicode_ci NOT NULL,
`visible` tinyint(4) NOT NULL default '1',
`closed` tinyint(4) NOT NULL default '0',
`views` int(11) NOT NULL default '1',
PRIMARY KEY (`id`),
KEY `cat_id_2` (`cat_id`,`updated`,`visible`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1116 ;
CREATE TABLE IF NOT EXISTS `fpost` (
`id` int(11) NOT NULL auto_increment,
`topic_id` int(11) NOT NULL,
`pet_id` int(11) NOT NULL,
`content` text collate utf8_unicode_ci NOT NULL,
`imageName` varchar(300) collate utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`reply_id` int(11) NOT NULL,
`visible` tinyint(4) NOT NULL default '1',
`md5` varchar(100) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `md5` (`md5`),
KEY `topic_id_2` (`topic_id`,`created`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=390971 ;
谢谢, 村庄
答案 0 :(得分:0)
您需要同时使用fcat.id, fcat.ord
答案 1 :(得分:0)
大胆重写
此代码在功能上并不相同,但是......
因为你想了解distinct
ftopic.id和fpost.id我会大胆并建议两个INNER JOIN而不是LEFT JOIN。
然后因为两个id是自动递增的,它们将不再重复,所以你可以删除distinct
。
SELECT
fcat.id
, fcat.title
, fcat.description
, count(ftopic.id) as number_topics
, count(fpost.id) as number_posts
FROM fcat
INNER JOIN ftopic ON fcat.id = ftopic.cat_id
INNER JOIN fpost ON ftopic.id = fpost.topic_id
GROUP BY fcat.id
ORDER BY fcat.ord
LIMIT 100;
这取决于您的数据,如果这是您正在寻找的,但我猜它会更快。
但是你的所有索引似乎都是有序的。
MySQL不会为小样本使用索引!
请注意,explain
列表中的MySQL只有 11行才能考虑fcat。这还不足以让MySQL真正开始担心索引,所以它没有
因为转向小行数的索引会降低速度。
MySQL试图加快速度,因此它选择不使用索引,这让很多人感到困惑,因为我们在索引上受过如此严格的训练。小样本量没有给出好的解释!
增加测试数据的大小,以便MySQL有更多的行需要考虑,你应该开始看到正在使用的索引。
关于force index
的常见误解
Force index
不强制MySQL使用索引
它暗示MySQL使用不同的索引,它可以自然地使用和,它通过在表扫描上设置非常高的成本来推动MySQL使用索引。登记/>
(在您的情况下,MySQL 不使用表扫描,因此force index
无效)
MySQL(与地球上大多数其他DBMS相同)都强烈要求使用索引,因此如果它没有(使用任何),那是因为根本不使用索引会更快。
MySQL如何知道使用哪个索引
查询优化器使用的参数之一是索引的存储基数
随着时间的推移,这些值会发生变化......但是研究这个表需要时间,所以除非你告诉它,否则MySQL不会这样做
另一个影响索引选择的参数是MySQL在执行查询时预计会遇到的预测磁盘搜索时间。
提高索引使用率的提示
ANALYZE TABLE
将指示MySQL重新评估索引并更新其密钥分发(基数)。 (考虑每天/每周在cron作业中运行) SHOW INDEX FROM table
将显示密钥分配。 OPTIMIZE TABLE
对表进行碎片整理并重新创建索引。 FORCE/USE/IGNORE INDEX
限制MySQL的查询优化器执行查询的选项。只考虑复杂的查询。