0

I need to find the ancestors in a table having an ID value and a Google research point me to recursive Common Table Expression (CTE) I wonder if EXPLAIN can be used to get some insights on how MySQL handles this and if there is room for optimization.

Also is this the best strategy to get ancestors in a table? I could involve code in here but don't want to because is gonna lead me to loops and probably multiple SELECT statements sent to the DB.

The SQL I wrote following the previous article is as follow:

WITH RECURSIVE page_revisions_path (id, page_id, parent_id) AS
(
 SELECT id, page_id, parent_id
 FROM page_revisions
 WHERE parent_id = 'some_id'
 UNION ALL
 SELECT c.id, c.page_id, c.parent_id 
 FROM page_revisions_path AS cp JOIN page_revisions AS c ON cp.id = c.parent_id
)

SELECT * FROM page_revisions_path;

Here is also the SHOW CREATE TABLE query result:

CREATE_TABLE `page_revisions` (
 `id` varchar(26) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
 `page_id` varchar(26) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `parent_id` varchar(26) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `routable` tinyint(1) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `IDX1` (`page_id`),
 KEY `IDX2` (`parent_id`),
 CONSTRAINT `FK1` FOREING KEY (`parent_id`) REFERENCES `page_revisions` (`id`),
 CONSTRAINT `FK2` FOREING KEY (`page_id`) REFERENCES `pages` (`id`)
) ENGINE=InnoDB
2
  • 1
    Too broad a question. Provide a couple of examples for us to discuss. (Include EXPLAIN, the SELECT, and SHOW CREATE TABLE.)
    – Rick James
    Feb 8, 2022 at 1:20
  • @RickJames I have added the requested info. The only thing I could not add was the EXPLAIN part because I am not sure how to use it on this WITH query indeed that is part of the question
    – ReynierPM
    Feb 8, 2022 at 16:23

1 Answer 1

0

(not an Answer; won't fit in a Comment)

Works for me:

mysql> EXPLAIN
    -> WITH RECURSIVE page_revisions_path (id, page_id, parent_id) AS
    -> (
    ->  SELECT id, page_id, parent_id
    ->  FROM page_revisions
    ->  WHERE parent_id = 'some_id'
    ->  UNION ALL
    ->  SELECT c.id, c.page_id, c.parent_id 
    ->  FROM page_revisions_path AS cp JOIN page_revisions AS c ON cp.id = c.parent_id
    -> )
    -> 
    -> SELECT * FROM page_revisions_path;
+----+-------------+----------------+------------+------+---------------+------+---------+-------+------+----------+--------------------------------------------+
| id | select_type | table          | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra                                      |
+----+-------------+----------------+------------+------+---------------+------+---------+-------+------+----------+--------------------------------------------+
|  1 | PRIMARY     | <derived2>     | NULL       | ALL  | NULL          | NULL | NULL    | NULL  |    4 |   100.00 | NULL                                       |
|  2 | DERIVED     | page_revisions | NULL       | ref  | IDX2          | IDX2 | 107     | const |    1 |   100.00 | NULL                                       |
|  3 | UNION       | cp             | NULL       | ALL  | NULL          | NULL | NULL    | NULL  |    2 |   100.00 | Recursive                                  |
|  3 | UNION       | c              | NULL       | ALL  | IDX2          | NULL | NULL    | NULL  |    1 |   100.00 | Using where; Using join buffer (hash join) |
+----+-------------+----------------+------------+------+---------------+------+---------+-------+------+----------+--------------------------------------------+
4 rows in set, 1 warning (0.00 sec)

It does require MySQL 8.0 or MariaDB 10.2.

VARCHAR(26) -- Eh? Too short for full names or uuids, etc.

Are there a million rows in the table? How often do you need to run the query?

3
  • ok, I can update that varchar to have more since it will hold ULID values :) and currently, there is not so much data but we're thinking of the near future where millions of rows are something to consider. I was using PhpStorm Database Console and the EXPLAIN was not supported, weird
    – ReynierPM
    Feb 8, 2022 at 17:47
  • Uuids are quite inefficient if the dataset is bigger than RAM. Please provide RAM size and value of innodb_buffer_pool_size and the projected size of the database..
    – Rick James
    Feb 8, 2022 at 19:58
  • Not sure I will be able to provide such info since this will be living in AWS and I have no access to production env. Locally this is running the default MySQL 8.0.23 Docker image with some shared resources since the host is macOS
    – ReynierPM
    Feb 9, 2022 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.