All Projects → gregnavis → Active_record_doctor

gregnavis / Active_record_doctor

Licence: mit
Identify database issues before they hit production.

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Active record doctor

Query track
Find time-consuming database queries for ActiveRecord-based Rails Apps
Stars: ✭ 258 (-70.17%)
Mutual labels:  database, rails, performance
Rein
Database constraints made easy for ActiveRecord.
Stars: ✭ 657 (-24.05%)
Mutual labels:  activerecord, database, rails
Zero downtime migrations
Zero downtime migrations with ActiveRecord 3+ and PostgreSQL
Stars: ✭ 513 (-40.69%)
Mutual labels:  activerecord, database, rails
Activerecord Clean Db Structure
Automatic cleanup for the Rails db/structure.sql file (ActiveRecord/PostgreSQL)
Stars: ✭ 101 (-88.32%)
Mutual labels:  activerecord, database, rails
Seamless database pool
Add support for master/slave database clusters in ActiveRecord to improve performance.
Stars: ✭ 222 (-74.34%)
Mutual labels:  activerecord, database, rails
Counter culture
Turbo-charged counter caches for your Rails app.
Stars: ✭ 1,397 (+61.5%)
Mutual labels:  activerecord, database, rails
Activerecord Sqlserver Adapter
SQL Server Adapter For Rails
Stars: ✭ 910 (+5.2%)
Mutual labels:  activerecord, database, rails
Scenic
Scenic is maintained by Derek Prior, Caleb Hearth, and you, our contributors.
Stars: ✭ 2,856 (+230.17%)
Mutual labels:  activerecord, database, rails
Database validations
Database validations for ActiveRecord
Stars: ✭ 274 (-68.32%)
Mutual labels:  activerecord, database, performance
Maghead
The fastest pure PHP database framework with a powerful static code generator, supports horizontal scale up, designed for PHP7
Stars: ✭ 483 (-44.16%)
Mutual labels:  database, performance
Activerecord Multi Tenant
Rails/ActiveRecord support for distributed multi-tenant databases like Postgres+Citus
Stars: ✭ 526 (-39.19%)
Mutual labels:  activerecord, rails
Prosopite
🔍 Rails N+1 queries auto-detection with zero false positives / false negatives
Stars: ✭ 555 (-35.84%)
Mutual labels:  rails, performance
Order query
Find next / previous Active Record(s) in one query
Stars: ✭ 472 (-45.43%)
Mutual labels:  activerecord, rails
Stateful enum
A very simple state machine plugin built on top of ActiveRecord::Enum
Stars: ✭ 546 (-36.88%)
Mutual labels:  activerecord, rails
Attribute normalizer
Adds the ability to normalize attributes cleanly with code blocks and predefined normalizers
Stars: ✭ 473 (-45.32%)
Mutual labels:  activerecord, rails
Activerecord Jdbc Adapter
JRuby's ActiveRecord adapter using JDBC.
Stars: ✭ 457 (-47.17%)
Mutual labels:  activerecord, rails
Github Ds
A collection of Ruby libraries for working with SQL on top of ActiveRecord's connection
Stars: ✭ 597 (-30.98%)
Mutual labels:  activerecord, rails
Unread
Handle unread records and mark them as read with Ruby on Rails
Stars: ✭ 638 (-26.24%)
Mutual labels:  activerecord, rails
Mobility
Pluggable Ruby translation framework
Stars: ✭ 644 (-25.55%)
Mutual labels:  activerecord, rails
Libmdbx
One of the fastest embeddable key-value ACID database without WAL. libmdbx surpasses the legendary LMDB in terms of reliability, features and performance.
Stars: ✭ 729 (-15.72%)
Mutual labels:  database, performance

Active Record Doctor

Active Record Doctor helps to keep the database in a good shape. Currently, it can:

More features coming soon!

Want to suggest a feature? Just shoot me an email.

Build Status

Installation

The preferred installation method is adding active_record_doctor to your Gemfile:

gem 'active_record_doctor', group: :development

Then run:

bundle install

Usage

Indexing Unindexed Foreign Keys

Foreign keys should be indexed unless it's proven ineffective. However, Rails makes it easy to create an unindexed foreign key. Active Record Doctor can automatically generate database migrations that add the missing indexes. It's a three-step process:

  1. Generate a list of unindexed foreign keys by running
bundle exec rake active_record_doctor:unindexed_foreign_keys > unindexed_foreign_keys.txt
  1. Remove columns that should not be indexed from unindexed_foreign_keys.txt as a column can look like a foreign key (i.e. end with _id) without being one.

  2. Generate the migrations

rails generate active_record_doctor:add_indexes unindexed_foreign_keys.txt
  1. Run the migrations
bundle exec rake db:migrate

Removing Extraneous Indexes

Let me illustrate with an example. Consider a users table with columns first_name and last_name. If there are two indexes:

  • A two-column index on last_name, first_name.
  • A single-column index on last_name.

Then the latter index can be dropped as the former can play its role. In general, a multi-column index on column_1, column_2, ..., column_n can replace indexes on:

  • column_1
  • column_1, column_2
  • ...
  • column_1, column_2, ..., column_(n - 1)

To discover such indexes automatically just follow these steps:

  1. List extraneous indexes by running:
bundle exec rake active_record_doctor:extraneous_indexes
  1. Confirm that each of the indexes can be indeed dropped.

  2. Create a migration to drop the indexes.

The indexes aren't dropped automatically because there's usually just a few of them and it's a good idea to double-check that you won't drop something necessary.

Also, extra indexes on primary keys are considered extraneous too and will be reported.

Note that a unique index can never be replaced by a non-unique one. For example, if there's a unique index on users.login and a non-unique index on users.login, users.domain then the tool will not suggest dropping users.login as it could violate the uniqueness assumption.

Detecting Unindexed deleted_at Columns

If you soft-delete some models (e.g. with paranoia) then you need to modify your indexes to include only non-deleted rows. Otherwise they will include logically non-existent rows. This will make them larger and slower to use. Most of the time they should only cover columns satisfying deleted_at IS NULL.

active_record_doctor can automatically detect indexes on tables with a deleted_at column. Just run:

bundle exec rake active_record_doctor:unindexed_deleted_at

This will print a list of indexes that don't have the deleted_at IS NULL clause. Currently, active_record_doctor cannot automatically generate appropriate migrations. You need to do that manually.

Detecting Missing Foreign Key Constraints

If users.profile_id references a row in profiles then this can be expressed at the database level with a foreign key constraint. It forces users.profile_id to point to an existing row in profiles. The problem is that in many legacy Rails apps the constraint isn't enforced at the database level.

active_record_doctor can automatically detect foreign keys that could benefit from a foreign key constraint (a future version will generate a migrations that add the constraint; for now, it's your job). You can obtain the list of foreign keys with the following command:

bundle exec rake active_record_doctor:missing_foreign_keys

The output will look like:

users profile_id
comments user_id article_id

Tables are listed one per line. Each line starts with a table name followed by column names that should have a foreign key constraint. In the example above, users.profile_id, comments.user_id, and comments.article_id lack a foreign key constraint.

In order to add a foreign key constraint to users.profile_id use the following migration:

class AddForeignKeyConstraintToUsersProfileId < ActiveRecord::Migration
  def change
    add_foreign_key :users, :profiles
  end
end

Detecting Models Referencing Undefined Tables

Active Record guesses the table name based on the class name. There are a few cases where the name can be wrong (e.g. you forgot to commit a migration or changed the table name). Active Record Doctor can help you identify these cases before they hit production.

IMPORTANT. Models backed by views are supported only in:

  • Rails 5+ and any database or
  • Rails 4.2 with PostgreSQL.

The only think you need to do is run:

bundle exec rake active_record_doctor:undefined_table_references

If there a model references an undefined table then you'll see a message like this:

The following models reference undefined tables:
  Contract (the table contract_records is undefined)

On top of that rake will exit with status code of 1. This allows you to use this check as part of your Continuous Integration pipeline.

Detecting Uniqueness Validations not Backed by an Index

A model-level uniqueness validations should be backed by a database index in order to be robust. Otherwise you risk inserting duplicate values under heavy load.

In order to detect such validations run:

bundle exec rake active_record_doctor:missing_unique_indexes

If there are such indexes then the command will print:

The following indexes should be created to back model-level uniqueness validations:
  users: email

This means that you should create a unique index on users.email.

Detecting Missing Non-NULL Constraints

If there's an unconditional presence validation on a column then it should be marked as non-NULL-able at the database level.

In order to detect columns whose presence is required but that are marked null: true in the database run the following command:

bundle exec rake active_record_doctor:missing_non_null_constraint

The output of the command is similar to:

The following columns should be marked as `null: false`:
  users: name

You can mark the columns mentioned in the output as null: false by creating a migration and calling change_column_null.

Detecting Missing Presence Validations

If a column is marked as null: false then it's likely it should have the corresponding presence validator.

In order to detect models lacking these validations run:

bundle exec rake active_record_doctor:missing_presence_validation

The output of the command looks like this:

The following models and columns should have presence validations:
  User: email, name

This means User should have a presence validator on email and name.

Detecting Incorrect Presence Validations on Boolean Columns

A boolean column's presence should be validated using inclusion or exclusion validators instead of the usual presence validator.

In order to detect boolean columns whose presence is validated incorrectly run:

bundle exec rake active_record_doctor:incorrect_boolean_presence_validation

The output of the command looks like this:

The presence of the following boolean columns is validated incorrectly:
  User: active

This means active is validated with presence: true instead of inclusion: { in: [true, false] } or exclusion: { in: [nil] }.

Ruby and Rails Compatibility Policy

The goal of the policy is to ensure proper functioning in reasonable combinations of Ruby and Rails versions. Specifically:

  1. If a Rails version is officially supported by the Rails Core Team then it's supported by active_record_doctor.
  2. If a Ruby version is compatible with a supported Rails version then it's also supported by active_record_doctor.
  3. Only most recent teeny Ruby versions and patch Rails versions are supported.

Author

This gem is developed and maintained by Greg Navis.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].