6

假设您有这样的查询...

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)

可以将多个人分配给给定任务。此查询的目的是为每个任务显示一行,但分配给任务的人员在一列中

现在...假设您在 、 和 上设置了正确tasksusers索引tasks_assigned_userstasksMySQL 优化器在加入派生表时仍然不会使用 TaskID 索引。WTF?!?!?

所以,我的问题是......如何让这个查询使用 tasks_assigned_users.TaskID 上的索引?临时表很蹩脚,所以如果这是唯一的解决方案...... MySQL 优化器是愚蠢的。

使用的索引:

  • 任务
    • 主要 - 任务 ID
  • 用户
    • 主要 - 用户 ID
  • tasks_assigned_users
    • 主要 - (任务 ID,用户 ID)
    • 附加索引 UNIQUE - (UserID,TaskID)

编辑:另外,这个页面说派生表在连接发生之前执行/实现。为什么不重新使用密钥来执行连接呢?

编辑 2: MySQL 优化器不会让您在派生表上放置索引提示(可能是因为派生表上没有索引)

编辑 3:这是一篇非常好的博客文章:http: //venublog.com/2010/03/06/how-to-improve-subqueries-derived-tables-performance/ 请注意,案例 #2 是我的解决方案正在寻找,但目前 MySQL 似乎不支持此功能。:(

编辑 4:刚刚发现:“从 MySQL 5.6.3 开始,优化更有效地处理 FROM 子句中的子查询(即派生表):...在查询执行期间,优化器可能会向派生表添加索引以加快从中检索行的速度。” 看起来很有希望...

4

3 回答 3

4

MySQL Server 5.6 中有一个解决方案——预览版(在撰写本文时)。

http://dev.mysql.com/doc/refman/5.6/en/from-clause-subquery-optimization.html

虽然,我不确定 MySQL 优化器在“将索引添加到派生表”时是否会重用已经存在的索引

考虑以下查询:

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 查询。

于 2012-01-18T20:22:33.703 回答
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
于 2012-01-18T19:44:16.517 回答
1

恐怕,这是不可能的。您必须创建一个临时表或视图才能使用索引。

于 2012-01-18T19:32:11.577 回答