programing

라라벨에서 마리아와 천천히 많은 관계를 맺는다.DB

randomtip 2022. 9. 4. 13:23
반응형

라라벨에서 마리아와 천천히 많은 관계를 맺는다.DB

내가 가진 것

다음과 같은 기본 모델이 있습니다.

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',
            ]);
    }
}

그리고 관련된 것:

Schema::create('steps', function (Blueprint $table) {
    $table->id();
    $table->foreignId('prospect_id')->constrained();
    $table->datetime('date');
});


class Step extends Model
{
}

취득하고 싶은 경우prospects그 안에latestStep저는 이렇게 해요.

Prospect::whereHas('latestStep')->limit(10)->get();

생성된 데이터베이스 요청은 다음과 같습니다.

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

문제

MySQL 5.7에서는 200k 잠재 고객 및 40k 단계에 대해 500ms 미만으로 작동합니다.

그러나 MariaDB 10.6에서는 2~3초 걸립니다.제한을 100으로 늘리면 20초에서 30초 정도 걸립니다.

어떻게 하면 해결할 수 있을까요?거기에 색인을 붙일까 생각 중인데, 어느 열에 붙이는지 잘 모르겠어요.

여기 있습니다.EXPLAINMySQL용

그리고 MariaDB

편집 1

이 답변은 https://stackoverflow.com/a/72121388/3789576에서 시도했지만 타이밍은 변경되지 않았습니다.

다음은 MariaDB에 대응하는 설명입니다.

쿼리에 대해 자세히 알 수는 없지만 다음과 같은 인덱스가 도움이 됩니다.

steps:  INDEX(prospect_id,  date)
steps:  INDEX(date, prospect_id,  id)
steps:  INDEX(prospect_id, id,  date)

복합 인덱스를 추가할 때 선행 열이 동일한 DROP 인덱스.즉, INDEX(a)와 INDEX(a, b)가 모두 있는 경우, 전자를 던집니다.

그리고... 그 때...LIMIT 10없이.ORDER BYOptimizer는 임의의 10 행을 자유롭게 선택할 수 있습니다.아마도 당신은 "최신"이나 다른 무언가를 선호하나요?

(PS: 생성된 SQL, Create Table 및 Descriptions를 제공해 주셔서 감사합니다.)

언급URL : https://stackoverflow.com/questions/72116019/slow-ofmany-relationship-in-laravel-for-mariadb

반응형