Оптимизация MySQL для большой таблицы myisam

OS=centos 6.7  [Dedicated server]
memory=15G      
cpu=Intel(R) Xeon(R) CPU E5-2403
mysql= V 5.1.73    

Вот таблица MyISAM и содержит около 5 миллионов строк данных. Через каждые 5-6 минут вставляются данные примерно для 3000 пользователей (например, скорость загрузки и загрузки, статус сеанса и т. д.).

информация таблицы: опишите "radacct"

enter image description here

мой.cnf

enter image description here

enter image description here

из mysql медленный журнал запросов один из запросов, который занимает больше всего времени ниже

Query_time: 7.941773  Lock_time: 0.155912 Rows_sent: 1 Rows_examined: 5377
use freeradius;
SET timestamp=1461582118;
SELECT sum(acctinputoctets) as upload,
       sum(acctoutputoctets) as     download
    FROM radacct a 
    INNER JOIN (SELECT acctuniqueid, MIN( radacctid )     radacctid 
                   FROM radacct 
                   WHERE username='batman215'
                     and acctstarttime  between '2016-02-03 12:10:47'
                                            and '2016-04-25 16:46:01' 
                   GROUP BY   acctuniqueid) b 
        ON a.acctuniqueid = b.acctuniqueid 
       AND a.radacctid =    b.radacctid;

объяснить результат запроса

enter image description here

когда есть много пользователей, которые пытаются увидеть их потребления пропускной способности сервер не может выполнить запросы из-за высокой нагрузки и ИО. Есть ли что-то, что я могу сделать для дальнейшей оптимизации базы данных ?

индексы из таблицы "radacct"

enter image description here

объяснить запрос без использования G

enter image description here

спасибо

2 ответов


давайте разберемся с этим, начиная с вашего внутреннего запроса, который:

        SELECT acctuniqueid, 
               MIN( radacctid ) radacctid 
          FROM radacct 
         WHERE username='batman215'
           and acctstarttime between '2016-02-03 12:10:47'
                                 and '2016-04-25 16:46:01' 
      GROUP BY   acctuniqueid

вы ищете матч равенства на username и матч диапазона на acctstarttime. Затем вы используете acctuniqueid для группировки и вытягивания экстремального значения (MIN()) от radacctid.

поэтому, чтобы ускорить этот подзапрос, вам нужен следующий составной индекс.

(username, acctstarttime, acctuniqueid, radacctid)

как это работает? Подумайте об индексе (это индексы BTREE) как отсортированном списке значений в он.

  1. обработчик запросов произвольно обращается к списку -- fast, O (log (n)) -- чтобы найти первую запись, соответствующую username и нижний конец вашего

               WHERE username='batman215'
                 and acctstarttime  between ...

просит INDEX(username, acctstarttime) в таком порядке.

    ON a.acctuniqueid = b.acctuniqueid 
   AND a.radacctid =    b.radacctid;

просит INDEX(acctuniqueid, radacctid) (в любом порядке) (или индекс покрытия Олли).

"каждые 5-6 минут вставляются данные примерно для 3000 пользователей" просит InnoDB вместо MyISAM. MyISAM делает блокировки таблиц, тем самым "вставка" вмешивается в другие запросы. советы по преобразованию.