What I've got
I've a base model which looks like this :
Schema::create('prospects', function (Blueprint $table) {
$table->id();
});
class Prospect extends Model
{
public function latestStep()
{
return $this->hasOne(Step::class)
->ofMany([
'date' => 'max',
'id' => 'max',
]);
}
}
And a related one :
Schema::create('steps', function (Blueprint $table) {
$table->id();
$table->foreignId('prospect_id')->constrained();
$table->datetime('date');
});
class Step extends Model
{
}
When I want to retrieve prospects which has a latestStep I go like this :
Prospect::whereHas('latestStep')->limit(10)->get();
The generated database request looks like this :
SELECT *
FROM `prospects`
WHERE EXISTS (
SELECT *
FROM `steps`
INNER JOIN (
SELECT max(`steps`.`id`) AS `id_aggregate`, `steps`.`prospect_id`
FROM `steps`
INNER JOIN (
SELECT max(`steps`.`date`) AS `date_aggregate`, `steps`.`prospect_id`
FROM `steps`
GROUP BY `steps`.`prospect_id`
) AS `latestStep`
ON `latestStep`.`date_aggregate` = `steps`.`date`
AND `latestStep`.`prospect_id` = `steps`.`prospect_id`
GROUP BY `steps`.`prospect_id`
) AS `latestStep`
ON `latestStep`.`id_aggregate` = `steps`.`id`
AND `latestStep`.`prospect_id` = `steps`.`prospect_id`
WHERE `prospects`.`id` = `steps`.`prospect_id`
)
LIMIT 10
The problem
On MySQL 5.7 it runs under 500ms for 20k prospects and 40k steps.
BUT on MariaDB 10.6 it takes between 2 to 3 seconds. If I increase the limit to 100, it takes about 20 to 30 seconds.
How can I solve this ? I've thought on putting an index there, but I don't really know on which columns.
Here are the EXPLAIN for MySQL

Edit 1
I've tried this answer https://stackoverflow.com/a/72121388/3789576 and the timing did not change.

