Skip to content

Instantly share code, notes, and snippets.

@fncr-dev
Last active November 14, 2017 13:24
Show Gist options
  • Select an option

  • Save fncr-dev/ca6ec70567af1af1f627748ca7866fbe to your computer and use it in GitHub Desktop.

Select an option

Save fncr-dev/ca6ec70567af1af1f627748ca7866fbe to your computer and use it in GitHub Desktop.
Optimisation Ruby On Rails Application

Optimisation Ruby On Rails Application

Rails database best practices

Write efficient and chainable scopes:

  • Return an ActiveRecord::Relation.
  • Filter data in the database.
  • Sort in the database.
  • Ordering out of scopes.

Reduce calls to the database:

  • Using .joins(), .includes() sometimes you will have to use .having(), .group() and in some cases, write some straight up SQL.

Use indexes:

  • Add an index on every id column as well as any column that is used in a where clause.

Use query objects for complicated queries:

def relation
  user_ids = GroupUser.select(:user_id).where(activated: true)
  User.where(id: user_ids)
end
SELECT users.* 
FROM users 
WHERE users.id 
IN (
  SELECT group_users.user_id 
  FROM group_users 
  WHERE group_users.activated = 't'
)

Avoid queries outside of scopes and query qbjects:

  • Query embedded in a controller (or view, task, etc) is harder to test in isolation and cannot be reused.

Use the right types:

  • Use the citext when need to comparisons be case-insensitive.
  • Avoid varchar, char, and anything else use text type.
  • Use the array type when need store tags, keywords in case when separate table and join table looks like overkill.
  • When need a globally unique ID use UUID type.
  • In case when need a NoSQL DB or store JSON blob use one of the jsonb type.

Active Record:

  • Use an enum attribute where the values map to integers in the database, but can be queried by name.
  • Don't user .not method, it's don't use indexes.
  • Don't initialize ActiveRecord Objects in case when it is useless.

Sidekiq asynchronous process

Make your job parameters simple:

UserWorker.perform_async(user_id)
  • The arguments that you pass should be composed of simple JSON datatypes.

Write idempotent and transactional jobs:

  • Your job can safely execute multiple times.

Concurrency and Queue:

  • Sidekiq process at a queue with a defined number of threads, configure you connection pool correct.
  • When you have multiple instance of sidekiq run each instance in uniq queue.

Common practices:

  • Use single responsibility and interface segregation principle when you plan your jobs.
  • Use delayed extensions it provide a very easy and simple way to make method calls asynchronous.

Denormalisations

  • Use elasticsearch to store and work with denormalized data.
  • Use jsonb or array to store denormalized data in table to reduce count of db queries.
  • Use extenders to avoid store denormalized data in db but it help to reduce count of db queries in spesific situations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment