Я вообще не являюсь гуру 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
С уважением
Ким
Я думаю, мы можем сделать только один проход по всей таблице 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
для каждого пользователя.
Ответы на запросы на 100% правильны, вы должны иметь возможность сделать это за один проход. Однако 2 минуты безумны! Я также подозреваю, что с одним пропуском это не так быстро, как вы хотите. У нас есть страница статуса для отображения всех пользователей, которые находятся в сети в любой момент, по причинам поддержки звучит так, как это похоже на то, что вы пытаетесь сделать.
Сначала убедитесь, что у вас есть указатель на acctstoptime. Я также подозреваю, что у вас есть плохая конфигурация в конфигурации MYSQL для работы с этой большой таблицей. Я также настоятельно рекомендую делать архивную базу данных и сохранять все активные сеансы в небольшой базе данных, что поможет много с большим объемом обновлений и вставок, что делает учет свободного радиуса.
У нас более 100 000 активных пользователей ежедневно с промежуточным обновлением в 300 секунд и генерируют около 3-4 миллиардов строк в год. каждый запрос у нас составляет менее 1 секунды. Я был бы рад помочь вам оптимизировать ваш материал радиуса.
Либо вы удаляете подзапрос
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
EXPLAIN
чтобы получить это.