Радиус SQL-запроса - оптимизировать

0

Я вообще не являюсь гуру SQL, но у меня есть SQL-запрос, который был автоматически использован на небольшом сервере FreeRadius. Теперь мы хотим использовать его на более крупном сервере, но я заметил, что запрос занимает много времени и использует процессор 100% в течение примерно двух минут...

Кто-нибудь имеет представление о том, как оптимизировать запрос? Цель состоит в том, чтобы найти, имеет ли пользователь более одного активного входа и получить информацию о самом старом.

Мы также можем принять больше результатов и выполнить сортировку на PHP, чтобы уменьшить нагрузку на базу данных radius.

Вот запрос, который мы используем сегодня:

  SELECT username, acctstarttime, acctsessionid, nasipaddress, framedipaddress
        FROM radacct
        WHERE username IN (
            SELECT username
            FROM radacct
            WHERE acctstoptime IS NULL
            GROUP BY username
            HAVING COUNT(username) > 1
        )
        AND acctstoptime IS NULL
        GROUP BY username
        ORDER BY username, acctstarttime ASC

С уважением

Ким

  • 0
    Просьба включить план выполнения. Вы можете использовать EXPLAIN чтобы получить это.
  • 0
    Также укажите схему таблицы, объем данных, спецификации сервера и т. Д. Они могут не понадобиться в данном конкретном случае, чтобы позволить вам улучшить, но вы всегда должны включать их.
Теги:
freeradius
radius

3 ответа

0
Лучший ответ

Я думаю, мы можем сделать только один проход по всей таблице radacct:

SELECT username, MIN(acctstarttime) AS min_start_time
FROM radacct
WHERE acctstoptime IS NULL
GROUP BY username
HAVING COUNT(*) >= 2
LIMIT 0, 30;

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

  • 0
    Я думаю, что это работает, с небольшой модификацией: SELECT username, MIN (acctstarttime) AS min_start_time FROM radacct WHERE acctstoptime IS NULL GROUP BY по имени пользователя HAVING COUNT (*)> = 2 LIMIT 0, 30
  • 0
    Я пытаюсь понять исходный запрос, и у меня в голове внешний запрос устарел, так как все данные, которые нам нужны, находятся внутри одной таблицы? Похоже, что внешний имел бы больше смысла, если бы он получал другую информацию из разных таблиц. Я на что-то здесь?
Показать ещё 1 комментарий
0

Ответы на запросы на 100% правильны, вы должны иметь возможность сделать это за один проход. Однако 2 минуты безумны! Я также подозреваю, что с одним пропуском это не так быстро, как вы хотите. У нас есть страница статуса для отображения всех пользователей, которые находятся в сети в любой момент, по причинам поддержки звучит так, как это похоже на то, что вы пытаетесь сделать.

Сначала убедитесь, что у вас есть указатель на acctstoptime. Я также подозреваю, что у вас есть плохая конфигурация в конфигурации MYSQL для работы с этой большой таблицей. Я также настоятельно рекомендую делать архивную базу данных и сохранять все активные сеансы в небольшой базе данных, что поможет много с большим объемом обновлений и вставок, что делает учет свободного радиуса.

У нас более 100 000 активных пользователей ежедневно с промежуточным обновлением в 300 секунд и генерируют около 3-4 миллиардов строк в год. каждый запрос у нас составляет менее 1 секунды. Я был бы рад помочь вам оптимизировать ваш материал радиуса.

  • 0
    Спасибо, но я разобрался. Исходный запрос был ошибочным, он повторял все записи radacct, по одному разу на запись ... так что это был скорее цикл, чем что-либо еще. Мы разрешаем пользователям дважды входить в горячую точку, но после этого мы находим и удаляем самый старый вход. Мы делаем это так, чтобы пользователь мог изменить свой маршрутизатор или логин в другом месте, не выходя из системы вручную, но он все еще может использовать только один логин за раз. Кроме того, время сеансов не истекает, они должны быть постоянными, пока у пользователя есть действующая подписка. Mikrotiks Hotspot не делает этого сам, поэтому ему нужна помощь.
0

Либо вы удаляете подзапрос

SELECT username, acctstarttime, acctsessionid, nasipaddress, framedipaddress
        FROM radacct
        WHERE acctstoptime IS NULL
        GROUP BY username
        ORDER BY username, acctstarttime ASC
        HAVING COUNT(username) > 1

или удалить group by из внешнего запроса (если вы ожидаете получить все строки с двойным username

  • 1
    У запроса есть проблемы помимо этого.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню