2015-05-18 4 views
-2

У меня есть приложение на основе Rails 4, которое обрабатывает некоторые работы стиля SIEM для нас. Я очень верю в то, чтобы сделать код максимально читаемым, а затем беспокоиться об оптимизации. Я обнаружил, что попытка найти все события, содержащие набор слов, приводит к исключительно низкой производительности, если я полагаюсь на AR, поэтому я прибегал к использованию SQL напрямую, даже если он хрупкий.ActiveRecord против SQL - Есть ли более чистый способ?

Есть ли лучший способ сделать следующее с помощью AR?

sql = "select event_id from events_words where generated>'#{starting_time.to_s(:db)}' and word_id in (select id from words where words.text in ('#{terms.join("', '")}')) group by event_id having count(distinct(word_id))=#{terms.count}" 

events_words является объединением таблица, содержащая word_id для каждого слова в каждом случае, в event_id для каждого события и generated, метку времени, когда было сгенерировано событие. Сгенерированное поле используется для ограничения результатов поиска до временного интервала, а сама таблица разбивается по дате, чтобы поддерживать индексы в размере, который может поместиться в ОЗУ.

ответ

0

Для повышения производительности и удобочитаемости рассмотрите возможность использования операции JOIN вместо IN (subquery). Чтобы улучшить удобочитаемость, рассмотрите квалификацию с каждой ссылкой.

Лично я нашел бы это утверждение будет гораздо более «читаемый»:

 SELECT e.event_id 
     FROM events_words e 
     JOIN (SELECT w.id 
        FROM words w 
       WHERE w.text IN ('#{terms.join("', '")}') 
      ) s 
      ON s.id = e.word_id 
     WHERE e.generated > '#{starting_time.to_s(:db)}' 
     GROUP BY e.event_id 
     HAVING COUNT(DISTINCT(e.word_id))=#{terms.count} 

... («читаемости» судить с точки зрения способности читателя, чтобы быстро выяснить, что запрос делать).

Как получить такой запрос, как сделанный в ActiveRecord (если это возможно), я склонен жалеть бедную душу, которая должна пробираться сквозь все то, что похоже на расшифровку того, что делает запрос.


EDIT

Просмотрев еще раз, я вижу, что нет никакой необходимости в представлении инлайн. (Это был сгенерирован из подзапроса во время моего первоначального изменения в операции JOIN, но это на самом деле не нужно

Это должно вернуть эквивалентный результат:.

 SELECT e.event_id 
     FROM events_words e 
     JOIN words w 
      ON w.id = e.word_id 
     WHERE e.generated > '#{starting_time.to_s(:db)}' 
      AND w.text IN ('#{terms.join("', '")}') 
     GROUP BY e.event_id 
     HAVING COUNT(DISTINCT(e.word_id))=#{terms.count} 
+0

Спасибо, я опробовать присоединиться и посмотреть, как это работает для исполнения! –

+0

@DavidHoelzer: Я надеюсь, что кто-то еще сможет вам помочь с повторной записью ActiveRecord. (Я действительно не помог ответить на заданный вами вопрос.) И, возможно, AR-запрос не будет таким ужасным, как я думаю, это будет так. (Я бы хотел поверить, что был бы элегантный способ выразить запрос, который вы хотите запустить, но у меня нет никаких доказательств, подтверждающих такое убеждение.) Используйте «EXPLAIN», чтобы увидеть план запроса. И убедитесь, что доступны подходящие индексы, например, «ON event_words (event_id, word_id, сгенерировано)» и «ON words (text, id)». – spencer7593

0

Вы можете попробовать это:

EventWord.joins(:word). 
      where(:words => {:text => terms}). 
      where("generated > ?", :starting_time). 
      group(:event_id). 
      having("count(distinct(word_id)) = ?", terms.count). 
      select(:event_id) 

Или ...

Event.joins(:word). 
     where(:words => {:text => terms}). 
     where("generated > ?", :starting_time). 
     group(:id). 
     having("count(distinct(words.id)) = ?", terms.count) 
+0

Oooooo ... Это выглядит АРИС! Я дам Вам знать. –

+0

На самом деле это потребовало бы, чтобы в таблице соединений была модель, а это не так ... Как правило, они основаны на взаимоотношениях habtm в отдельных моделях ... Просто создание модели 'event_word.rb', наследующей от AR, будет не решая этого, я не думаю ...? –

+0

Возможно, попробуйте дополнительное выражение на основе событий. –

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