Need two indexes on a HABTM join table?

前端 未结 3 1684
忘了有多久
忘了有多久 2021-01-31 15:37

A simple has_and_belongs_to_many association:

Person has_and_belongs_to_many :products
Product has_and_belongs_to_many :persons

Ar

相关标签:
3条回答
  • 2021-01-31 16:05

    Close - you most likely want the following:

    add_index :person_products, [:person_id, :product_id], :unique => true
    add_index :person_products, :product_id
    

    The :unique => true is not strictly required and it depends whether or not it makes sense to have a person associated with a product multiple times. I would say if you're not sure, you probably do want the :unique flag.

    The reason for the index structure is that all modern databases can execute queries on both person_id and product_id using the first index regardless of the order specified in a query. E.g.

    SELECT foo FROM bar WHERE person_id = 1 AND product_id = 2
    SELECT foo FROM bar WHERE product_id = 2 AND person_id = 1
    

    are treated as the same and the database is smart enough to use the first index.

    Likewise, queries using only person_id can also be run using the first index. Multi-column b-tree indexes can use fewer columns than they have provided they are specified from the left of the original declaration.

    For queries using only product_id, this cannot be executed against the first index (since that index is defined with person_id in the leftmost position). Hence you need a separate index to enable lookups on that field alone.

    The multi-column b-tree index property also extends to indexes with higher numbers of columns. If you had an index on (person_id, product_id, favorite_color, shirt_size), you could use that index to run queries using person_id, (person_id, product_id), etc, so long as the order matches the definition.

    0 讨论(0)
  • 2021-01-31 16:14

    Yes they are helpful. But do you really need them? It all depends on what you're gonna do with it. Index on (person_id,product_id) will allow you to quickly find products belonging to person but will not help finding persons that own certain product. It will also enforce UNIQUE so you probably should use it. separate indexes on (person_id) and (product_id) will allow you to find both products belonging to person and persons that own certain product. Indices on (person_id,product_id) and (product_id,person_id) will work for both cases too and will be faster but will take more space and there will take a little bit (very little) more when inserting/updating rows. The time and space overhead is almost always worth it unless you have a base where you write more often than read. Personally I've seen Index Only Scans in 9.2 benefit greatly from two indexes on both columns. So you the real choice is between:

    unique index on (col 2, col 1), unique index on (col 1, col 2)

    and

    unique Index on (col 1, col 2), index on (col 2)

    0 讨论(0)
  • 2021-01-31 16:17

    You just need one, unless you are doing unique

    add_index :person_products, :person_id
    add_index :person_products, :product_id
    

    Or for an index on both columns

    add_index :person_products, [:person_id, :product_id]
    

    This will help performance when querying on those columns on the database. It will depend on your query if it includes both columns or just one.

    http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index

    0 讨论(0)
提交回复
热议问题