Golthana Posted June 22, 2016 Posted June 22, 2016 Извините, если в в той теме. Вопрос по оптимизации работы mysql. Есть таблица, в которой хранится netflow. Любой запрос выполняется 10 мин. Как диагностировать проблему?
KaYot Posted June 22, 2016 Posted June 22, 2016 http://mysqltuner.com/ Качаете скрипт, запускаете, он вам все подробно расскажет.
Golthana Posted June 22, 2016 Author Posted June 22, 2016 Да. Запускал, выполнил рекомендации. Все равно выполнение запроса = 10 минутам. При том, что select COUNT(*) from 'table_name'; Делается быстро.
alsdfg Posted June 22, 2016 Posted June 22, 2016 Да. Запускал, выполнил рекомендации. Все равно выполнение запроса = 10 минутам. При том, что select COUNT(*) from 'table_name'; Делается быстро. Смотрите http://dev.mysql.com/doc/refman/5.7/en/explain.html Также смотрите чтобы были индексы на поля по которым происходит выборка в запросе.
Golthana Posted June 22, 2016 Author Posted June 22, 2016 mysql> EXPLAIN SELECT * FROM raw;+----+-------------+-------+------+---------------+------+---------+------+-----------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+-----------+-------+| 1 | SIMPLE | raw | ALL | NULL | NULL | NULL | NULL | 820510737 | NULL |+----+-------------+-------+------+---------------+------+---------+------+-----------+-------+1 row in set (0.01 sec)
Golthana Posted June 22, 2016 Author Posted June 22, 2016 Вот структура: mysql> show create table raw;+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Table | Create Table |+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| raw | CREATE TABLE `raw` ( `unix_secs` int(11) unsigned NOT NULL DEFAULT '0', `unix_nsecs` int(11) unsigned NOT NULL DEFAULT '0', `sysuptime` int(11) unsigned NOT NULL DEFAULT '0', `exaddr` varchar(15) NOT NULL DEFAULT '0', `dpkts` int(11) unsigned NOT NULL DEFAULT '0', `doctets` int(11) unsigned NOT NULL DEFAULT '0', `srcaddr` varchar(15) NOT NULL DEFAULT '0', `dstaddr` varchar(15) NOT NULL DEFAULT '0', `srcport` smallint(5) unsigned NOT NULL DEFAULT '0', `dstport` smallint(5) unsigned NOT NULL DEFAULT '0', `prot` tinyint(3) unsigned NOT NULL DEFAULT '0') ENGINE=MyISAM DEFAULT CHARSET=latin1 |+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.00 sec)
bos Posted June 22, 2016 Posted June 22, 2016 я конечно не силен, в БД, но мне кажется, что если вы проведете партиционирование таблицы, и перепишите запросы чтобы они использовали все прелести партиционирования, то будет значительно легче. использование innodb так же предпочтительнее, разработчики говорят что myisam безнадежно устарел и в след 7м релизе будет выпилен. (по заявлениям некоторых людей innodb показывает более лучшие результаты и в olap oltp )
KaYot Posted June 22, 2016 Posted June 22, 2016 Первым делом нужно поменять движок таблицы на InnoDB, и задать для mysql здоровенный innodb_pool. Сейчас у вас запросы вероятно вообще не кешируются и каждый раз выполняются с вычиткой всей таблицы с диска.
NiTr0 Posted June 22, 2016 Posted June 22, 2016 Вот структура 1) как уже сказали - InnoDB вместо окаменелости MyISAM 2) индексы где? без индексов - мускул тупо сравнивает каждую из 820 млн строк с критериями where...
Golthana Posted June 22, 2016 Author Posted June 22, 2016 индексы где? Их на каждый столбец прописывать?
Golthana Posted June 22, 2016 Author Posted June 22, 2016 SELECT FROM_UNIXTIME(unix_secs), srcaddr, (SUM(doctets)/1024)/1024 as 'doctets' FROM raw WHERE srcaddr = '".$ip."' AND DATE_FORMAT(FROM_UNIXTIME(unix_secs), '%Y-%m-%d') between '".$startdate."' AND '".$enddate."' GROUP BY DATE_FORMAT(FROM_UNIXTIME(unix_secs), '%Y-%m-%d') Вот весь запрос
KaYot Posted June 22, 2016 Posted June 22, 2016 Индексами должны быть поля используемые в where. У вас это unix_secs и srcaddr. Добавьте, это сразу даст многократный буст к скорости обработки.
Golthana Posted June 22, 2016 Author Posted June 22, 2016 (edited) CREATE INDEX ip ON raw(srcaddr); и CREATE INDEX date ON raw(unix_secs) ТАК? А запрос поменяется от этого? Движок таблицы уже уже сменил Edited June 22, 2016 by Golthana
KaYot Posted June 22, 2016 Posted June 22, 2016 Запрос не поменяется, индексы лишь упрощают движку поиск в таблице. Теоретически 1 индекс на базе 2ух полей в вашем случае(с миллионами записей) будет еще эффективнее, но тут жена-архитектор БД сказала "хз, нужно тестить" Добавьте индексы, дайте базе большой кэш innodb и будет все космически.
NiTr0 Posted June 22, 2016 Posted June 22, 2016 DATE_FORMAT(FROM_UNIXTIME(unix_secs), '%Y-%m-%d') between '".$startdate."' AND '".$enddate." эта херня принципиально неиндексируемая. уж не в абиллсе ли такой бред подсмотрели? делайте нормальный запрос (да-да, startdate и enddate в unixtime, а не вырывание гланд через анус) и делайте индекс по полям, используемым в выборке.
Golthana Posted June 22, 2016 Author Posted June 22, 2016 делайте нормальный запрос Например? уж не в абиллсе ли такой бред подсмотрели? Нет. В какой-то статье прочитал. Поскольку в mysql несилен, то не могу оценить правильность введенного запроса
foreverok Posted June 22, 2016 Posted June 22, 2016 Индексы, движки - это конечно все возможно и даст небольшой прирост. Судя по самому запросу и размеру БД, проблема в том, что создается временная таблица на диске (диски наверное не ssd?), причем не маленькая. Посмотрите размер временной таблицы которая создается при выполнении запроса, возможно удастся засунуть её в tmpfs.
Golthana Posted June 22, 2016 Author Posted June 22, 2016 диски наверное не ssd?) Нет Посмотрите размер временной таблицы которая создается при выполнении запроса, возможно удастся засунуть её в tmpfs. А ссылку на документацию по этому поводу можно? Или в двух словах?
KaYot Posted June 22, 2016 Posted June 22, 2016 (edited) А с какой стати автоматически создаваться временной таблице? Edited June 22, 2016 by KaYot
Golthana Posted June 22, 2016 Author Posted June 22, 2016 (edited) Создаю два индекса. Процесс задумался, видимо время надо) Потом сравню результат. SELECT FROM_UNIXTIME(unix_secs), srcaddr, (SUM(doctets)/1024)/1024 as 'doctets' FROM raw WHERE srcaddr = '".$ip."' AND FROM_UNIXTIME(unix_secs) between '".$startdate."' AND '".$enddate."' GROUP BY FROM_UNIXTIME(unix_secs); Такой запрос имелся ввиду? Edited June 22, 2016 by Golthana
Golthana Posted June 22, 2016 Author Posted June 22, 2016 | Table | Create Table |+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| raw | CREATE TABLE `raw` ( `unix_secs` int(11) unsigned NOT NULL DEFAULT '0', `unix_nsecs` int(11) unsigned NOT NULL DEFAULT '0', `sysuptime` int(11) unsigned NOT NULL DEFAULT '0', `exaddr` varchar(15) NOT NULL DEFAULT '0', `dpkts` int(11) unsigned NOT NULL DEFAULT '0', `doctets` int(11) unsigned NOT NULL DEFAULT '0', `srcaddr` varchar(15) NOT NULL DEFAULT '0', `dstaddr` varchar(15) NOT NULL DEFAULT '0', `srcport` smallint(5) unsigned NOT NULL DEFAULT '0', `dstport` smallint(5) unsigned NOT NULL DEFAULT '0', `prot` tinyint(3) unsigned NOT NULL DEFAULT '0') ENGINE=InnoDB DEFAULT CHARSET=latin1 |
Melanxolik Posted June 22, 2016 Posted June 22, 2016 Я бы ip загонял в ntoa. Unixsec генерирует кучу неповторных значений что заставляет сканировать таблицу до поиска соответствий. Ради интереса. Если сперва найти диапазон времени и потом ip?
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now