Помогите оптимизировать запрос для MySQL - PullRequest
0 голосов
/ 18 июня 2010

У меня есть запрос MySQL, который выглядит следующим образом

SELECT
    count(`clicks`.`user_id`) as total,
    `users`.`fullname`
FROM
    `users`,
    `clicks`,
WHERE
    `users`.`id` = `clicks`.`user_id`
GROUP BY
    `clicks`.`user_id`
ORDER BY
    `total` desc
LIMIT
    0,20;

Я веду статистику по нескольким играм типа нажатия кнопок. Он имеет таблицу пользователей и таблицу кликов. Он регистрирует клики от определенного пользователя. Пользователь может нажать на кнопку в любое время. Двадцать кликов в один день, тридцать в другой и т. Д. Не все подряд.

В настоящее время около 2 000 кликов для пользователей ~ 2 000. Этот запрос в среднем занимает 1,38 секунды. Я бы хотел ускорить его, если это вообще возможно.

Ответы [ 6 ]

1 голос
/ 19 июня 2010
  1. Определен ли USERS.id как первичный ключ для таблицы? Это должно быть ...
  2. Предполагая, что INNODB, CLICKS.user_id имеет ограничение внешнего ключа для связывания его значений с USERS.id?
  3. USERS.id и CLICKS.user_id - это числовой тип данных (IE: INT), не основанный на тексте?
  4. Индексы должны быть добавлены (если они еще не существуют) для:
    • CLICKS.user_id
    • USERS.fullname
  5. Если индексы существуют, пытались ли вы обновить статистику таблицы :

    ANALYZE TABLE USERS;
    ANALYZE TABLE CLICKS;
    
1 голос
/ 19 июня 2010

Этот запрос, вероятно, выполняется так же быстро, как и при условии, что у вас есть индексированные столбцы clicks.user_id и users.id.

Одна вещь, которую я могу себе представить, - это ответственность за большую медлительностькоторый является предложением ORDER BY.Видя, что это агрегированное поле, ему, вероятно, придется сначала получить все данные, а затем отсортировать их без особой оптимизации.Сортировка является хорошим кандидатом, когда что-то идет медленно.

Другая идея состоит в том, чтобы сохранить отдельную таблицу, которая содержит общее количество кликов.Если вам нужны эти записи, то вам может потребоваться выполнить 2 запроса за клик ... один для существующей таблицы, а другой для обновления таблицы user / click, которая будет иметь только user_id и click_count плюс все, что вы думаетеявляется целесообразным.Таким образом, SELECT должны стать молниеносными даже для большого количества пользователей, потому что вы извлекаете только минимально необходимое количество строк, а не целую кучу из них, которые в любом случае только агрегируются.

0 голосов
/ 19 июня 2010

Я просто подумал о другом.Вы можете получить лучшие результаты, используя INNER JOINs.

Untested:

SELECT
    count(`clicks`.`user_id`) as total,
    `users`.`fullname`
FROM
    `users`
    INNER JOIN `clicks` ON `clicks`.`user_id` = `users`.`id`
GROUP BY
    `clicks`.`user_id`
ORDER BY
    `total` desc
LIMIT
    0,20;
0 голосов
/ 19 июня 2010

Попробуйте это (не проверено):

SELECT
    C.total,
    `users`.`fullname`
FROM
    `users`
INNER JOIN
    (SELECT COUNT(*) AS total, user_id 
     FROM 
         `clicks` 
     GROUP BY 
        `user_id` 
     ORDER BY 
        COUNT(*) 
     LIMIT 0,20) C
ON C.user_id = users.user_id

ORDER BY
    C.total desc

Подсчет строк сначала может сэкономить вам немного времени.

0 голосов
/ 18 июня 2010

Создание индекса для clicks.userid для начинающих. Это будет иметь значение

0 голосов
/ 18 июня 2010

Убедитесь, что вы создали индексы для users.id и clicks.user_id. Вы также можете попробовать подсчитать количество кликов перед выполнением объединения, но я подозреваю, что если это действительно улучшит производительность, то движок сделает это за вас.

...