Use type column first in multi-column indexes #14143

Merged
merged 1 commit into from Oct 27, 2014

Projects

None yet

5 participants

@derekprior

add_reference can very helpfully add a multi-column index when you use
it to add a polymorphic reference. However, the first column in the
index is the id column, which is less than ideal.

The PostgreSQL docs say:

A multicolumn B-tree index can be used with query conditions that
involve any subset of the index's columns, but the index is most
efficient when there are constraints on the leading (leftmost)
columns.

The MySQL docs say:

MySQL can use multiple-column indexes for queries that test all the
columns in the index, or queries that test just the first column, the
first two columns, the first three columns, and so on. If you specify
the columns in the right order in the index definition, a single
composite index can speed up several kinds of queries on the same
table.

In a polymorphic relationship, the type column is much more likely to be
useful as the first column in an index than the id column. That is, I'm
more likely to query on type without an id than I am to query on id
without a type.

@sorentwo

This looks straight forward and helpful to me. Nicely documented commit as well. 👍

@rafaelfranca
Member

This depends of your usage. Usually you do PolymorphicClass.find(id), since id is unique.

It would be hard to change this to something that please everyone, so I think we should keep as it is.

@derekprior

This depends of your usage. Usually you do PolymorphicClass.find(id), since id is unique.

And the change here does not impact that use case at all.

It would be hard to change this to something that please everyone, so I think we should keep as it is.

In what circumstance would you ever want to find a record that has a specific polymorphic_id column without either restricting that by the record's id column or by the polymorphic_type column. I honestly can't think of a single use case for that behavior.

Conversely, I can think of plenty of times where I'd want to find all records of a certain polymorphic_type regardless of the polymorphic_id.

@rafaelfranca
Member

We will need a CHANGELOG entry for this change

@derekprior

@rafaelfranca Changelog added and rebased against master.

@senny senny commented on an outdated diff Aug 13, 2014
activerecord/CHANGELOG.md
* `create_join_table` removes a common prefix when generating the join table.
This matches the existing behavior of HABTM associations.
+* Make possible to change `record_timestamps` inside Callbacks.
@senny
senny Aug 13, 2014 Ruby on Rails member

this entry doesn't look related.

@senny
Member
senny commented Aug 13, 2014

This only fixes it half way. We also need to patch the references method. There is also test-case for this.

@senny senny commented on an outdated diff Aug 13, 2014
...erecord/test/cases/migration/references_index_test.rb
@@ -93,7 +93,7 @@ def test_creates_polymorphic_index_for_existing_table
t.references :foo, :polymorphic => true, :index => true
end
- assert connection.index_exists?(table_name, [:foo_id, :foo_type], :name => :index_testings_on_foo_id_and_foo_type)
+ assert connection.index_exists?(table_name, [:foo_type, :foo_id], :name => :index_testings_on_foo_type_and_foo_id)
@senny
senny Aug 13, 2014 Ruby on Rails member

can you change it to Ruby 1.9 Hash syntax?

@derekprior derekprior Use type column first in multi-column indexes
`add_reference` can very helpfully add a multi-column index when you use
it to add a polymorphic reference. However, the first column in the
index is the `id` column, which is less than ideal.

The [PostgreSQL docs][1] say:
> A multicolumn B-tree index can be used with query conditions that
> involve any subset of the index's columns, but the index is most
> efficient when there are constraints on the leading (leftmost)
> columns.

The [MySQL docs][2] say:
> MySQL can use multiple-column indexes for queries that test all the
> columns in the index, or queries that test just the first column, the
> first two columns, the first three columns, and so on. If you specify
> the columns in the right order in the index definition, a single
> composite index can speed up several kinds of queries on the same
> table.

In a polymorphic relationship, the type column is much more likely to be
useful as the first column in an index than the id column. That is, I'm
more likely to query on type without an id than I am to query on id
without a type.

[1]: http://www.postgresql.org/docs/9.3/static/indexes-multicolumn.html
[2]: http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html
9cdd0a1
@derekprior

@senny, ready for another look. /cc @sgrif

@senny
Member
senny commented Oct 27, 2014

@derekprior thank you 💛

@senny senny merged commit 9cdd0a1 into rails:master Oct 27, 2014

1 check passed

Details continuous-integration/travis-ci The Travis CI build passed
@derekprior derekprior deleted the derekprior:dp-compound-index-ordering branch Apr 9, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment