このようなクエリがあるとします...
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)
特定のタスクに複数の人を割り当てることができます。このクエリの目的は、タスクごとに 1 つの行を表示することですが、タスクに割り当てられた人を 1 つの列に表示します。
さて... tasks
、users
、およびに適切なインデックスが設定されているとしtasks_assigned_users
ます。tasks
派生テーブルに結合する場合、MySQL オプティマイザーは引き続き TaskID インデックスを使用しません。なんと!?!?
それで、私の質問は...どうすればこのクエリで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 句 (つまり、派生テーブル) のサブクエリをより効率的に処理します:...クエリの実行中に、オプティマイザーは派生テーブルにインデックスを追加する場合があります。そこからの行の取得を高速化します。」有望そうです...