My first answer was "Yes, it's a good practice to do that". But the question kept hanging in my head: is it REALLY necessary to do so? So I went directly to the MSSMS to find out.
This is the scenario:
(Yes, no FK between them, and cannot be created because there were Child.ParentId that had no corresponding Parent.ParentId, strangely. No, the affected rows cannot be deleted)
Table Child (3.8m rows approx)
Index_name | Index_description | Index_keys |
IX_Child_Description | nonclustered located on PRIMARY | Description |
PK_Child | clustered, unique, primary key located on PRIMARY | ChildID |
Table Parent (5.6 m rows approx)
Index_name | Index_description | Index_keys |
IX_Parent_Description | nonclustered located on PRIMARY | Description |
The query was similar to this one:
select * from Child c inner join Parent p on p.ParentID = c.ParentID where p.Description = 'XXXXXXXXXXX'So, as you can see the predicate is filtering the Parent table only. Let's see the resulting execution plan for this query:
There is a Index Scan being done on the Child table, because there is no index on the Child.ParentId column (Even the MSSMS suggests creating an index on that column). Let's first create and index on Parent.ParentID then, and re execute the query:
create unique clustered index PX_Parent on Parent(ParentId)
create index IX_Child_ParentId on Child(ParentId)
Now, an Index Seek on the new index is being done. So, both indexes were used. In this scenario, creating both was useful. Ok, so far, I've said nothing new. But, what if I change the query like this:
select * from Child c inner join Parent p on p.ParentID = c.ParentID where c.Description = 'XXXXXXXXXXX'So instead of filtering on the Parent table, I filter on the Child table. Is the index on Child.ParentId still useful? Let see...
No, the new index was not used. So, should I drop it, the execution plan should remain the same:
drop index Child.IX_Child_CommonIdThe resulting execution plan:
Summarizing, creating indexes on both tables when joining is a good practice, yes, but not always practical. If the scenario would have been the second query, creating an index only in the Parent.ParentId table would have solved the problem. Have in mind that this could differ depending on the rows on the table, statistics, different predicates, etc...
No comments:
Post a Comment