Использование scan
создает массив, считает его размер, а затем выбрасывает. Если у вас много вхождений подстроки в большой файл, вы временно создадите большой массив, потенциально сжигающий процессорное время с управлением памятью, но он все равно должен работать довольно быстро, даже с 300 МБ.
Поскольку Word является классом ActiveRecord, он зависит от схемы и любых индексов в вашей базе данных, а также от любых проблем, которые могут возникнуть на сервере базы данных. Если база данных не оптимизирована или реагирует медленно, или запрос, используемый для извлечения данных, неэффективен, то итерация будет медленной. Возможно, вам будет гораздо проще захватить группы Word
, чтобы они были в ОЗУ, а затем выполнить итерации по ним.
И, если база данных и ваш код работают на одном и том же компьютере, вы можете страдать от ограничений ресурсов, таких как наличие только одного диска, недостаточно ОЗУ и т. Д.
Трудно сказать, не зная больше о вашей среде и оборудовании.
РЕДАКТИРОВАТЬ:
Я могу сначала захватить подстроки в массив / хэш, затем добавить результаты подсчета в массив или хэш и записать результаты обратно в базу данных после того, как все подсчеты выполнены. Вы думаете, это будет быстрее, верно?
Нет, я сомневаюсь, что это очень поможет, и, не зная, в чем заключается проблема, все, что вы можете сделать, это усугубить проблему, потому что вам придется загрузить 10 000 записей в виде объектов из базы данных, а затем создать 10 000 элементов хеш или массив, который также будет в памяти вместе с записями в БД, затем запишите их.
В настоящее время Ruby будет использовать только одно ядро, но вы можете набрать скорость, используя Ruby 1.9+. Я бы порекомендовал установить RVM и позволить ему управлять вашим Ruby. Обязательно прочитайте инструкции на этой странице, затем запустите rvm notes
и следуйте этим указаниям.
Какова ваша модель Word и как выглядят базовая схема и индексы? База данных находится на той же машине?
РЕДАКТИРОВАТЬ: При просмотре схемы таблицы у вас нет индексов, кроме id
, который действительно не сильно поможет при обычном поиске. Я бы порекомендовал представить вашу схему на сайте-партнере Stack Overflow https://dba.stackexchange.com/ и объяснить, что вы хотите сделать. Как минимум, я бы добавил ключ к текстовым полям, чтобы избежать полных сканирований таблиц для любых выполненных вами поисков.
Что может помочь больше, это прочитать: Извлечение нескольких объектов в пакетах из «Интерфейса запросов Active Record».
Кроме того, посмотрите на SQL, генерируемый при работе Word.each
. Это что-то вроде "select * from word"
? Если это так, Rails набирает 10000 записей, чтобы перебирать их одну за другой. Если это что-то вроде "select * from word where id=1"
, то для каждой записи у вас есть чтение базы данных, за которым следует запись при обновлении счетчика. Это тот сценарий, который поможет исправить ссылка «Извлечение нескольких объектов в пакетах».
Кроме того, я предполагаю, что content
- это текст, который вы ищете, но я не могу сказать точно. Возможно ли, что у вас есть дублированные текстовые значения, заставляющие вас выполнять сканирование более одного раза для одного и того же текста? Если это так, выберите ваши записи, используя условие unique
в этом поле, а затем обновите счетчик для всех совпадающих записей за один раз.
Профилировали ли вы свой код, чтобы увидеть, может ли сам Ruby помочь вам определить проблему? Немного измените ваш код для обработки 100 или 1000 записей. Запустите приложение с флагом -r profile
. При выходе из приложения профилировщик выведет таблицу с указанием времени, потраченного на это.
Какую версию Rails вы используете?