2017-02-01 5 views
0

У меня есть 3 таблицы InnoDB 2 из которых являются "большой"TIMESTAMPDIFF оптимизации MIN MAX

  • composer_sessions 92 строк
  • сессий 2,530,587 строк
  • отслеживания 8,032,697 на строки

Я бегу следующий запрос:

SELECT TIMESTAMPDIFF(SECOND, 
        MIN(tracking.timestamp), 
        MAX(tracking.timestamp)) AS `thetime`, 
     SUM(tracking.type = 'scene') AS `scenecount` 
FROM `tracking`, `sessions` 
WHERE tracking.tour_ID = '102098' 
    AND sessions.session_ID = tracking.session_ID 
    AND sessions.IP NOT IN(SELECT DISTINCT `IP` 
          FROM `composer_sessions`) 
GROUP BY tracking.session_ID 
HAVING TIMESTAMPDIFF(SECOND, MIN(tracking.timestamp), 
          MAX(tracking.timestamp)) <= '3600' 
    AND TIMESTAMPDIFF(SECOND, MIN(tracking.timestamp), 
          MAX(tracking.timestamp)) > '60' 
    AND SUM(tracking.type = 'scene') >= '2' 

Все столбцы, используемые в запросе, индексируются. «Соединение» в запросе используется для отсечения данных, связанных с IP-адресами, которые нам не нужны в результатах.

Есть ли лучший способ для меня структурировать этот запрос и/или может ли кто-нибудь предложить сложные (многоколоночные) индексы, чтобы сделать этот запрос быстрее?

+0

Попробуйте использовать 'thetime' в' п HAVING', вместо того чтобы повторять расчет. Хотя я не уверен, что это изменит ситуацию. – Barmar

+0

Попробуйте заменить тест 'NOT IN' шаблоном' LEFT JOIN/NULL'. – Barmar

+0

Возможно, вы захотите прочитать это, особенно раздел о вопросах эффективности запросов. http://meta.stackoverflow.com/questions/271055/tips-for-asking-a-good-structured-query-language-sql-question/271056#271056 –

ответ

1

Попробуйте изменить запрос, чтобы использовать современный синтаксис объединения, сказать

SELECT ... 
    FROM tracking 
    JOIN sessions ON sessions.session_ID = tracking.session_ID 
    LEFT JOIN composer_sessions ON sessions.IP = composer_sessions.IP 
WHERE composer_sessions.IP IS NULL 
    AND tracking.tour_ID = '102098' 
GROUP BY tracking.session_ID 
HAVING ... 

Это также использует LEFT JOIN ... IS NULL шаблон для устранения нежелательных строк на основе содержимого вашей третьей таблицы.

Затем создайте так называемый compound covering index на вашей таблице tracking. Он должен содержать следующие столбцы в этом порядке.

(tour_id, session_id, timestamp, type) 

Это позволяет tracking часть вашего запроса, чтобы быть удовлетворены непосредственно из индекса. Планировщик запросов может произвольно получить доступ к индексу на основе вашего выбора tour_id, поскольку это значение остается самым большим в индексе. Затем он может последовательно сканировать индекс, чтобы вытащить остальную часть необходимого вам материала.

Аналогично, попробуйте составной индекс на вашей sessions таблице на

(session_ID, IP) 

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

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

Прочитайте это: http://use-the-index-luke.com/