如何告诉MySQL Optimizer在派生表上使用索引?

BMi*_*ner 6 mysql sql optimization join derived-table

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

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)
Run Code Online (Sandbox Code Playgroud)

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

现在...假设你有正确的指标设置上tasks,userstasks_assigned_users.在连接tasks到派生表时,MySQL Optimizer仍然不会使用TaskID索引.WTF?!?!?

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

使用的索引:

  • 任务
    • PRIMARY - TaskID
  • 用户
    • 主要 - 用户ID
  • tasks_assigned_users
    • PRIMARY - (TaskID,UserID)
    • 附加索引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子句(即派生表):......在查询执行,优化程序可以添加一个索引来派生表加快从中检索行." 似乎有希望......

BMi*_*ner 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衍生_t2 ON t1.f1=衍生_t2.f1;

文档说:“如果这样做允许使用引用访问来实现最低成本的执行计划,优化器会在衍生_t2 的列 f1 上构建索引。”

好的,这很好,但是优化器会重用 t2 中的索引吗?换句话说,如果 t2.f1 存在索引怎么办?该索引是否会被重新使用,或者优化器是否会为派生表重新创建该索引?谁知道?

编辑: MySQL 5.6 之前的最佳解决方案是创建临时表,在该表上创建索引,然后在临时表上运行 SELECT 查询。