假设您有这样的查询...
SELECT T.TaskID, T.TaskName, TAU.AssignedUsers
FROM `tasks` T
LEFT OUTER JOIN (
SELECT TaskID, GROUP_CONCAT(U.FirstName, ' ',
U.LastName SEPARATOR ', ') AS AssignedUsers
FROM `tasks_assigned_users` TAU
INNER JOIN `users` U ON (TAU.UserID=U.UserID)
GROUP BY TaskID
) TAU ON (T.TaskID=TAU.TaskID)
可以将多个人分配给给定任务。此查询的目的是为每个任务显示一行,但将人员分配给单个列中的任务
现在......假设您在tasks
,users
和tasks_assigned_users
上设置了正确的索引。将tasks
加入派生表时,MySQL Optimizer仍然不会使用TaskID索引。 WTF?!?!?
所以,我的问题是......如何使这个查询使用tasks_assigned_users.TaskID上的索引?临时表是蹩脚的,所以如果这是唯一的解决方案...... MySQL优化器是愚蠢的。
使用的索引:
编辑:此外,this page表示派生表在连接发生之前执行/实现。为什么不重复使用密钥来执行连接?
编辑2: MySQL优化器不允许您将index hints放在派生表上(可能是因为派生表上没有索引)
编辑3:以下是一篇非常好的博客文章:http://venublog.com/2010/03/06/how-to-improve-subqueries-derived-tables-performance/请注意,案例#2是我正在寻找的解决方案,但似乎MySQL不支持这个在这个时候。 :(
编辑4:刚刚找到this:“从MySQL 5.6.3开始,优化器更有效地处理FROM子句中的子查询(即派生表):...在查询执行期间,优化器可以向派生表添加索引,以加速从中检索行。“似乎很有希望......
答案 0 :(得分:4)
MySQL Server 5.6中有一个解决方案 - 预览版本(撰写本文时)。
http://dev.mysql.com/doc/refman/5.6/en/from-clause-subquery-optimization.html
虽然,我不确定MySQL Optimizer是否会在“将索引添加到派生表”时重用已存在的索引
考虑以下问题:
SELECT * FROM t1 JOIN(SELECT * FROM t2)AS derived_t2 ON t1.f1 = derived_t2.f1;
文档说:“如果这样做允许使用ref访问来获得最低成本的执行计划,那么优化器会从derived_t2构建一个列f1的索引。”
好的,那很好,但优化器是否重用了t2的索引?换句话说,如果t2.f1存在索引怎么办?是否重新使用此索引,或者优化程序是否为派生表重新创建此索引?谁知道?
编辑: MySQL 5.6之前的最佳解决方案是创建临时表,在该表上创建索引,然后在临时表上运行SELECT查询。
答案 1 :(得分:2)
我看到的问题是,通过执行子查询,没有底层索引表。 如果你有表演,我会在最后进行分组,如下所示:
SELECT T.TaskID, T.TaskName, GROUP_CONCAT(U.FirstName, ' ', U.LastName SEPARATOR ', ') AS AssignedUsers
FROM `tasks` T
LEFT OUTER JOIN `tasks_assigned_users` TAU ON (T.TaskID=TAU.TaskID)
INNER JOIN `users` U ON (TAU.UserID=U.UserID)
GROUP BY T.TaskID, T.TaskName
答案 2 :(得分:1)
我害怕,这是not possible。您必须创建临时表或视图才能使用索引。