[MDEV-19078] Support lateral derived tables Created: 2019-03-28  Updated: 2024-01-31

Status: Open
Project: MariaDB Server
Component/s: Optimizer
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Igor Babaev Assignee: Michael Widenius
Resolution: Unresolved Votes: 43
Labels: compat80

Attachments: JPEG File sshot-2021-10-12-18-49-15-1.jpg    
Issue Links:
Blocks
is blocked by MDEV-26831 New name resolution Open
PartOf
includes MDEV-6373 Add support for LATERAL keyword Open
is part of MDEV-28906 MySQL 8.0 desired compatibility Open
Relates
relates to MDEV-19337 CTEs not working with outer references Closed
relates to MDEV-30744 WITH AS clause doesn't work with an o... Closed
relates to MDEV-33018 Support LEFT JOIN LATERAL Open

 Description   

Currently MariaDB does not allow to use lateral derived tables in queries though it
uses builds them internally for when employing split optimization.
Consider the following query

SELECT t.b FROM t1, LATERAL (SELECT * FROM t2 WHERE t1.a=t2.a) AS t 

Here the reference t1.a in the WHERE condition of derived table t refers to the field a
of the table t1 used in the same FROM list as t.

SQL standard allows lateral derived tables and MySQL 8.0 supports them.



 Comments   
Comment by Nuno [ 2019-08-10 ]

MySQL 8.0 implemented this.

Really useful, as many times I need this feature and I don't have it.

SQL Server has OUTER APPLY and CROSS APPLY.

Would be great if MariaDB implemented LATERAL.

More comments and more votes in https://jira.mariadb.org/browse/MDEV-6373

Comment by Nuno [ 2019-12-12 ]

Any update regarding this implementation?

Every other database system has this, except MariaDB...

Thank you very much.

Comment by Noel Diaz [ 2020-10-07 ]

Is there an ETA on this ?

Comment by Sergei Golubchik [ 2020-11-04 ]

No. At the moment it's not planned for 10.6

Comment by Nuno [ 2020-12-19 ]

I keep wishing for this...
It was requested in 2014 (MDEV-6373), currently marked as Critical.
6 years later, still not planned :/

Comment by Adrian Wiik [ 2020-12-23 ]

I find myself lacking this functionality as well. I need it to optimize a currently very expensive query on the front page of our web app. I would absolutely love to come back to this StackOverflow question to announce that this feature is available as soon as it is. I see that implementation has been planned for 10.7, let's hope that promise is fulfilled.

Comment by Nuno [ 2021-03-02 ]

igor serg marko Hoping to see this planned and implemented in 10.7, please!
Thank you very much & have a great day.

Comment by Nuno [ 2021-10-02 ]

igor serg marko Hey guys! Is this still going on 10.7, or out of luck at this point?
Thank you very much!
Kind regards.

Comment by Sergei Golubchik [ 2021-10-12 ]

Likely out of luck. Depends on when 10.7 will be closed for new features.

Comment by Nuno [ 2021-10-12 ]

serg
Thank you for your reply, and I really appreciate everyone's efforts with MariaDB.
BIG THANKS to your deliveries.

However, please consider that this feature has been 2 of the most voted requests tagged for 10.7 (two different JIRA tickets) for long time, and something where MariaDB stays behind MySQL, PostgreSQL and SQL Server.
And is a huge limitation in many situations which LATERAL JOIN would make very easy.

Have a very great day.

Comment by Nuno [ 2021-10-25 ]

Bad news - postponed since 10.6

Comment by Nuno [ 2022-02-07 ]

MDEV-19078 has 33 votes while MDEV-6373 has only 19 votes.

MDEV-19078 (with more votes) was removed the "Fix version" so it will no longer appear in the results sorted by Votes, for a specific milestone/fix version.

And meanwhile, MDEV-6373 was bumped to fix version 10.9.

Seriously... MariaDB is the only DB I know that still doesn't support LATERAL / OUTER APPLY.

Comment by Nuno [ 2022-03-28 ]

igor serg marko Any updates on the plan for MDEV-19078 and MDEV-6373, please?
Thank you very much!

Comment by Sergei Golubchik [ 2022-03-30 ]

sorry, there's no immediate plan at the moment

Comment by antonis [ 2022-11-09 ]

Decided to migrate to MariaDB from mysql and this issue causes errors to most of my queries. Is there any plan on adding support for lateral derived tables this in the very near future or shall I abort migration?

Thank you

Comment by Sergei Golubchik [ 2022-11-18 ]

It's unlikely to happen in the "very near future". This is work in progress, indeed (or, to be more precise, we're implementing necessary prerequisites), but it'll take some time.

Comment by Nuno [ 2022-11-18 ]

Thank you, serg.

This is really the only feature I miss a lot in MariaDB, and keeps being a daily inconvenience, not having it.

However, I'm thankful that at least work is being done in the pre-requisites.

Thank you very much everyone.

Comment by Rick James [ 2022-11-18 ]

@Nuno - It seems like the initial example can be rewritten, in fewer keystrokes, as

SELECT t2.b FROM t1 JOIN t2 t1.a=t2.a

Do you have an example of LATERAL that cannot be rewritten as INNER JOIN?

If rewriting is always feasible, then might it be "easy" to have the Optimizer reformulate it – similar to what is done between LEFT JOIN, EXISTS, and IN(SELECT)?

Comment by Nuno [ 2022-11-18 ]

Any example where I need to do a subquery with an "ORDER BY" that needs to return 2 or more columns, used by other JOINs in the main query.

Example (just randomly from top of my mind):

SELECT
  users.user_id
, users.user_name
, some_extra_data.whatever
, most_popular_post.post_id
, most_popular_post.title
, most_popular_post.time
, most_popular_post.community_id
, most_popular_post.community_name
FROM users
JOIN some_extra_data USING(user_id)
LATERAL (
  SELECT 
    posts.post_id
  , posts.title
  , posts.time
  , communities.community_id
  , communities.community_name
  FROM posts
  JOIN communities USING(community_id)
  WHERE posts.from=user_id
  ORDER BY posts.total_replies DESC LIMIT 1
) AS most_popular_post
ORDER BY most_popular_post.time DESC

There are plenty of examples like these, and many times I'm forced to create multiple subqueries in the SELECT, for each field I need, or subqueries in subqueries in a JOIN, etc, just because LATERAL isn't available.

You might suggest the above could be converted by starting the query with posts/communities, instead of users, but please note that in this case, I want ALL users to appear, even if "most_popular_post" is NULL

Comment by Rick James [ 2022-11-19 ]

@Nuno - Thanks. I'll research how LATERAL can be used to solve the "groupwise-max" and "Top-N per group" problems. There are many inefficient algorithms out there and some return extra rows when the max value (eg, total_replies) occurs more than once.

Comment by Kuno Vaik [ 2022-11-24 ]

I have also optimized many queries using LATERAL JOIN in postgresql and I really miss it in mariadb.

Comment by Gavin Ray [ 2023-07-27 ]

Just to add some extra context, `LATERAL` is essentially a window function under the hood.

The transformation for the following `LATERAL` query. "Fetch the first 5 Artists, and for each Artist, fetch their first 3 Albums":

select art.*, alb.*
from (select * from artists limit 5) art
       cross join lateral (select *
                           from    albums
                           where  albums.artist_id = art.artist_id
                           limit 3) alb

Is:

SELECT art.*, alb.*
FROM (
  SELECT *, row_number() OVER (PARTITION BY artist_id ORDER BY album_id) as rn
  FROM albums
) alb
LEFT JOIN (
  SELECT *
  FROM artists
  LIMIT 5
) art ON alb.artist_id = art.artist_id
WHERE alb.rn <= 3;

With the results:

artist_id	name	album_id	title	artist_id
1	Artist 1	1	Album 1	1
1	Artist 1	2	Album 2	1
1	Artist 1	3	Album 3	1
2	Artist 2	4	Album 4	2
2	Artist 2	5	Album 5	2
2	Artist 2	6	Album 6	2
3	Artist 3	7	Album 7	3
3	Artist 3	8	Album 8	3
3	Artist 3	9	Album 9	3

In fact, in CockroachDB this is exactly how the transformation/rewriting is implemented:

$> explain select * from abc, lateral (select * from xyz where x = a limit 2);
                                           info
-------------------------------------------------------------------------------------------
  distribution: local
  vectorized: true
 
  • filter
  │ estimated row count: 1
  │ filter: row_num <= 2
  └── • window
      │ estimated row count: 2
      └── • hash join
          │ estimated row count: 2
          │ equality: (x) = (a)
          ├── • scan
          │     estimated row count: 6 (100% of the table; stats collected 2 minutes ago)
table: xyz@xyz_pkey
          │     spans: FULL SCAN
          └── • scan
                estimated row count: 1 (100% of the table; stats collected 3 minutes ago)
                table: abc@abc_pkey
                spans: FULL SCAN

Generated at Thu Feb 08 08:48:54 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.