Пользовательский запрос ActiveRecord против загрузки find_by_sql - PullRequest
3 голосов
/ 22 февраля 2011

У меня есть пользовательский запрос, который выглядит следующим образом

self.account.websites.find(:all,:joins => [:group_websites => {:group => :users}],:conditions=>["users.id =?",self])

где self - это пользователь объект

Мне удается сгенерировать эквивалент SQL для того же

Вот как это выглядит

sql = "select * from websites INNER JOIN group_websites on group_websites.website_id = websites.id INNER JOIN groups on groups.id = group_websites.group_id INNER JOIN group_users ON (groups.id = group_users.group_id) INNER JOIN users on (users.id = group_users.user_id) where (websites.account_id = #{account_id} AND (users.id = #{user_id}))"

С приличным пониманием SQL и ActiveRecord Я предположил, что (с чем большинство согласится) результат, полученный из вышеупомянутого запроса, может занять больше времени по сравнению с результатом, полученным из find_by_sql (sql ) один .

но удивительно

Когда я запустил два вышеупомянутых Я нашел пользовательский запрос ActiveRecord, ведущий путь от ActiveRecord "find_by_sql" по времени загрузки вот результат теста

Время загрузки пользовательского запроса ActiveRecord

загрузка сайта (0,9 мс)

Колонки сайта (1,0 мс)

find_by_sql время загрузки

загрузка сайта (1,3 мс)

Колонки сайта (1,0 мс)

Я повторил тест снова и снова, и результат все равно остался прежним (пользовательский запрос выиграл битву)

Я знаю, что разница не так уж велика, но все же я просто не могу понять, почему обычный запрос find_by_sql медленнее, чем Custom Query

Может ли кто-нибудь поделиться этим светом?

В любом случае, спасибо

С уважением Вирен Неги

Ответы [ 2 ]

1 голос
/ 22 февраля 2011

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

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

Я думаю, что вы можете проверить это: попробуйте find_by_sql следующим образом (параметризовано):

User.find_by_sql(["select * from websites INNER JOIN group_websites on group_websites.website_id = websites.id INNER JOIN groups on groups.id = group_websites.group_id INNER JOIN group_users ON (groups.id = group_users.group_id) INNER JOIN users on (users.id = group_users.user_id) where (websites.account_id = ? AND (users.id = ?))", account_id, users.id])
0 голосов
/ 22 февраля 2011

Ну, причина, вероятно, довольно проста - с пользовательским SQL запрос SQL немедленно отправляется на сервер БД для выполнения. Помните, что Ruby - это интерпретируемый язык *1001*, поэтому Rails генерирует новый SQL-запрос на основе метаязыка ORM, который вы использовали, прежде чем его можно будет отправить на фактический сервер БД для исполнения. Я бы сказал, что дополнительные 0,1 мс - это время, затрачиваемое платформой для генерации запроса.

...