SQL Server Performance Forum – Threads Archive
Optimizer not using our indexes
Description of problem.<br />We have in the Database table ConsumerListing with a number of<br />searchable<br />columns. We can not predict the combination of search conditions.<br />Because of<br />that we chose to create a number of one-column non-clustered indexes.<br /><br />Two types of searches are being performed on the table.<br />Type 1: we need to access all records which satisfy certain conditions.<br />In<br />our example people who Dogs and interested in Gardening in the household.<br />Type 2 we need to access records which satisfy certain conditions and<br />have<br />certain phone numbers. To achieve that we decided in addition to<br />one-column<br />non-clustered indexes to create indexes with keys AreaCode, Phone and<br />add<br />all the other search conditions on the leaf level of non clustered index<br />(included columns new for SQL Server 2005).<br /><br />We decided to test query<br />select count(*) from ConsumerListing<br />where<br />Dogs=’Y’ AND Gardner=’Y'<br />It took long. Query optimizer issued following execution plan:<br />StmtText<br />————————————————————————<br />—-<br />————————————————————————<br />—-<br />———————————————–<br /> |–Compute<br />Scalar(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’












How many possible values can you have in the "Dogs" column (or any such column)> Two, I guess, since you say they have low selectivity? At first glance, I would imagine that is the problem. The optimizer is not likely to choose an index over a scan when the index is not selective.
I know most likely it is the reason, but
1.Why it is using index in case of search of just one condition. Index has low selectivity as well.
2.Besides index hints for each query is it any global setting we can use to push server to desired behavior
Thank you.
– just a little remark regarding your tests :
Like you stated (correctly) you performed :
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET STATISTICS IO ON
SET STATISTICS TIME ONResulsts for SET STATISTICS TIME ON SQL Server Execution Times:
CPU time = 36266 ms, elapsed time = 396475 ms.–default
Did you also perform
the DBCC DROPCLEANBUFFERS and DBCC FREEPROCCACHE
before you executed your test with the hints ?
resulting to CPU time = 19032 ms, elapsed time = 19245 ms.–with index hints
[?] – dogs=’y’ … meaning you have a Y-N index ? cardinality plays a huge roll with indexes. You can force it using a hint, but there may be better ways to implement it not using just a two-valued index …. thinking out of the box.
Did you also perform
the DBCC DROPCLEANBUFFERS and DBCC FREEPROCCACHE
before you executed your test with the hints ?
Yes I run DBCC DROPCLEANBUFFERS and DBCC FREEPROCCACHE before test with hints.
dogs=’y’ … meaning you have a Y-N index ? cardinality plays a huge roll with indexes. You can force it using a hint, but there may be better ways to implement it not using just a two-valued index …. thinking out of the box.
Y and U(unknown) to be exact.
Of course two column index will be more efficient. The challenge is that we have around 170 search conditions and combinations are not predictable. That#%92s why we choose to use bunch of one-valued indexes.
Thank you.
"select count(*)" probably is not a good indicator for this reason: Count(*) simply has to count qualifying rows, not return any data; as such, the optimizer is likely to choose to scan the smallest index available that can produce the "where" clause results (even when the selectivity is so low), which is indeed your one-column index. In usage where data needs to be returned from any other column, or where any join is needed, it probably won’t behave that way. I know of no way around the cardinality problem except to break your data out in some other way than binary columns, or perhaps partitioning the table.
… around 170 search conditions …
Should they all be dynamic ?
At first … maybe yes
Maybe you may want to examine this predicate-load and then determine there wich are the most used and maybe even come to a conclusion that there a pattern use-case so you can develop a couple of scenarios with tuned fixed combinations …
well whatever was performance, the drop clean buffers did not take effect before the second query because you can clearly see that both indexes were in memory the net is the default plan was 36 cpu-sec, compared with 19 for the hinted plan,
just to be fair, run the default with OPTION (MAXDOP 1) to get a non-parallel plan comparison what you are seeing is a discrepancy between the optimizer cost formulas and the true cost in any case, the hinted plan is not that efficient either at 19 cpu-sec,
is a throughput of 3 searches/min per proc acceptable, with no other activity i think you need consider some mandatory search conditions, ie, no single bit field searches
and build compound indexes to match requirements
]]>