2015-09-02 4 views
0

У меня есть следующий запрос, который занимает около 15 секунд. Если я удалю ORDER BY, это займет 3 секунды, что слишком длинное.MySQL Query с левым соединением, группой и порядком очень медленно

SELECT 
pages.id AS id, 
pages.page_title AS name, 
SUM(visitors.bounce) AS bounce, 
SUM(visitors.goal) AS goal, 
count(visitors.id) AS volume 
FROM 
pages 
LEFT JOIN visitors ON pages.id = visitors.page_id 
GROUP BY pages.id 
ORDER BY volume DESC 

Для удобства чтения, я немного упростили этот запрос от той, которая используется в приложении, но я тестировал с этим упрощенным запросом и проблема не существует до сих пор. Так что проблема в этой части.

Табличные страницы: около 3 тыс. Записей. Посетители таблицы: около 300 тыс. Записей.

То, что я сделал:

  • У меня есть индексы на visitors.page_id (с внешним ключом ссылается pages.id).
  • Очевидно, что мои идентификационные поля заданы как первичный ключ.

То, что я пробовал:

  • я увеличил read_buffer_size, sort_buffer_size, read_rnd_buffer_size, к 64M.
  • EXPLAIN запрос с сортировкой (15 секунд): enter image description here
  • Объяснить запрос без сортировки (3 сек, до сих пор способ долго, и это не выход, я хочу): enter image description here
  • Снимите SUM и граф расчетов, они действительно не повлияли на время выполнения.

Любые идеи для улучшения запроса?

+0

Базы данных не могут волшебным образом сделать все быстрее. Ваш запрос требует полного сканирования 2 таблиц, потому что он должен извлекать все строки независимо от того, что вы делаете. Это займет пару секунд для таблицы в 300 тыс. Строк. Кроме того, в планах появляются предложения WHERE, даже если ваш запрос их не имеет. Вы уверены, что именно этот запрос EXPLAIN задал? Вы можете кэшировать результат каждые несколько минут и доставлять его клиенту? – jpmc26

+0

Это действительно немного сложнее, есть несколько фильтров, которые могут быть установлены пользователем, но они, похоже, не влияют на скорость запроса, поэтому я удалил их в этом примере. Но мабы вместо того, чтобы упростить мой вопрос, я сделал его менее простым, извините. Из-за этих настроек пользователи могут установить, кеширование затруднено (сотни вариантов) ... Вы думаете, что лучше, если я задам новый вопрос с полным запросом? Я полагал, что пока этот базовый пример медленный, это необходимо решить в первую очередь. Но теперь я понимаю, что, вероятно, фильтры могут сделать это быстрее ... – dirk

+0

Фильтры могут предоставлять параметры индексирования. Пейджинг плюс индекс тоже может помочь. Оба варианта предоставляют возможность ограничить размер набора результатов, который должна обрабатывать база данных. Хотя, поскольку вы хотите сортировать по результату, пейджинг может быть недостаточно для вас. – jpmc26

ответ

1

Во-первых, попробуйте Мое первое предложение сделать агрегацию до присоединения:

SELECT p.id, p.page_title AS name, 
     v.bounce, v.goal,v.volume 
FROM pages p LEFT JOIN 
    (SELECT page_id, sum(v.bounce) as bounce, sum(v.goal) as goal, 
      count(*) as volumn 
     FROM visitors v 
     GROUP BY page_id 
    ) v 
    ON pages.id = v.page_id 
ORDER BY volume DESC; 

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

+0

Спасибо. Это имеет существенное значение.Вместе с выводами из комментариев моего сообщения (на самом деле есть некоторая фильтрация, из-за меня не было разумно упростить вопрос), я могу это исправить. Благодаря! – dirk

Смежные вопросы