closure_tree
closure_tree copied to clipboard
join default_tree_scope only when a limit_depth is given
Although the query issued by the closure_tree_class.has_tree call has an optional argument limit_depth to reduce the load, the cost remains excessively high when dealing with the hierarchy table containing huge amount of records. Below is the execution plan of the query.
MySQL [app_db]> EXPLAIN
SELECT
`tags`.*
FROM
`tags`
INNER JOIN `tag_hierarchies`
ON `tags`.`id` = `tag_hierarchies`.`descendant_id`
INNER JOIN (
SELECT
descendant_id,
MAX(generations) AS depth
FROM
`tag_hierarchies`
GROUP BY
descendant_id
) AS generation_depth
ON `tags`.id = generation_depth.descendant_id
WHERE
`tag_hierarchies`.`ancestor_id` = 2
AND (
`tags`.`id` != '2'
)
ORDER BY
`tag_hierarchies`.generations ASC,
sort_order,
generation_depth.depth;
+----+-------------+-----------------+------------+--------+-------------------------------+------------------+---------+--------------------------------------+---------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------+------------+--------+-------------------------------+------------------+---------+--------------------------------------+---------+----------+----------------------------------------------+
| 1 | PRIMARY | tag_hierarchies | NULL | ref | tag_anc_desc_idx,tag_desc_idx | tag_anc_desc_idx | 4 | const | 14 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | PRIMARY | tags | NULL | eq_ref | PRIMARY | PRIMARY | 8 | app_db.tag_hierarchies.descendant_id | 1 | 100.00 | Using where |
| 1 | PRIMARY | <derived2> | NULL | ref | <auto_key0> | <auto_key0> | 4 | app_db.tags.id | 10 | 100.00 | Using where |
| 2 | DERIVED | tag_hierarchies | NULL | index | tag_anc_desc_idx,tag_desc_idx | tag_desc_idx | 4 | NULL | 970,482 | 100.00 | Using index |
+----+-------------+-----------------+------------+--------+-------------------------------+------------------+---------+--------------------------------------+---------+----------+----------------------------------------------+
4 rows in set (0.003 sec)
The default_tree_scope is only meaningful when limit_depth is specified (though it's questionable whether it actually reduces the load). I have confirmed that even without the join, the load is not significantly higher.