Ускорить группу - PullRequest
       5

Ускорить группу

0 голосов
/ 08 ноября 2019

Рассмотрим следующий запрос:

select * 
  from `cg_reviews` 
 inner join `cg_park` on `cg_park`.`cg_id` = `cg_reviews`.`cgr_cg_id` 
 where `status` = 'approved' 
   and `cgr_approval_time` > 0 
 group by `cg_park`.`cg_id` 
 order by `cgr_approval_time` desc limit 3

В основном запрашиваются все утвержденные обзоры парка, упорядоченные по времени утверждения, и только один отзыв на парк. Это означает, что я не хочу больше одного обзора на парк, поэтому каждый из 3 результатов должен быть из другого парка (cg_id).

Этот запрос работает, но даже с каждым индексом, который я могу придумать,по-прежнему медленно на 18687 строк. Когда я удаляю группу по предложению, это молниеносно. Как еще можно сделать этот запрос с уникальными парками?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Исходя из вашего комментария об одобренных обзорах, я должен предположить, что столбец "статус" находится в таблице отзывов. Лучше всего всегда иметь table.column или alias.column, чтобы другим не приходилось угадывать, к какому столбцу относится.

Тем не менее, я хотел бы иметь индекс из нескольких столбцов, чтобы упорядочить и сгруппировать. В частности,

table        index
cg_reviews   ( status, cgr_cg_id, cgr_approval_time )

Ваша таблица парковки cg_id = reviews cgr_cg_id, поэтому, поскольку они будут иметь одинаковое значение, ваша группа может быть "cgr_cg_id" и использовать индекс.

Не видяданные, у вас может быть 100 обзоров для каждого "cgr_cg_id", и вы заботитесь только о самых последних ... и из этого вам нужен только верхний 3. Эта часть запроса не имеет отношения к таблице PARK и может быть выполненачерез

select
      r.cgr_cg_id,
      max( r.cgr_approval_time ) latestReview,
   from
      cg_reviews r
   where
          r.status = 'approved'
      and r.cgr_approval_time > 0
   group by
      r.cgr_cg_id
   order by
      max( r.cgr_approval_time ) DESC
   limit 3

Итак, теперь вы получаете 3 записи из всех отзывов. Группой является столбец идентификатора парка, и, поскольку при упорядочении по последнему максимальному времени для группы вы не получаете один и тот же парк с несколькими отзывами. Наконец, вам нужны детали для представления конечному пользователю. Это должно быть быстро, так как теперь мы можем присоединиться к таблице парковки и просмотра только этих трех записей и должны быть практически мгновенными, используя тот же индекс. Просто сделайте приведенный выше запрос первым из запроса, задав ему псевдоним

select
      r2.*,
      p.*
   from
      ( select
            r.cgr_cg_id,
            max( r.cgr_approval_time ) latestReview,
         from
            cg_reviews r
         where
                r.status = 'approved'
            and r.cgr_approval_time > 0
         group by
            r.cgr_cg_id
         order by
            max( r.cgr_approval_time ) DESC
         limit 3 ) PQ

         JOIN cg_reviews r2
            on r2.status = 'approved'
           AND PQ.cgr_cg_id = r2.cgr_cg_id 
           AND PQ.latestReview = r2.cgr_approval_time

         JOIN cg_park p
            on PQ.cgr_cg_id = p.cg_id
0 голосов
/ 08 ноября 2019

было бы лучше выполнить группировку в большей таблице до присоединения, а не после.

SELECT *
FROM (
    SELECT *
    FROM cg_reviews
    WHERE cgr_approval_time > 0
    AND status = 'approved'
    GROUP BY cgr_cg_id
) AS cgr
INNER JOIN cg_park AS cgp ON cgp.cg_id = cgr.cgr_cg_id
ORDER BY cgr_approval_time DESC
LIMIT 3

Убедитесь, что на cgr_cg_id есть индекс (если он объявлен как FOREIGN KEY индексбудет создан автоматически).

Обратите внимание, что эта группировка не даст надежных результатов. Поскольку строки cg_reviews не определяются однозначно столбцом, по которому вы группируете, вы получите столбцы из произвольных строк в каждой группе. Вероятно, вы должны увидеть SQL, выбирающий только строки с максимальным значением в столбце , чтобы узнать, как выбрать четко определенную строку в каждой группе (например, строку с самым последним временем утверждения).

...