2013-10-08 3 views
1

У меня есть таблица в MySQL, как этогоКак обрабатывать миллионы записей ежедневно с MySQL

CREATE TABLE IF NOT EXISTS `connections` (
    `src` int(10) unsigned NOT NULL, 
    `sport` smallint(5) unsigned NOT NULL, 
    `dst` int(10) unsigned NOT NULL, 
    `dport` smallint(5) unsigned NOT NULL, 
    `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`src`,`sport`,`dst`,`dport`,`time`), 
    KEY `time` (`time`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

2,5 миллиона записей ежедневно вставленных в этой таблице.

Когда я хочу выбирать записи в течение определенного периода времени, например, дня. это занимает около 7 минут. как я могу улучшить его.

i`m используя рубин на рельсах версии 4.0.0

Мой выбор как этот

connections = Connection.select('src, dst, UNIX_TIMESTAMP(time) as time') 
        .where(time: timeFrom..timeTo) 
        .order('time ASC') 

После выбора из базы данных У меня есть цикл, как это:

connections.each do |con| 

     link = getServerID(con['src']) 
     link = getServerID(con['dst']) if link == 0 

     @total[link].append [con['time'] * 1000, con['dst']] 
end 

в этот цикл у меня есть бит процесс на src и dst, тогда я добавляю его в хеш , этот раздел берет и мой компьютер разбился

+0

Мне нужны эти записи, я не хочу выбирать меньше записей. –

+0

Получите более мощный сервер, а затем –

+1

Это похоже на то, что один фрагмент SQL может получить ваш окончательный результат без необходимости циклического перемещения большого количества данных в рубине на рельсах.Предположим, вы можете получить идентификаторы src и/или dst с соединением. Поместите немного тестовых данных и примеры того, что вы хотели бы получить от него. – Kickstart

ответ

1

Прежде всего, вы должны попытаться выполнить запрос SQL непосредственно в базу данных без Rails. Это помогает определить узкое место: медленный ли запрос или рельсы? Я думаю, что часть SQL не должна быть проблемой, но сначала проверьте ее.

Я думаю, ваша самая большая проблема заключается в connections.each. Это загружает все соответствующие строки в ваше приложение и создает модели ActiveRecord. Давайте сделаем некоторую математику: 2.5M entries * 1KB (просто угадать, возможно больше) приведет к 2.5GB данных, загруженных в вашу память. Вы можете увидеть улучшение использования connection.find_each, потому что оно загружает соединения в меньших партиях.

Что делает getServerID способ? Он называется 5M раз.

Я уверен, что вы не сможете улучшить этот код. Похоже, что неправильная база данных для проблемы или плохой алгоритм. Поскольку маловероятно, что вы хотите отображать 2.5M записей на веб-сайте, лучше сказать нам, чего вы хотите достичь.

0

Как уже упоминалось, для сбора 2,5-миллиметровых записей требуется много памяти/процессора. Попробуйте собрать записи в партиях.

Rails имеет пакетную поддержку встроенный: http://api.rubyonrails.org/classes/ActiveRecord/Batches.html

connections.find_each do |con| 
    link = getServerID(con['src']) 
    link = getServerID(con['dst']) if link == 0 

    @total[link].append [con['time'] * 1000, con['dst']] 
end 

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

Смежные вопросы