19

When we add or remove a new index to speed up something, we may end up slowing down something else. To protect against such cases, after creating a new index I am doing the following steps:

  1. start the Profiler,
  2. run a SQL script which contains lots of queries I do not want to slow down
  3. load the trace from a file into a table,
  4. analyze CPU, reads, and writes from the trace against the results from the previous runs, before I added (or removed) an index.

This is kind of automated and kind of does what I want. However, I am not sure if there is a better way to do it. Is there some tool that does what I want?

Edit 1 The person who voted to close my question, could you explain your reasons?

Edit 2 I googled up but did not find anything that explains how adding an index can slow down selects. However, this is a well known fact, so there should be something somewhere. If nothing comes up, I can write up a few examples later on.

Edit 3 One such example is this: two columns are highly correlated, like height and weight. We have an index on height, which is not selective enough for our query. We add an index on weight, and run a query with two conditions: a range on height and a range on weight. because the optimizer is not aware of the correlation, it grossly underestimates the cardinality of our query.

Another example is adding an index on increasing column, such as OrderDate, can seriously slow down a query with a condition like OrderDate>SomeDateAfterCreatingTheIndex.

A-K
  • 16,804
  • 8
  • 54
  • 74
  • Mmm. I can see how _some operations_ could slow down with added indexes. I don't expect _queries_ to be affected. I'd expect only locking operations (inserts, deletes, or explictely locking queries) to be affected, in the worst case. – sehe Sep 16 '11 at 21:08
  • @sehe: adding an index can slow down selects. It is not very likely but possible. – A-K Sep 16 '11 at 21:36
  • do you have a source reference on that? I suppose it would be with too many index pages being read and thrashing cache lines? Could you not (like with Oracle IIRC) hint at the SQL engine what indexes to use, and which to ignore? Explain plans are really helpful for that (so, static analysis, not profiling). – sehe Sep 16 '11 at 21:41
  • 2
    One obscure but potential scenario is when the new index is less optimal than the one previously used for a query, but the new one is chosen because of stale statistics, parameter sniffing or other factors that can lead the optimizer to the wrong index... – Aaron Bertrand Sep 17 '11 at 01:25
  • 3
    @sehe - [Here is a recent example](http://stackoverflow.com/questions/7481818/sql-why-is-select-count-mincol-maxcol-faster-then-select-mincol-max/7482342#7482342) where the availability of an index on `startdate` means that the select query is catastrophically worse than if the index wasn't there at all. – Martin Smith Sep 23 '11 at 09:47
  • @MartinSmith: Ah, of course; that's subtle but makes a lot of sense (TL;DR: indexes may alter the order in which records are visited and this _could_ alter the worst case performance of certain (aggregating) queries that formerly relied on 'seeing' the interesting records 'early' (or, perhaps, _not late_); That answer got my +1, very well spotted. Thx for the cross post here as well. – sehe Sep 23 '11 at 11:34
  • 1
    @sehe - And more worryingly you might hit a bug in the product too... [Incorrect Results Caused By Adding an Index](http://sqlblog.com/blogs/paul_white/archive/2013/08/21/incorrect-results-caused-by-adding-an-index.aspx) – Martin Smith Oct 12 '13 at 14:36

4 Answers4

8

Ultimately what you're asking can be rephrased as 'How can I ensure that the queries that already use an optimal, fast, plan do not get 'optimized' into a worse execution plan?'.

Whether the plan changes due to parameter sniffing, statistics update or metadata changes (like adding a new index) the best answer I know of to keep the plan stable is plan guides. Deploying plan guides for critical queries that already have good execution plans is probably the best way to force the optimizer into keep using the good, validated, plan. See Applying a Fixed Query Plan to a Plan Guide:

You can apply a fixed query plan to a plan guide of type OBJECT or SQL. Plan guides that apply a fixed query plan are useful when you know about an existing execution plan that performs better than the one selected by the optimizer for a particular query.

The usual warnings apply as to any possible abuse of a feature that prevents the optimizer from using a plan which may be actually better than the plan guide.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • 1
    Remus, I like this idea, so +1 from me. However, I am dealing with hundreds of modules, and looking for an easy an efficient way to monitor if they misbehave. Even if I freeze all my execution plans, I will still have to monitor if they still perform well - frozen plans may get out of date and become counter-productive. – A-K Sep 19 '11 at 13:38
1

How about the following approach:

  • Save the execution plans of all typical queries.
  • After applying new indexes, check which execution plans have changed.
  • Test the performance of the queries with modified plans.
Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
0

From the page "Query Performance Tuning"

Improve Indexes

This page has many helpful step-by-step hints on how to tune your indexes for best performance, and what to watch for (profiling).

As with most performance optimization techniques, there are tradeoffs. For example, with more indexes, SELECT queries will potentially run faster. However, DML (INSERT, UPDATE, and DELETE) operations will slow down significantly because more indexes must be maintained with each operation. Therefore, if your queries are mostly SELECT statements, more indexes can be helpful. If your application performs many DML operations, you should be conservative with the number of indexes you create.

Other resources:

However, it’s important to keep in mind that non-clustered indexes slow down the data modification and insertion process, so indexes should be kept to a minimum

Fragmented indexes and tables in SQL Server can slow down application performance. Here's a stored procedure that finds fragmented indexes in SQL servers and databases.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 2
    Thanks, but I am not asking about generic guidelines on index tuning. My question is about how to efficiently implement concrete steps to make sure these guidelines are met. As such, your answer does not match my question. – A-K Sep 19 '11 at 18:43
0

Ok . First off, index's slow down two things (at least)

-> insert/update/delete : index rebuild

-> query planning : "shall I use that index or not ?"

Someone mentioned the query planner might take a less efficient route - this is not supposed to happen.

If your optimizer is even half-decent, and your statistics / parameters correct, there is no way it's going to pick the wrong plan.

Either way, in your case (mssql), you can hardly trust the optimizer and will still have to check every time.

What you're currently doing looks quite sound, you should just make sure the data you're looking at is relevant, i.e. real use case queries in the right proportion (this can make a world of difference).

In order to do that I always advise to write a benchmarking script based on real use - through logging of production-env. queries, a bit like I said here :

Complete db schema transformation - how to test rewritten queries?

Community
  • 1
  • 1
Morg.
  • 697
  • 5
  • 7
  • Can you please tell me which RDBMS has an optimizer that always generates the perfect plan as implied by the first half of your answer? – Martin Smith Sep 27 '11 at 13:11
  • None at this point. However you can trust some Optimizers more than others for most basic tasks and the (WTF) cited here about MSSQL looks like it is related to either wrong stats/settings or just wrong optimizer. The PostgreSQL optimizer looks to me like it's pretty good for anything standard, and getting better every day, and in that sense, I would expect it to fail much less. "not supposed to happen" means it should not happen .. we all know how the result can differ from the intent. Half-decent optimizer may be something that does not exist, but again I have some trust in the pgsql one. – Morg. Sep 28 '11 at 11:32