2015-07-06 2 views
0

У меня есть приложение Rails, работающее на Heroku. У меня есть маршрут, ведущий к «домашней» контроллера и „действия ПРЕДЛОЖЕНИЙ“:Повысить производительность для загрузки 3000 записей с помощью Rails?

Rails.application.routes.draw do 
    get 'listings', to: 'home#listings' 

end 

Мой список действий:

class HomeController < ApplicationController 
    def listings 
     render json: MultiJson.dump({listings:Listing.all}) 
    end 

    ... 
end 

У меня есть таблица Тэг, содержащий 3000 записей Схема для. Перечисления стол:

create_table "listings", force: :cascade do |t| 
    t.integer "user_id",        null: false 
    t.boolean "deleted",    default: false, null: false 
    t.string "rent",         null: false 
    t.string "deposit",        null: false 
    t.string "availability",       null: false 
    t.string "min_duration",       null: false 
    t.string "male_count",       null: false 
    t.string "female_count",       null: false 
    t.string "longitude",       null: false 
    t.string "latitude",        null: false 
    t.string "location" 
    t.string "comments" 
    t.string "photos" 
    t.datetime "created_at",       null: false 
    t.datetime "updated_at",       null: false 
    end 

Когда запускаются 'Heroku журналы' Я вижу это:

Started GET "/listings.json" for 108.6.235.199 at 2015-07-06 14:08:02 +0000 
Processing by HomeController#listings as JSON 
    Parameters: {"home"=>{}} 
    Listing Load (34.3ms) SELECT "listings".* FROM "listings" 
Completed 200 OK in 3717ms (Views: 0.3ms | ActiveRecord: 40.4ms) 

Нормально ли это для 3,7 секунд для загрузки и рендеринга 3000 записей через json? Есть ли способ повысить производительность до порядка 100 миллисекунд? Почему это время ActiveRecord составляет 40.ms, а Views - 0,3 мс, но Completed is 3717ms? Было бы лучше использовать MongoDB вместо Postgres для хранения и загрузки записей со скоростью?

+0

Сначала вы должны узнать, какой слой добавляет накладные расходы. Что происходит, когда вы запускаете 'explain analysis select * из списков' в своем SQL-клиенте? Для чего это время выполнения? Он измеряет время выполнения запроса на стороне ** сервера **, исключая любые служебные данные сети или интерфейса. –

+0

Попробуйте поместить эти 3k записи HARDCODED в массив в вашем контроллере и посмотреть, сколько времени потребуется для его рендеринга. Это не вопрос производительности db. Для объектов 3k требуется время. – xlembouras

+2

Я хотел бы предложить вам начать использовать какую-то разбивку на страницы на стороне сервера. Почему вы когда-нибудь захотите отправить столько данных клиенту в любом случае? – Frost

ответ

4

Проблема не в сборе записей из БД, как показывает ваш журнал, он тратит только 40 мс в AR-процессе (3000 записей ничего не представляют для PG). Проблема заключается в сериализации записей 3k.

Я рекомендую использовать ActiveModel::Serializer, чтобы помочь оптимизировать процесс.

+0

Я тоже так думал - поэтому я вложил в фиктивный массив 3000 хэшей, и я получил это: «Завершено 200 OK в 929ms (Views: 0.2ms | ActiveRecord: 0.0ms) «Это почти на 3 секунды меньше - так что, конечно, выборка из базы данных ест много времени. Только 40 мс для вызова SQL, но еще 3 секунды для загрузки всех объектов во время выполнения. – etayluz

+2

Да, MultiJSON может сериализовать массив хэшей намного быстрее, чем объект ActiveRecord_Relation. Посмотрите на свой журнал: «Листинг Load (34.3ms)» SELECT «списки». * FROM «listings» 'Для получения записей из БД и других 4.1ms для возврата коллекции к контроллеру потребовалось всего 34,4 мс. Если вы заходите в консоль Rails, вы можете увидеть узкое место: получить список и установить локальную переменную, а затем запустить «Benchmark.measure {MultiJson.dump (перечисление: )}' – tagCincy

+0

Спасибо tagCincy, я сделал это но ничего не отображается: 2.2.1: 004?> listings = Listing.all 2.2.1: 005> listings.count (6.8ms) ВЫБОР COUNT (*) FROM "listings" => 3005 2.2.1 : 006> Benchmark.measure {MultiJson.dump (перечисление: листинги} 2.2.1: 007?> – etayluz

0

Я следил за сообщением @ tagCincy и узнал, что самый быстрый способ создания json всех записей в таблице базы данных - позволить базе данных (в данном случае Postgres) выполнять весь тяжелый подъем и разрешать Rails и Active Record Отдохни. Postgress поддерживает метод, называемый «row_to_json»

render json: MultiJson.dump({listings:ActiveRecord::Base.connection.execute("select row_to_json(listings) from listings;")}) 

Это приводит к улучшению в скорости 6х в производительности в этом случае, идущей от 3717ms до 644ms, как показано выше, в и под вопросом. На самом деле это даже лучше, потому что в этом примере я вытягиваю таблицу объявлений и пользователей, тогда как в вопросе это была только таблица списков, которую я получал.

> Started GET "/listings.json?data=(%0A%20%20%20%20settings,%0A%20%20%20%20listings,%0A%20%20%20%20users%0A)" for 108.6.235.199 at 2015-07-07 05:39:15 +0000 
> (31.5ms) select row_to_json(users) from users; 
>  Processing by HomeController#listings as JSON 
>  Parameters: {"data"=>"(\n settings,\n listings,\n users\n)", "home"=>{}} 
>  (121.9ms) select row_to_json(listings) from listings; 
>  Completed 200 OK in 644ms (Views: 0.3ms | ActiveRecord: 153.3ms) 
Смежные вопросы