2

У меня есть запрос, который занимает 48 секунд, чтобы выполнить следующим образом:SELECT DISTINCT Очень медленно

SELECT count(DISTINCT tmd_logins.userID) as totalLoginsUniqueLast30Days 
FROM tmd_logins 
join tmd_users on tmd_logins.userID = tmd_users.userID 
where tmd_users.isPatient = 1 AND loggedIn > '2011-03-25' 
and tmd_logins.userID in 
    (SELECT userID as accounts30Days FROM tmd_users 
    where isPatient = 1 AND created > '2012-04-29' AND computerID is null) 

Когда я удалить DISTINCT ключевое слово она занимает менее 1 секунды, так что кажется, что горлышко бутылки лежит в том, что ,

База данных добавляет запись в таблицу tmd_logins каждый раз, когда пользователь входит в систему. Я пытаюсь получить общее количество всех пользователей, которые были созданы и зарегистрированы в течение определенного периода времени, например, за последние 30 дней.

Я попытался удалить ключевое слово DISTINCT и добавить group by tmd_logins.userID в инструкцию, но проблема с производительностью остается.

Таблица tmd_logins насчитывает около 300000 записей, tmd_users имеет около 40000

Есть ли лучший способ сделать это?

+1

Глупый вопрос: вместо этого вы пытались использовать 'DISTINCT tmd_users.userID'? Результат должен быть таким же, но вам может повезти с оптимизатором, потому что 'tmd_users.userID' индексируется (при условии, конечно, его первичный ключ' tmd_users'). – dasblinkenlight

+0

У вас есть индекс на созданном и loggedIn? –

+0

Можем ли мы увидеть план выполнения? – HABO

ответ

3

Проблема в том, что у вас есть план выполнения. Я предполагаю, что предложение «in» может ввести в заблуждение. Вы можете попробовать:

SELECT count(DISTINCT tmd_logins.userID) as totalLoginsUniqueLast30Days 
FROM tmd_logins join 
    tmd_users 
    on tmd_logins.userID = tmd_users.userID join 
    (SELECT distinct userID as accounts30Days 
     FROM tmd_users 
     where isPatient = 1 AND 
      created > '2012-04-29' AND 
      computerID is null 
    ) t 
    on tmd_logins.userID = t.accounts30Days 
where tmd_users.isPatient = 1 AND 
     loggedIn > '2011-03-25' 

Это может быть или не работает. Однако мне интересно, о структуре самого запроса. Казалось бы, UserID должен отличаться от таблицы tmd_users. Если это так, то вы можете обернуть все свои условия в одну:

SELECT count(DISTINCT tmd_logins.userID) as totalLoginsUniqueLast30Days 
FROM tmd_logins join 
    tmd_users 
    on tmd_logins.userID = tmd_users.userID 
where tmd_users.isPatient = 1 AND 
     loggedIn > '2011-03-25' and 
     created > '2012-04-29' AND 
     computerID is null 

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

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