2016-10-11 3 views
0

У меня есть запрос, который получает доступ к журналам посещения сайта из таблицы. Затем я присоединяюсь к другим двум таблицам, чтобы получить всю информацию пользователя. На этом этапе запрос прекрасен.MySQL (pdo) Медленный дополнительный запрос

Медленный запрос: Затем я должен использовать вспомогательный запрос, чтобы получить журналы посещения на определенную дату на основе состояния. Именно этот подзапрос заставляет весь запрос практически размалывать. Через 30-40 секунд запрос завершится.


Таблицы:

  • Таблицы InnoDB (изменение в MyISAM не имеет никакого значения для производительности).
  • Таблица 1 имеет около 1 м записей. Таблица2 имеет около 250K. Таблица 3 имеет около 100K. Таблица 4 имеет около 500K.


Запрос:

SELECT COUNT(*) AS visits , table1.userName, table2.userId, table2.col1, table2.col2, table2.col3, table2.col4, table3.col20 
    FROM table1 
    LEFT JOIN table2 ON table2.userName = table1.userName 
    LEFT JOIN table3 ON table3.col2 = table1.col2 
    WHERE table1.col1 = 'foo' 
    AND table1.Date > (
     SELECT max(a.VisitDate) FROM table4 a 
      WHERE a.userId = table2.userId AND a.col1 = 'bar' 
     ) 
    GROUP BY table1.userName, table1.Date 

Я не строил эту структуру данных и не имею возможности изменить его. Я анализирую этот запрос на базовую функцию PDO.

+1

соединения являются более эффективными, чем подзапросов – nogad

+0

Run EXPLAIN на этот запрос и добавить результаты на вопросы –

+0

также, было бы полезно знать, что индексы, которые вы указали на таблицах –

ответ

0

Вы можете попробовать с помощью внутреннего соединения (на подвыборки)

SELECT 
     COUNT(*) AS visits 
    , table1.userName 
    , table2.userId 
    , table2.col1 
    , table2.col2 
    , table2.col3 
    , table2.col4 
    , table3.col20 
FROM table1 
LEFT JOIN table2 ON table2.userName = table1.userName 
LEFT JOIN table3 ON table3.col2 = table1.col2 
INNER JOIN (
    SELECT max(a.VisitDate) as max_visit_date FROM table4 a 
     WHERE a.userId = table2.userId AND a.col1 = 'bar' 
    ) t on table1.Date > t.max_visit_date 
GROUP BY table1.userName, table1.Date; 
Смежные вопросы