Years ago someone said "Hey - why not drop auto-created stats, since the stats you need will just get created again and you'll end up getting rid of those you no longer need." That *may* be a reasonable step on some systems. If the risk of bad plans on first execution of a query needed stats that have been dropped is too high, its a bad deal. If the potential concurrent cost of auto-creating dropped stats is too high, that's a bad deal. What about analyzing query plans over some period of time to see which stats are actually used in those plans? Then auto-stats which aren't used in that set of plans could be dropped.
That type of stats analysis could have other uses, too. Prioritizing manual stats updates in regular maintenance comes to mind. Or, determining what stats to create/update on an Always On Availability Group primary based on secondary activity. And troubleshooting problem queries or identifying suspicious "watchlist" stats based on highly variable queries/plans they are involved with.
So I created this blog post almost 4 years ago. And now I'll plead with you to not use the query there... it's awful. If you want to query trace flag 8666 style stats from plan XML, please start from the query in this post instead - its much more well behaved 😊
Before I drop all those SQL Server auto-generated column stats....
In SQL Server 2016 SP2 and after, the optimizer stats consulted in compiling the plan are included in the plan XML without trace flag 8666.
Today, let's talk about the world before that.
If trace flag 8666 is set at the session level, a plan retrieved from plan cache will also include details for optimizer stats relevant to the plan in the XML. (Trace flag 8666 also includes other details.) The format is quite different than in SQL Server 2016 SP2 and later. If trace flag 8666 is set globally, plans in the Query Store will also contain the trace flag 8666 details. On a production server, I recommend targeted use of trace flag 8666 for investigation or troubleshooting purposes - please test very carefully for overhead if trace flag 8666 will be used globally.
So here I create a test table, with an integer column and an XML column. Today I'll insert a single plan for testing.
So here's the query...
And... it works!
Its fairly efficient, too. The results from "set statistics time on" for this test case are below. If parsing more plans, certainly the CPU time and elapsed time will increase.
I've got an upcoming workshop at TugaIT in July 2018... getting the most bang out of your buck for administrative tasks like stats updates is a topic on the docket!
TugaIT Summer 2018 Edition: Insight-Based Administration