views:

48

answers:

1

My object model is given below and would like your inputs on the number of indexes to create for faster query responses (on h2, mysql). Assumptions and questions are given below the following model.

@Entity
@Table(name = "user")
public class User  {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_user_org_id")
    @Index(name = "idx_user_org_id")
    @JoinColumn(name = "org_id", nullable = false, referencedColumnName = "id")
    @NotNull
    private Organization organization;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_user_year_id")
    @Index(name = "idx_user_year_id")
    @JoinColumn(name = "year", nullable = false, referencedColumnName = "id")
    @NotNull
    private Year year;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_user_created_by")
    @Index(name = "idx_user_created_by")
    @JoinColumn(name = "created_by", nullable = false, referencedColumnName = "id")
    @NotNull
    private User createdBy;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "desc")
    private String desc;

    @Column(name = "is_system", length = LEN_1)
    @Type(type = "org.hibernate.type.YesNoType")
    private boolean isSystem = false;

    @Column(name = "user_type", nullable = false)
    private UserType userType;

    @Column(name = "status", nullable = false)
    @NotNull
    private Status status;

}

Our plan is to use multi column indexes instead of a single column index (i.e. create index user_idx based on (organization, year, isSystem, status, userType, createdBy)). Assuming I have this index, will I get optimized responses for my queries listed below.

  1. select * from user where organization=1 and year=2010;
  2. select * from user where organization=1 and year=2010 and isSytem=true or false; (i.e. system users or application defined users)
  3. select * from user where organization=1 and year=2010 and isSytem=false and userType=Manager (i.e. all managers)
  4. select * from user where organization=1 and year=2010 and isSytem=false and userType=Employee (i.e. all employees)
  5. select * from user where organization=1 and year=2010 and isSytem=false and userType=Manager and status=ACTIVE (i.e. Active users)
  6. select * from user where organization=1 and year=2010 and createdBy='Sam' or 'Joe' Does [6] need a different multi column index, consisting of the above 3 columns?

  7. Since we are creating a multi column index as per my original assumption, can I safely remove the individual indexes (idx_user_org_id, idx_user_year_id, idx_user_created_by) as currently defined in the model?

+2  A: 

You should switch the order of the columns in your index:

(organization, year, isSystem, userType, status, createdBy)

This allows it to better serve these two queries:

select * from user where organization=1 and year=2010 and isSystem=false and userType=Manager
select * from user where organization=1 and year=2010 and isSystem=false and userType=Employee

Does [6] need a different multi column index, consisting of the above 3 columns?

It doesn't need a new index - it can use the existing one but in a less efficient way - only the first two columns will be used. Adding a new index for this query looks like a good idea though.

can I safely remove the individual indexes

Yes. You should remove unused indexes otherwise they will just take up disk space and slow down table modifications without providing any benefit.

Mark Byers
Ok, as for as [6] is concerned if I create a multi column index using (organization, year, createdBy) this will be used instead of the previous index. Am I correct?
@user339108: Probably it will use that index, yes. You should run `EXPLAIN SELECT ...` to find out for sure.
Mark Byers
@Mark - I tried adding a new multi column index for resolving [6] and after that all queries seem to be using the new multi column index for queries mentioned from [1-5]. This doesn't seem correct though? Let me know, what I am missing here?
@user339108: Sometimes the difference in performance between two indexes is so small that it doesn't matter, in which case the MySQL optimizer may choose an index which is different from what you expected. Try timing the queries with the first index then with the second and see if there is a significant difference. If not, I wouldn't worry about it too much.
Mark Byers