3

I have a question concerning best-practices for indexing in SQL Server (or any RDBMS for that matter). Take the following table:

ProfileID int
Text      nvarchar(50)

ProfileID is joined to a Profile table. For each profile, each Text must be unique. Therefore I put a Primary cover key on both columns. Fine.

However, I also want to be able to query the above table by ProfileID. So I also put an index on ProfileID too.

This means I have an overlapping index. I don't know if this is a total waste since there is a cover index already, or if it's correct since the cover index would be a hash of the two columns (or am I misunderstanding cover indexes)?

Edit:

I created the index in the order (ProfileID, Text). What if, for argument's sake, there were 3 columns A, B, and C, that had a cover index over all 3. Would it only benefit if we queried against "A" or "A, B, and C", but not "B", or "C", or "B and C"?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
IamIC
  • 17,747
  • 20
  • 91
  • 154

1 Answers1

5

An index on (ProfileID, Text) (in this order) is an index on ProfileID as well.

You may still want to create an additional index on ProfileID only, if you want greater SELECT performance on queries that do not involve Text.

However, this has two drawbacks:

  1. Maintaining two indexes requires more resources and performance of DML queries (INSERT, UPDATE, DELETE) may suffer

  2. If you mix queries of the two types, both indexes will occupy the cache and there can be more cache misses than with a single index.

    It is not a problem if your table is small enough to fit into the cache along with both indexes.

The cover index would be a hash of the two columns (or am I misunderstanding cover indexes)?

A truly covering index would be created this way:

CREATE INDEX ix_mytable_profile__text ON mytable (ProfileID) INCLUDE (Text)

This way, Text would only be stored in leaf-level nodes of the index.

However, since you need a UNIQUE index, both columns need to be parts of the key. The nodes are sorted lexicographically on ProfileID then Text.

I created the index in the order (ProfileID, Text). What if, for argument's sake, there were 3 columns A, B, and C, that had a cover index over all 3. Would it only benefit if we queried against "A" or "A, B, and C", but not "B", or "C", or "B and C"?

CREATE INDEX ix_mytable_a_b_c ON mytable (a, b, c)

SELECT  a, b, с
FROM    mytable
WHERE   a = 1 

-- Index lookup, no table lookup. a is leading

SELECT  a, b, с
FROM    mytable
WHERE   a = 1
        AND b = 1

-- Index lookup, no table lookup. (a, b) are leading.

SELECT  a, b, с
FROM    mytable
WHERE   b = 1

-- Index full scan (`b` is not leading), no table lookup

SELECT  a, b, с
FROM    mytable
WHERE   c = 1

-- Index full scan (`c` is not leading), no table lookup

SELECT  a, b, с, d
FROM    mytable
WHERE   a = 1

-- Index lookup, table tookup (d is not a part of the index).

SELECT  a, b, с, d
FROM    mytable
WHERE   b = 1

-- Table full scan (there is no point in using index at all, neither for lookup nor for covering).
Community
  • 1
  • 1
Quassnoi
  • 413,100
  • 91
  • 616
  • 614
  • @Quassnoi It sounds like you're saying the cover index will *partly* help a query against ProfileID, but not as well as an independent index on this column would. – IamIC Nov 11 '10 at 12:59
  • @IanC: the composite index will be larger in size and it *may* take additional time to traverse it. Since fewer nodes fit into one page, the index depth may be larger. It may take `5` page lookups to find a node with the composite index where only `2` or `3` would suffice with a simple one. – Quassnoi Nov 11 '10 at 13:04
  • Also note that what you create is not a covering index in the strict sense. In a covering index, the covered columns are not sorted or used in lookups. – Quassnoi Nov 11 '10 at 13:05
  • @Quassnoi So the composite index (cover index) isn't a hash of the columns, but is actually the data, making it possible to efficiently search the first or all columns. Is that correct? – IamIC Nov 11 '10 at 13:06
  • @IanC: the main goal of the covering index is to avoid the table lookup. If you use fields other than `ProfileID` and `Text` in your query, the table lookup will happen anyway. Also note that composite index and covering index are not the same. In a composite index, there is more than one **key** column, in a covering index there can be only one key column. – Quassnoi Nov 11 '10 at 13:09
  • @Quassnoi Oh, so a cover index is simply an index on a non-key column. I wish documentation would make it clearer. – IamIC Nov 11 '10 at 13:16
  • 2
    @IanC: http://msdn.microsoft.com/en-us/library/ms188783.aspx and look section `G`. As for me, it's pretty clear. – Quassnoi Nov 11 '10 at 13:17
  • @Quassnoi That MSDN document doesn't contain the term "cover index". This is why I've been having a hard time trying to figure out what they are. But I get it on composite indexes, thank you. – IamIC Nov 11 '10 at 13:26
  • @IanC: probably because it's *covering*? :) – Quassnoi Nov 11 '10 at 13:28
  • @Quassnoi LOL! http://msdn.microsoft.com/en-us/library/ms190806.aspx fascinating!! You've been a great help. Thanks so much! – IamIC Nov 11 '10 at 13:36