The key to using a multi-column index is for the query to be what is called Sargable, which comes from S earch Arg ument able. Multi-column indexes are sorted primarily by the first column, with ties being sorted by the second column, etc.
In logical order, a three column index would be sorted like this:
first second third
1 1 1
1 1 2
1 1 3
1 2 1
1 5 2
2 1 5
2 2 1
So, in order to seek to a specific part of the index, the query has to have a value for the first column, and to use the second column in the index, it has to have an exact value for the first column.* If a column has an inequality or range filter, then it can use the index for that column, but not for any columns after that.
From looking at the query, we can tell that if the index was used, it was a full scan, meaning it wasn't really used as an index. You can view the execution plan and look for seek vs scan to tell for sure. Subsequent runs would be faster because the data is cached in memory, so it doesn't have to read it from disk again.
Looking at your query, you have client_acct
and letter_type
as exact comparisons, so I would use those as the first two columns, the more selective one first, so I'd think client_acct
. For the third column, I would guess that letter_date
would be more selective, so I suggest that. I would also INCLUDE
the letter_balance
column on the index so that it can filter rows that don't fit, even if it can't seek to those rows. Also, there are multiple ways that SQL can execute the query, so this isn't necessarily the best possible index, but I'd expect it to be reasonably good.
It isn't clear where total_payments
and sum_payments
are coming from, but I'm going to assume that they come from the client
side. In this case the index is covering, which means that the query can get all of the information that it needs from the index and never needs to look back and the main table.
*True for SQL Server. Some RDMS's can make use of an index even if an earlier column isn't exact, but it is still best to be exact if possible.