Сортировка MySQL по нескольким таблицам занимает очень много времени

#mysql #sql #sql-order-by

#mysql #sql #sql-order-by

Вопрос:

У меня есть таблица с объектами и связанными таблицами object_info, object_theme (категория), местоположения и владельцы объектов.

Что я хочу, так это сначала показать все объекты от владельцев объектов с более высоким приоритетом, а затем остальные. Итак, мой запрос выглядит примерно так:

 SELECT 
   (...)
FROM objects
INNER JOIN object_info ...
INNER JOIN objectowner_info ...
INNER JOIN locations ...
WHERE object_active = 1
  AND object_owner_active = 1
ORDER BY object_owner_priority DESC,
         object_price ASC
   LIMIT 0, 10
  

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

Каковы наилучшие шаги для оптимизации этого запроса? Я перепробовал все виды индексов, но узким местом, похоже, является сортировка. Когда я убираю это, запрос выполняется в порядке с точки зрения скорости.

(Пожалуйста, обратите внимание, что я не объединял темы (категории), я думаю реализовать это по-другому из-за отношений 1: n, которые вам также понадобятся для группировки результата, и это кажется ужасно медленным. Все остальные таблицы, упомянутые в объединении, имеют соотношение 1: 1.).

Для сравнения: запрос без сортировки по обоим столбцам занимает 0,0011 секунды. Упомянутый выше с обоими столбцами 0.8779. Но в зависимости от нагрузки это может занять даже секунды.


ОБЪЯСНИТЕ с помощью сортировки:

 id  select_type     table   type    possible_keys                                       key                 key_len     ref             rows    Extra
1   SIMPLE          o       ALL     PRIMARY,fk_object_user,fk_object_city,type active   NULL                NULL        NULL            63773   Using where; Using temporary; Using filesort
1   SIMPLE          ooi     ref     fk_objectowner_id                                   fk_objectowner_id   4           o.object_user   1       Using where
1   SIMPLE          oo      eq_ref  PRIMARY,id_and_status                               PRIMARY             4           o.object_user   1       Using where
1   SIMPLE          l       eq_ref  PRIMARY                                             PRIMARY             4           o.object_city   1       Using where
1   SIMPLE          oi      ref     fk_info_lang,fk_info_object,lang_object             fk_info_object      3           o.object_id     1       Using where
  

ОБЪЯСНЯТЬ без сортировки:

 id  select_type     table   type    possible_keys                                       key                 key_len     ref             rows    Extra
1   SIMPLE          o       ALL     PRIMARY,fk_object_user,fk_object_city,type active   NULL                NULL        NULL            63773   Using where
1   SIMPLE          ooi     ref     fk_objectowner_id                                   fk_objectowner_id   4           o.object_user   1   Using where
1   SIMPLE          oo      eq_ref  PRIMARY,id_and_status                               PRIMARY             4           o.object_user   1   Using where
1   SIMPLE          l       eq_ref  PRIMARY                                             PRIMARY             4           o.object_city   1   Using where
1   SIMPLE          oi      ref     fk_info_lang,fk_info_object,lang_object             fk_info_object      3           o.object_id     1   Using where
  

Комментарии:

1. Фигурируют ли object_owner_priority и object_price (что наиболее важно, первый из двух) в каком-либо из индексов, используемых при выполнении этого запроса?

2. Индекс задается в таблице objectowner. Но когда я выполняю запрос EXPLAIN, он не отображается в списке «возможные ключи».

3. «запрос без сортировки по обоим столбцам занимает 0,0011 секунды». Сколько времени это займет, если у вас есть LIMIT 0,1000 ?

4. Можете ли вы также опубликовать результат EXPLAIN?

5. Было бы полезно, если бы вы могли опубликовать сценарии создания таблиц и фактический запрос, который вы выполняете — прямо сейчас это немного гипотетично.

Ответ №1:

Определите индексы в object_owner_priority и object_price и измените предложение where на что-то вроде:

 WHERE object_active   0 = 1
  AND object_owner_active   0 = 1
  

Если повезет, это должно сработать. Если вы определили индексы для object_active или object_owner_active, рассмотрите возможность их удаления.

Комментарии:

1. К сожалению, это не сработало. Для упомянутых вами индексов определяются и удаляются индексы. Результата нет. Для сравнения: запрос без обеих сортировок занимает 0,0011 секунды. При обеих сортировках: 0,8779 секунды.

Ответ №2:

Что ж, теперь проблема решена путем создания отдельных столбцов заказа и заполнения их с помощью задания cron, которое время от времени выполняет медленный запрос для генерации требуемого заказа.