【发布时间】:2013-04-17 21:08:05
【问题描述】:
我正在使用 InnoDB。
查询、解释和索引
选择 故事。*, 计数(cmets.id)作为 cmets, GROUP_CONCAT( DISTINCT 分类 2.name SEPARATOR ';' ) 作为分类名称, GROUP_CONCAT( 不同的图像.id ORDER BY images.position, images.id 分隔符';' ) 作为 images_id, GROUP_CONCAT( 不同的图像.caption ORDER BY images.position, images.id 分隔符';' ) 作为 images_caption, GROUP_CONCAT( 不同的图像.thumbnail ORDER BY images.position, images.id 分隔符';' ) 作为 images_thumbnail, GROUP_CONCAT( 不同的图像.medium ORDER BY images.position, images.id 分隔符';' ) 作为图像_媒体, GROUP_CONCAT( 不同的图像.大 ORDER BY images.position, images.id 分隔符';' ) AS images_large, GROUP_CONCAT( DISTINCT users.id ORDER BY users.id SEPARATOR ';' ) 作为作者 ID, GROUP_CONCAT( DISTINCT users.display_name ORDER BY users.id SEPARATOR ';' ) 作为作者显示名称, GROUP_CONCAT( 不同的 users.url ORDER BY users.id SEPARATOR ';' ) 作为作者 URL 从 故事 LEFT JOIN 分类 ON stories.id = 分类.story_id LEFT JOIN 分类 AS 分类2 ON stories.id = classifications2.story_id 左连接 cmets ON stories.id = cmets.story_id 左连接 image_story ON stories.id = image_story.story_id 左连接图像 ON images.id = image_story.`image_id` 左连接 author_story ON stories.id = author_story.story_id 左加入用户 ON users.id = author_story.author_id WHERE 分类。`name` LIKE 'Home:Top%' AND stories.status = 1 GROUP BY stories.id 按分类排序。`名称`,分类。`位置` +----+-------------+------------------+--------+-- -------------+---------+---------+--------------- ---------+--------+------------------------------- ---------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+------------------+--------+-- -------------+---------+---------+--------------- ---------+--------+------------------------------- ---------------+ | 1 |简单 |故事 |参考 |状态 |状态 | 1 |常量 | 434792 |使用哪里;使用临时的;使用文件排序 | | 1 |简单 |分类 |参考 |故事ID |故事ID | 4 |故事.id | 1 |使用位置 | | 1 |简单 |分类2 |参考 |故事ID |故事ID | 4 |故事.id | 1 |使用位置 | | 1 |简单 |厘米 |参考 |故事ID |故事ID | 8 |故事.id | 6 |使用哪里;使用索引 | | 1 |简单 |图片故事 |参考 |故事ID |故事ID | 4 |故事.id | 1 |空 | | 1 |简单 |图片 | eq_ref |初级 |初级 | 4 | image_story.image_id | 1 |空 | | 1 |简单 |作者故事 |参考 |故事ID |故事ID | 4 |故事.id | 1 |使用位置 | | 1 |简单 |用户 | eq_ref |初级 |初级 | 4 | author_story.author_id | 1 |使用位置 | +----+-------------+------------------+--------+-- -------------+---------+---------+--------------- ---------+--------+------------------------------- ---------------+ +-----------------+------------+-------------+---- ----------+-------------+------------+------------- +---------+--------+------+------------+ |表 |非唯一 |键名 | Seq_in_index |列名 |整理 |基数|子部分 |包装 |空 |索引类型 | +-----------------+------------+-------------+---- ----------+-------------+------------+------------- +---------+--------+------+------------+ |故事 | 0 |初级 | 1 |编号 |一个 | 869584 |空 |空 | | BTREE | |故事 | 1 | created_at | 1 | created_at |一个 | 434792 |空 |空 | | BTREE | |故事 | 1 |来源 | 1 |来源 |一个 | 2 |空 |空 |是 | BTREE | |故事 | 1 | source_id | 1 | source_id |一个 | 869584 |空 |空 |是 | BTREE | |故事 | 1 |类型 | 1 |类型 |一个 | 2 |空 |空 | | BTREE | |故事 | 1 |状态 | 1 |状态 |一个 | 2 |空 |空 | | BTREE | |故事 | 1 |类型状态 | 1 |类型 |一个 | 2 |空 |空 | | BTREE | |故事 | 1 |类型状态 | 2 |状态 |一个 | 2 |空 |空 | | BTREE | |分类 | 0 |初级 | 1 |编号 |一个 | 207 |空 |空 | | BTREE | |分类 | 1 |故事ID | 1 |故事ID |一个 | 207 |空 |空 | | BTREE | |分类 | 1 |姓名 | 1 |姓名 |一个 | 103 |空 |空 | | BTREE | |分类 | 1 |姓名 | 2 |职位 |一个 | 207 |空 |空 |是 | BTREE | |厘米 | 0 |初级 | 1 |编号 |一个 | 239336 |空 |空 | | BTREE | |厘米 | 1 |状态 | 1 |状态 |一个 | 2 |空 |空 | | BTREE | |厘米 | 1 |日期 | 1 |日期 |一个 | 239336 |空 |空 | | BTREE | |厘米 | 1 |故事ID | 1 |故事ID |一个 | 39889 |空 |空 | | BTREE | +-----------------+------------+-------------+---- ----------+-------------+------------+------------- +---------+--------+------+------------+查询时间
平均需要0.035 seconds 才能运行。
如果我只删除GROUP BY,平均时间会下降到0.007。
如果我只删除 stories.status=1 过滤器,平均时间会下降到 0.025。这个好像很容易优化。
如果我只删除LIKE 过滤器和ORDER BY 子句,平均时间会下降到0.006。
更新 1:2013-04-13
通过答案,我的理解得到了多方面的提高。
我向author_story 和images_story 添加了索引,这似乎改进了对0.025 秒的查询,但出于某种奇怪的原因,EXPLAIN 计划看起来好多了。此时删除ORDER BY 将查询降低到0.015 秒并同时删除ORDER BY 和GROUP BY 将查询性能提高到0.006。我是现在要关注的两件事吗?如果需要,我可能会将ORDER BY 移到应用逻辑中。
这里是修改后的EXPLAIN 和INDEXES
更新 2:2013-04-14
我注意到另一件事。如果我不选择 stories.content (LONGTEXT) 和 stories.content_html (LONGTEXT),则查询将从 0.015 秒下降到 0.006 秒。现在我正在考虑是否可以不使用 content 和 content_html 或用其他东西替换它们。
我在上面的 2013-04-13 更新中更新了查询、索引和解释,而不是在这个更新中重新发布,因为它们是次要的和增量的。该查询仍在使用filesort。我无法摆脱GROUP BY,但已经摆脱了ORDER BY。
更新 3:2013-04-16
根据要求,我从 image_story 和 author_story 中删除了 stories_id INDEXES,因为它们是多余的。结果是解释的输出仅更改为显示possible_keys 已更改。不幸的是,它仍然没有显示Using Index 优化。
还将LONGTEXT 更改为TEXT,现在获取LEFT(stories.content, 500) 而不是stories.content,这在查询执行时间上产生了非常显着的差异。
【问题讨论】:
-
你能发布解释计划吗?
-
同时显示您的索引。
-
您预计什么时间可以满足查询要求?
-
@newtover,就个人而言,如果它可以达到 0.01 秒以下,那真的会让我放心,因为这个查询每秒可以运行几十次,但这可能是我的一厢情愿。我会尽我所能。
-
是否可以获得带有测试数据的转储?对结果使用分页怎么样?
标签: mysql optimization group-by left-join