PHP, оптимизация запросов и задачи, паттерны решения проблемы. Как сделать функциональность быстрее и лучше

Я программирую блог и столкнулся с проблемой. Автоблог.

Суть состоит в том, что на страницу нужно вывести post, информацию пользователя который написал данный пост, количество комментариев + комментарии, количество подписчиков и подписок пользователя, количество лайков поста.

Я использую yii2 ( для REST API )

Тоесть приблизительно для вывода одной страницы мне нужно сделать много запросов в БД, а именно:

Вот так я получаю данные по посту, информацию по авто и так далее

$query = $this->getPostSelect();
        $query->addSelect([
            'user_cars.id as userCarId',
            'user_cars.makeId',
            'user_cars.modelId',
            'user_cars.generationId',
            'makes.name as makeName',
            'models.defaultName as modelDefaultName',
            'models.name as modelName',
            'generations.defaultName as generationDefaultName',
            'generations.name as generationName',
            'user_cars.carUsername',
            'cars_posts.costAmount',
            'cars_posts.costCurrency',
        ])
            ->innerJoin(UserCars::tableName(), 'cars_posts.carId = user_cars.id')
            ->innerJoin(Makes::tableName(), 'user_cars.makeId = makes.id')
            ->innerJoin(Models::tableName(), 'user_cars.modelId = models.id')
            ->innerJoin(Generations::tableName(), 'user_cars.generationId = generations.id');

        $post = $query->where(['cars_posts.id' => $postId])
            ->orderBy(['cars_posts.id' => SORT_DESC])
            ->asArray()
            ->one();

метод getPostSelect

return $this::find()
            ->select([
                'cars_posts.id',
                'cars_posts.title',
                'cars_posts.categoryId',
                'cars_posts.content',
                'cars_posts.userId',
                'cars_posts.createdAt',
                'cars_posts.mileage',
                'cars_posts.coverUrl',
                'user.username',
                'user.country',
                'user.avatar',
                'user.city',
                'categories.id as categoryId',
                'categories.name'
            ])
            ->innerJoin(User::tableName(), 'user.id = cars_posts.userId')
            ->innerJoin(Categories::tableName(), 'categories.id = cars_posts.categoryId');

Далее мне нужно получить количество комментариев по посту:

public function getCountComments($postId){
  return self::find()->where(['postId' => $postId])->count();
}

далее получить комментарии: Для пагинации использую lastId, вместо offset (работает на много быстрее)

public function getPostComments($lastId, $postId)
    {
        return self::find()->select(['id', 'comment', 'date'])
            ->where(['postId' => $postId])
            ->andWhere(['<', 'id', $lastId])
            ->limit(10)
            ->all();
    }

Далее получить количество лайков поста

public function getCountLikes()
{
  return self::find()->where(['postId' => $postId])->count();
}

Далее получить количество подписок и подписчиков для пользователя который написал данные пост. И вот здесь я задался вопрос, а не слишком ли много запросов в базу данных для получения информации для одного поста?

Как это оптимизировать?

Мои мысли таковы:

  1. Слишком тяжелый и большой запрос на получение информации поста. Получать имя модели, марки, генерации и категории можно по другому, а именно переделать все это на отдельные запросы SELECT и их закешировать, данные будут браться с кеша и пропадет большая связка и запрос будет работать быстрее.

  2. Получать количество комментариев. Сохранять комментарии в БД , а также информацию обновлять в кеше (Redis? FileCache?). Тоесть пользователь написал комментарий:

  3. ДОбавить комментарий в базу данных

  4. В кеше будет храниться массив индификаторов комментариев и при добавлении комментария добавлять его на начало масива в кеше (аналогично и с удалением комментария, удаляем в БД и удаляем в кеше). Затем взять массив с кеша и подсчитать количество (а это означает что для подсчета количества комментариев мы не будем трогать БД)

  5. Аналогично и с лайками, храним информацию в БД(кто поставил лайк на какой пост) и обновляем инфу в кеше

  6. Аналогично с количество подписок и подписчиков

Так я вижу как возможно оптимизировать. И тогда для получения информации мы делаем 1-ин запрос на получение поста, все остальное берем с кеша.

Правильный ли такой подход? Как правильно или лучше было бы оптимизировать данную логику и решить проблему? Правильная ли логика для средне нагружаемоего блога? Уж очень не хочеться на столько сильно трогать БД. Если решение логично и правильно, какой кеш лучше использовать? Очень хорошо Redis, и очень удобен в работе, также стандарный yii2 FileCache.

P.S Таблицы проиндексированы.


Ответы (0 шт):